yuanzhi_kuang 6 miesięcy temu
rodzic
commit
fa61419662
19 zmienionych plików z 2141 dodań i 552 usunięć
  1. 3 3
      websrc/com/kingdee/eas/custom/dormitorysystem/application/handler/CheckInApplicationListHandler.java
  2. 24 373
      websrc/com/kingdee/eas/custom/dormitorysystem/application/handler/RoomChangeApplicationEditHandler.java
  3. 6 6
      websrc/com/kingdee/eas/custom/dormitorysystem/application/handler/RoomChangeApplicationListHandler.java
  4. 332 0
      websrc/com/kingdee/eas/custom/dormitorysystem/application/service/CheckAgainstByCheckInBillIdsService.java
  5. 244 0
      websrc/com/kingdee/eas/custom/dormitorysystem/application/service/CheckDuplicateCheckInByBillIdService.java
  6. 336 0
      websrc/com/kingdee/eas/custom/dormitorysystem/application/service/ValidateRoomAvailableByBillIdsService.java
  7. 316 0
      websrc/com/kingdee/eas/custom/dormitorysystem/application/service/ValidateRoomAvailableService.java
  8. 41 0
      websrc/com/kingdee/eas/custom/dormitorysystem/service/GetLastMWaterPowerService.java
  9. 72 0
      websrc/com/kingdee/eas/custom/dormitorysystem/service/GetRoomListService.java
  10. 224 0
      websrc/com/kingdee/eas/custom/dormitorysystem/service/GetWaterPowerReadingService.java
  11. 184 0
      websrc/com/kingdee/eas/custom/dormitorysystem/service/SaveWaterPowerReadService.java
  12. 23 0
      websrc/com/kingdee/eas/custom/dormitorysystem/service/ShowType.java
  13. 2 2
      websrc/com/kingdee/eas/custom/dormitorysystem/waterelectricity/handler/WaterElectricityBatchListHandler.java
  14. 64 60
      websrc/com/kingdee/eas/custom/dormitorysystem/waterelectricity/handler/WaterElectricityListHandler.java
  15. 165 3
      websrc/com/kingdee/eas/custom/dormitorysystem/waterelectricity/handler/WaterElectricitySpecialEditHandler.java
  16. 45 45
      websrc/com/kingdee/eas/custom/dormitorysystem/waterelectricity/handler/WaterElectricitySpecialListHandler.java
  17. 21 24
      websrc/com/kingdee/eas/custom/dormitorysystem/waterpower/handler/WaterPowerMeterReadingEditHandler.java
  18. 12 12
      websrc/com/kingdee/eas/custom/dormitorysystem/waterpower/importService/WaterPowerMeterReadingImportService.java
  19. 27 24
      websrc/com/kingdee/eas/custom/dormitorysystem/waterpower/utils/WaterPowerUtil.java

+ 3 - 3
websrc/com/kingdee/eas/custom/dormitorysystem/application/handler/CheckInApplicationListHandler.java

@@ -15,7 +15,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 /**
- * @Description 入住申请单列表Handler
+ * @Description 鍏ヤ綇鐢宠�鍗曞垪琛℉andler
  * @Date 2025/4/24 13:47
  * @Created by Heyuan
  */
@@ -32,9 +32,9 @@ public class CheckInApplicationListHandler extends DormitoryApplicationListHandl
         try {
             HRBillBaseInfo hrBillBaseInfo = (HRBillBaseInfo) model;
             String billIds = hrBillBaseInfo.getId().toString();
-            //根据单据id校验房间是否入住(批量)
+            //鏍规嵁鍗曟嵁id鏍¢獙鎴块棿鏄�惁鍏ヤ綇(鎵归噺)
             ValidateRoomAvailableByBillIdsUtil.startValidate(ctx, billIds);
-            //检查入住申请单是否重复、入住信息是否重复,时间是否交叉
+            //妫€鏌ュ叆浣忕敵璇峰崟鏄�惁閲嶅�銆佸叆浣忎俊鎭�槸鍚﹂噸澶�,鏃堕棿鏄�惁浜ゅ弶
             CheckDuplicateCheckInByBillIdUtil.startValidate(ctx, billIds);
             super.beforeSubmit(request, response, model);
         } catch (BOSException e) {

+ 24 - 373
websrc/com/kingdee/eas/custom/dormitorysystem/application/handler/RoomChangeApplicationEditHandler.java

@@ -44,7 +44,7 @@ import java.util.*;
 /**
  * @author qingwu
  * @date 2025/4/27
- * @apiNote ABK_换宿申请单
+ * @apiNote ABK_鎹㈠�鐢宠�鍗�
  */
 public class RoomChangeApplicationEditHandler extends HRBillBaseEditHandler {
     private Logger logger = Logger.getLogger(RoomChangeApplicationEditHandler.class);
@@ -53,378 +53,29 @@ public class RoomChangeApplicationEditHandler extends HRBillBaseEditHandler {
     @Override
     protected void beforeSubmit(HttpServletRequest request, HttpServletResponse response, CoreBaseInfo model) throws SHRWebException {
         logger.error("beforeSubmit--");
-//        HRBillBaseInfo hrBillBaseInfo = (HRBillBaseInfo) model;
-//        String billIds = hrBillBaseInfo.getId().toString();
-//        Map result = null;
-//        try {
-//            result = validateRoomAvailableByBillIds(billIds);
-//        } catch (Exception e) {
-//            logger.error(e);
-//            throw new ShrWebBizException("调用方法validateRoomAvailableByBillIds报错: " + e.getMessage());
-//        }
-//        Integer code = (Integer) result.get("code");
-//        if (500 == code) {
-//            List<String> errorMsgList = (List<String>) result.get("errorMsg");
-//            StringBuilder errorMsgBuilder = new StringBuilder();
-//            for (String errorMsg : errorMsgList) {
-//                errorMsgBuilder.append(errorMsg).append("\n");
-//            }
-//            throw new ShrWebBizException(errorMsgBuilder.toString());
-//        }
-//        //设置单据状态为未审批
-//        model.setInt("billState", 1);
-        super.beforeSubmit(request, response, model);
-    }
-
-    public Map validateRoomAvailableByBillIds(String billIds) throws BOSException {
-        logger.error("validateRoomAvailableByBillIds--");
-        if (StringUtils.isEmpty(billIds)) {
-            logger.error("单据id不能为空!");
-            throw new BOSException("单据id不能为空!");
-        }
-        Map<String, List<Map<String, Date>>> roomListMap = new HashMap<String, List<Map<String, Date>>>();
-        //StringBuilder errorMsg = new StringBuilder();
-        List<String> errorMsgList = new ArrayList<String>();
-        // HRBillBaseFactory.getLocalInstance()
-        ICoreBillBase iCoreBillBase = (ICoreBillBase) BOSObjectFactory.createBOSObject(ctx,
-                BOSUuid.read(billIds.split(",")[0]).getType());
-        SelectorItemCollection sic = new SelectorItemCollection();
-        sic.add("*");
-        sic.add("entrys.*");
-        sic.add("entrys.person.*");
-        sic.add("entrys.person.personType.*");
-        sic.add("entrys.adjustRoom.*");
-        sic.add("entrys.adjustRoom.DormitoryType.*");
-        FilterInfo filterInfo = new FilterInfo();
-        FilterItemCollection filterItems = filterInfo.getFilterItems();
-        //房间
-        filterItems.add(new FilterItemInfo("id", AtsUtil.toSet(billIds), CompareType.INCLUDE));
-        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
-        CoreBillBaseCollection hrBillBaseCollection = iCoreBillBase.getCoreBillBaseCollection(viewInfo);
-        logger.error("hrBillBaseCollection--" + hrBillBaseCollection.size());
-        for (int i = 0; i < hrBillBaseCollection.size(); i++) {
-            HRBillBaseInfo hrBillBaseInfo = (HRBillBaseInfo) hrBillBaseCollection.get(i);
-            //String billId = hrBillBaseInfo.getId().toString();
-            String baseInfoNumber = hrBillBaseInfo.getNumber();
-            String bosType = hrBillBaseInfo.getId().getType().toString();
-            AbstractObjectCollection entrys = (AbstractObjectCollection) hrBillBaseInfo.get("entrys");
-            logger.error("entrys--" + entrys.size());
-            for (int j = 0; j < entrys.size(); j++) {
-                try {
-                    HRBillBaseEntryInfo entryInfo = (HRBillBaseEntryInfo) entrys.getObject(j);
-                    Date checkInDate = null;
-                    //B371AC0A 换宿单分录    0CDEF948表头
-                    if ("0CDEF948".equals(bosType)) {
-                        //换宿单
-                        checkInDate = entryInfo.getDate("checkInDate");
-                    }
-                    if (checkInDate == null) {
-                        throw new BOSException("换宿日期不能为空!");
-                    }
-                    //退宿日期
-                    Date checkoutDate = entryInfo.getDate("checkoutDate");
-                    if (checkoutDate == null) {
-                        throw new BOSException("退宿日期不能为空!");
-                    }
-                    //人员
-                    PersonInfo personInfo = (PersonInfo) entryInfo.getObjectValue("person");
-                    if (personInfo == null) {
-                        throw new BOSException("人员不能为空!");
-                    }
-                    //房间
-                    DormitoryInfo dormitory = (DormitoryInfo) entryInfo.getObjectValue("adjustRoom");
-                    if (dormitory == null) {
-                        throw new BOSException("房间不能为空!");
-                    }
-                    String roomId = dormitory.getId().toString();
-                    //根据入住日期,性别,员工类别查询可选房间
-                    //人员类型
-                    PersonDormitoryTypeInfo personType = (PersonDormitoryTypeInfo) personInfo.get("personType");
-                    if (personType == null) {
-                        throw new BOSException("员工[" + personInfo.getName() + "]的人员类别为空,请及时维护!");
-                    }
-                    //String personTypeId = personType.getId().toString();
-                    //已住人数
-                    int dormCheckInCount = 0;
-                    //1.校验房间信息
-                    validateDormitoryInfo(ctx, personInfo, dormitory);
-                    //可住人数
-                    int occupancyCapacity = dormitory.getOccupancyCapacity();
-                    //2.根据换宿日期和退宿日期算出入住信息房间已住人数
-                    dormCheckInCount += getCheckInInfoByOccupants(ctx, checkInDate, checkoutDate, roomId, personType);
-                    //3.根据换宿日期和退宿日期算出入住申请单状态为申请中的已住人数
-                    dormCheckInCount += getCheckInInfoByCheckInApplication(ctx, checkInDate, checkoutDate, roomId, personType);
-                    //4.根据换宿日期和退宿日期算出换宿申请单状态为申请中的已住人数
-                    dormCheckInCount += getRoomChangeInfoByRoomChangeApplication(ctx, checkInDate, checkoutDate, roomId, personType);
-                    //5.根据当前参数缓存算出已住人数
-                    if (roomListMap.containsKey(roomId)) {
-                        List<Map<String, Date>> roomMapList = roomListMap.get(roomId);
-                        for (int k = 0; k < roomMapList.size(); k++) {
-                            Map<String, Date> roomMap = roomMapList.get(k);
-                            Date checkInDateOld = roomMap.get("checkInDate");
-                            Date checkoutDateOld = roomMap.get("checkoutDate");
-                            //申请入住日期在入住日期和退宿日期之间
-                            //入住日期在申请入住日期和申请退宿日期之间
-                            if ((checkInDateOld.compareTo(checkInDate) <= 0 && checkoutDateOld.compareTo(checkInDate) >= 0)
-                                    || (checkInDateOld.compareTo(checkInDate) >= 0 && checkInDateOld.compareTo(checkoutDate) <= 0)) {
-                                dormCheckInCount++;
-                            }
-                        }
-                    }
-                    logger.error("occupancyCapacity--" + occupancyCapacity);
-                    logger.error("dormCheckInCount--" + dormCheckInCount);
-                    //6.算出房间剩余可住人数: 可住人数 - 已住人数
-                    if (occupancyCapacity - dormCheckInCount < 0) {
-                        String dormitoryName = dormitory.getName();
-                        throw new BOSException("当前入住人数" + dormCheckInCount + ",已超过房间[" + dormitoryName + "]可住人数" + occupancyCapacity + ",不能入住!");
-                    }
-                    Map roomMap = new HashMap();
-                    roomMap.put("checkInDate", checkInDate);
-                    roomMap.put("checkoutDate", checkoutDate);
-                    if (roomListMap.containsKey(roomId)) {
-                        roomListMap.get(roomId).add(roomMap);
-                    } else {
-                        List list = new ArrayList();
-                        roomListMap.put(roomId, list);
-                        list.add(roomMap);
-                    }
-                } catch (Exception e) {
-                    logger.error("单据编号为" + baseInfoNumber + "校验未通过: " + e.getMessage(), e);
-                    errorMsgList.add("单据编号为" + baseInfoNumber + "校验未通过: " + e.getMessage());
-                    //errorMsg.append("单据编号为").append(baseInfoNumber).append("校验未通过: ").append(e.getMessage()).append(System.lineSeparator());
-                }
-            }
-        }
-        Map result = new HashMap();
-        if (errorMsgList.size() > 0) {
-            result.put("code", 500);
-            result.put("errorMsg", errorMsgList);
-        } else {
-            result.put("code", 200);
-        }
-        return result;
-    }
-
-    /**
-     * 根据入住日期和退宿日期算出换宿申请单状态为申请中的已住人数
-     *
-     * @param ctx
-     * @param checkInDate  入住日期
-     * @param checkoutDate 退宿日期
-     * @param roomId       房间id
-     * @param personType   人员类型
-     * @return
-     * @throws BOSException
-     */
-    private int getRoomChangeInfoByRoomChangeApplication(
-            Context ctx,
-            Date checkInDate,
-            Date checkoutDate,
-            String roomId,
-            PersonDormitoryTypeInfo personType
-    ) throws BOSException {
-        IRoomChangeApplicationEntry iRoomChangeApplicationEntry = RoomChangeApplicationEntryFactory.getLocalInstance(ctx);
-        FilterInfo filterInfo = new FilterInfo();
-        FilterItemCollection filterItems = filterInfo.getFilterItems();
-        //房间
-        filterItems.add(new FilterItemInfo("adjustRoom", roomId));
-        //申请入住日期在入住日期和退宿日期之间
-        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.LESS_EQUALS));
-        filterItems.add(new FilterItemInfo("checkoutDate", checkInDate, CompareType.GREATER_EQUALS));
-        //换宿日期在申请入住日期和申请退宿日期之间
-        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.GREATER_EQUALS));
-        filterItems.add(new FilterItemInfo("checkInDate", checkoutDate, CompareType.LESS_EQUALS));
-        //单据状态等于审批中
-        filterItems.add(new FilterItemInfo("parent.billState", "1,2,3", CompareType.INCLUDE));
-        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) and #5");
-        SelectorItemCollection sic = new SelectorItemCollection();
-        sic.add("adjustRoom.id");
-        sic.add("person.personType.id");
-        sic.add("person.personType.name");
-        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
-        RoomChangeApplicationEntryCollection roomChangeApplicationEntryCol = iRoomChangeApplicationEntry.getRoomChangeApplicationEntryCollection(viewInfo);
-        String personTypeId = personType.getId().toString();
-        String personTypeName = personType.getName();
-        //已住人数
-        int dormCheckInCount = 0;
-        for (int i = 0; i < roomChangeApplicationEntryCol.size(); i++) {
-            RoomChangeApplicationEntryInfo roomChangeApplicationEntryInfo = roomChangeApplicationEntryCol.get(i);
-            //房间
-            PersonInfo person = roomChangeApplicationEntryInfo.getPerson();
-            String personName = person.getName();
-            //人员类型
-            PersonDormitoryTypeInfo personDormitoryType = (PersonDormitoryTypeInfo) person.get("personType");
-            if (personDormitoryType == null) {
-                throw new BOSException("员工[" + personName + "]的人员类别为空,请及时维护!");
-            }
-            String personDormitoryTypeId = personDormitoryType.getId().toString();
-            String personDormitoryTypeName = personDormitoryType.getName();
-            if (!personTypeId.equals(personDormitoryTypeId)) {
-                throw new BOSException("人员类别[" + personTypeName + "]与宿舍类型[" + personDormitoryTypeName + "]不符,不能入住!");
-            }
-            //累计已住人数
-            dormCheckInCount++;
+        HRBillBaseInfo hrBillBaseInfo = (HRBillBaseInfo) model;
+        String billIds = hrBillBaseInfo.getId().toString();
+        Map result = null;
+        try {
+            result = validateRoomAvailableByBillIds(billIds);
+        } catch (Exception e) {
+            logger.error(e);
+            throw new ShrWebBizException("璋冪敤鏂规硶validateRoomAvailableByBillIds鎶ラ敊: " + e.getMessage());
         }
-        return dormCheckInCount;
-    }
-
-    /**
-     * 根据入住日期和退宿日期算出入住申请单状态为申请中的已住人数
-     *
-     * @param ctx
-     * @param checkInDate  入住日期
-     * @param checkoutDate 退宿日期
-     * @param roomId       房间id
-     * @param personType   人员类型
-     * @return
-     * @throws BOSException
-     */
-    private int getCheckInInfoByCheckInApplication(
-            Context ctx,
-            Date checkInDate,
-            Date checkoutDate,
-            String roomId,
-            PersonDormitoryTypeInfo personType
-    ) throws BOSException {
-        ICheckInApplicationEntry iCheckInApplicationEntry = CheckInApplicationEntryFactory.getLocalInstance(ctx);
-        FilterInfo filterInfo = new FilterInfo();
-        FilterItemCollection filterItems = filterInfo.getFilterItems();
-        //房间
-        filterItems.add(new FilterItemInfo("adjustRoom", roomId));
-        //申请入住日期在入住日期和退宿日期之间
-        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.LESS_EQUALS));
-        filterItems.add(new FilterItemInfo("checkoutDate", checkInDate, CompareType.GREATER_EQUALS));
-        //入住日期在申请入住日期和申请退宿日期之间
-        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.GREATER_EQUALS));
-        filterItems.add(new FilterItemInfo("checkInDate", checkoutDate, CompareType.LESS_EQUALS));
-        //单据状态等于审批中
-        filterItems.add(new FilterItemInfo("parent.billState", "1,2,3", CompareType.INCLUDE));
-        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) and #5");
-        SelectorItemCollection sic = new SelectorItemCollection();
-        sic.add("adjustRoom.id");
-        sic.add("person.personType.id");
-        sic.add("person.personType.name");
-        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
-        CheckInApplicationEntryCollection checkInApplicationEntryCol = iCheckInApplicationEntry.getCheckInApplicationEntryCollection(viewInfo);
-        String personTypeId = personType.getId().toString();
-        String personTypeName = personType.getName();
-        //已住人数
-        int dormCheckInCount = 0;
-        for (int i = 0; i < checkInApplicationEntryCol.size(); i++) {
-            CheckInApplicationEntryInfo checkInApplicationEntryInfo = checkInApplicationEntryCol.get(i);
-            //房间
-            PersonInfo person = checkInApplicationEntryInfo.getPerson();
-            String personName = person.getName();
-            //人员类型
-            PersonDormitoryTypeInfo personDormitoryType = (PersonDormitoryTypeInfo) person.get("personType");
-            if (personDormitoryType == null) {
-                throw new BOSException("员工[" + personName + "]的人员类别为空,请及时维护!");
+        Integer code = (Integer) result.get("code");
+        if (500 == code) {
+            List<String> errorMsgList = (List<String>) result.get("errorMsg");
+            StringBuilder errorMsgBuilder = new StringBuilder();
+            for (String errorMsg : errorMsgList) {
+                errorMsgBuilder.append(errorMsg).append("\n");
             }
-            String personDormitoryTypeId = personDormitoryType.getId().toString();
-            String personDormitoryTypeName = personDormitoryType.getName();
-            if (!personTypeId.equals(personDormitoryTypeId)) {
-                throw new BOSException("人员类别[" + personTypeName + "]与宿舍类型[" + personDormitoryTypeName + "]不符,不能入住!");
-            }
-            //累计已住人数
-            dormCheckInCount++;
-        }
-        return dormCheckInCount;
-    }
-
-    /**
-     * 校验房间信息
-     *
-     * @param ctx
-     * @param personInfo
-     * @param dormitory  房间
-     * @return
-     * @throws BOSException
-     * @throws EASBizException
-     */
-    protected void validateDormitoryInfo(
-            Context ctx,
-            PersonInfo personInfo,
-            DormitoryInfo dormitory
-    ) throws BOSException, EASBizException {
-        Genders gender = personInfo.getGender();
-        if (gender == null) {
-            throw new BOSException("员工性别为空!");
-        }
-        String personInfoName = personInfo.getName();
-        IDormitory iDormitory = DormitoryFactory.getLocalInstance(ctx);
-        //查询房间信息
-        String dormitoryName = dormitory.getName();
-        DormitoryClassification roomClassification = dormitory.getRoomClassification();
-        if (!DormitoryClassification.ROOM.equals(roomClassification)) {
-            String classificationAlias = roomClassification.getAlias();
-            throw new BOSException("房间[" + dormitoryName + "]房间归类为" + classificationAlias + ",不能入住!");
-        }
-        BasicItemStateEnum dormitoryInfoState = dormitory.getState();
-        if (BasicItemStateEnum.DISABLE.equals(dormitoryInfoState)) {
-            throw new BOSException("房间[" + dormitoryName + "]未启用,不能入住!");
-        }
-        //宿舍类型
-        DormitoryTypeInfo dormitoryType = dormitory.getDormitoryType();
-        Genders roomGender = dormitoryType.getGender();
-        if (roomGender != null && gender.getValue() != roomGender.getValue()) {
-            String dormitoryTypeName = dormitoryType.getName();
-            throw new BOSException("房间[" + dormitoryName + "]宿舍类型为" + dormitoryTypeName + ",与人员[" + personInfoName + "]的性别不符!");
+            throw new ShrWebBizException(errorMsgBuilder.toString());
         }
+        // 璁剧疆鍗曟嵁鐘舵€佷负鏈��鎵�
+        // model.setInt("billState", 1);
+        super.beforeSubmit(request, response, model);
     }
 
-    /**
-     * 根据入住日期和退宿日期算出入住信息中每个房间已住人数
-     *
-     * @param ctx
-     * @param checkInDate  入住日期
-     * @param checkoutDate 退宿日期
-     * @param roomId       房间id
-     * @param personType   人员类型
-     * @return
-     * @throws BOSException
-     */
-    protected int getCheckInInfoByOccupants(
-            Context ctx,
-            Date checkInDate,
-            Date checkoutDate,
-            String roomId,
-            PersonDormitoryTypeInfo personType
-    ) throws BOSException {
-        IOccupants iOccupants = OccupantsFactory.getLocalInstance(ctx);
-        FilterInfo filterInfo = new FilterInfo();
-        FilterItemCollection filterItems = filterInfo.getFilterItems();
-        //房间
-        filterItems.add(new FilterItemInfo("Dormitory", roomId));
-        //申请入住日期在入住日期和退宿日期之间
-        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.LESS_EQUALS));
-        filterItems.add(new FilterItemInfo("checkoutDate", checkInDate, CompareType.GREATER_EQUALS));
-        //入住日期在申请入住日期和申请退宿日期之间
-        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.GREATER_EQUALS));
-        filterItems.add(new FilterItemInfo("checkInDate", checkoutDate, CompareType.LESS_EQUALS));
-        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) ");
-        SelectorItemCollection sic = new SelectorItemCollection();
-        sic.add("PersonDormitoryType.id");
-        sic.add("PersonDormitoryType.name");
-        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
-        OccupantsCollection occupantsCollection = iOccupants.getOccupantsCollection(viewInfo);
-        String personTypeId = personType.getId().toString();
-        String personTypeName = personType.getName();
-        //已住人数
-        int dormCheckInCount = 0;
-        String personDormitoryTypeId = null;
-        for (int i = 0; i < occupantsCollection.size(); i++) {
-            OccupantsInfo occupantsInfo = occupantsCollection.get(i);
-            //人员宿舍分类
-            PersonDormitoryTypeInfo personDormitoryType = occupantsInfo.getPersonDormitoryType();
-            personDormitoryTypeId = personDormitoryType.getId().toString();
-            String personDormitoryTypeName = personDormitoryType.getName();
-            if (!personTypeId.equals(personDormitoryTypeId)) {
-                throw new BOSException("人员类别[" + personTypeName + "]与宿舍类型[" + personDormitoryTypeName + "]不符,不能入住!");
-            }
-            dormCheckInCount++;
-        }
-        return dormCheckInCount;
-    }
 
     @Override
     protected void afterCreateNewModel(HttpServletRequest request, HttpServletResponse response, CoreBaseInfo coreBaseInfo) throws SHRWebException {
@@ -434,12 +85,12 @@ public class RoomChangeApplicationEditHandler extends HRBillBaseEditHandler {
             RoomChangeApplicationEntryCollection entrys = roomChangeApplicationInfo.getEntrys();
             RoomChangeApplicationEntryInfo roomChangeApplicationEntryInfo = new RoomChangeApplicationEntryInfo();
             roomChangeApplicationEntryInfo.setCheckoutDate(DateTimeUtils.parseDate("2199-12-31", "yyyy-MM-dd"));
-            //managementNotes  宿舍管理说明
+            // managementNotes  瀹胯垗绠$悊璇存槑
             StringBuilder managementNotes = new StringBuilder();
-            managementNotes.append("本人愿意遵守以下条款:").append("\n");
-            managementNotes.append("1、自觉遵守公司《宿舍管理制度》和员工宿舍区有关管理办法,不私自调换宿舍和床位。").append("\n");
-            managementNotes.append("2、自觉维护宿舍公共区域的卫生,爱护公物,损坏公物自觉赔偿。").append("\n");
-            managementNotes.append("3、自觉遵守消防安全,节约用电用水。").append("\n");
+            managementNotes.append("鏈�汉鎰挎剰閬靛畧浠ヤ笅鏉℃�锛�").append("\n");
+            managementNotes.append("1銆佽嚜瑙夐伒瀹堝叕鍙搞€婂�鑸嶇�鐞嗗埗搴︺€嬪拰鍛樺伐瀹胯垗鍖烘湁鍏崇�鐞嗗姙娉曪紝涓嶇�鑷�皟鎹㈠�鑸嶅拰搴婁綅銆�").append("\n");
+            managementNotes.append("2銆佽嚜瑙夌淮鎶ゅ�鑸嶅叕鍏卞尯鍩熺殑鍗�敓锛岀埍鎶ゅ叕鐗╋紝鎹熷潖鍏�墿鑷��璧斿伩銆�").append("\n");
+            managementNotes.append("3銆佽嚜瑙夐伒瀹堟秷闃插畨鍏�紝鑺傜害鐢ㄧ數鐢ㄦ按銆�").append("\n");
             roomChangeApplicationInfo.setManagementNotes(managementNotes.toString());
             entrys.add(roomChangeApplicationEntryInfo);
         } catch (Exception e) {

+ 6 - 6
websrc/com/kingdee/eas/custom/dormitorysystem/application/handler/RoomChangeApplicationListHandler.java

@@ -53,23 +53,23 @@ public class RoomChangeApplicationListHandler extends DormitoryApplicationListHa
                     .getRoomChangeApplicationInfo("select *, entrys.* ,entrys.person.* ,entrys.adjustRoom.* where id = '" + billId + "'");
             RoomChangeApplicationEntryCollection entrys = roomChangeApplicationInfo.getEntrys();
             RoomChangeApplicationEntryInfo entryInfo = entrys.get(0);
-            //换宿日期
+            //鎹㈠�鏃ユ湡
             Date checkInDate = entryInfo.getCheckInDate();
-            //调整房间
+            //璋冩暣鎴块棿
             DormitoryInfo adjustRoom = entryInfo.getAdjustRoom();
-            //人员
+            //浜哄憳
             PersonInfo person = entryInfo.getPerson();
-            //年月
+            //骞存湀
             String yearMonth = DateTimeUtil.getFmtDate(checkInDate, "yyyy-MM");
             logger.error("yearMonth---" + yearMonth);
-            //水电明细
+            //姘寸數鏄庣粏
             IWaterElectricity iWaterElectricity = WaterElectricityFactory.getLocalInstance(ctx);
             String sql = "where person.id= '" + person.getId() + "' and yearMonth = '" + yearMonth + "' and dormitory.id = '" + adjustRoom.getId() + "'";
             logger.error("sql---" + sql);
             boolean exists = iWaterElectricity.exists(sql);
             logger.error("exists---" + exists);
             if (exists) {
-                throw new ShrWebBizException(person.getName() + "已经在" + yearMonth + ",产生水电明细不能进行反审批!!");
+                throw new ShrWebBizException(person.getName() + "宸茬粡鍦�" + yearMonth + ",浜х敓姘寸數鏄庣粏涓嶈兘杩涜�鍙嶅�鎵癸紒锛�");
             }
         } catch (EASBizException e) {
             e.printStackTrace();

+ 332 - 0
websrc/com/kingdee/eas/custom/dormitorysystem/application/service/CheckAgainstByCheckInBillIdsService.java

@@ -0,0 +1,332 @@
+package com.kingdee.eas.custom.dormitorysystem.application.service;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.BOSObjectFactory;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.bsf.service.app.IHRMsfService;
+import com.kingdee.bos.dao.AbstractObjectCollection;
+import com.kingdee.bos.metadata.entity.*;
+import com.kingdee.bos.metadata.query.util.CompareType;
+import com.kingdee.bos.util.BOSUuid;
+import com.kingdee.eas.basedata.person.Genders;
+import com.kingdee.eas.basedata.person.PersonInfo;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.custom.dormitorysystem.application.CheckInApplicationEntryCollection;
+import com.kingdee.eas.custom.dormitorysystem.application.CheckInApplicationEntryFactory;
+import com.kingdee.eas.custom.dormitorysystem.application.CheckInApplicationEntryInfo;
+import com.kingdee.eas.custom.dormitorysystem.application.ICheckInApplicationEntry;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.DormitoryFactory;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.DormitoryInfo;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.IDormitory;
+import com.kingdee.eas.custom.dormitorysystem.enumerationset.DormitoryClassification;
+import com.kingdee.eas.custom.dormitorysystem.occupants.IOccupants;
+import com.kingdee.eas.custom.dormitorysystem.occupants.OccupantsCollection;
+import com.kingdee.eas.custom.dormitorysystem.occupants.OccupantsFactory;
+import com.kingdee.eas.custom.dormitorysystem.occupants.OccupantsInfo;
+import com.kingdee.eas.custom.dormitorysystem.otherbasicdata.DormitoryTypeInfo;
+import com.kingdee.eas.custom.dormitorysystem.otherbasicdata.PersonDormitoryTypeInfo;
+import com.kingdee.eas.framework.CoreBillBaseCollection;
+import com.kingdee.eas.framework.ICoreBillBase;
+import com.kingdee.eas.hr.ats.AtsUtil;
+import com.kingdee.eas.hr.base.HRBillBaseEntryInfo;
+import com.kingdee.eas.hr.base.HRBillBaseInfo;
+import com.kingdee.shr.base.syssetting.BasicItemStateEnum;
+import com.kingdee.util.StringUtils;
+import org.apache.log4j.Logger;
+
+import java.util.*;
+
+/**
+ * @Description 根据单据id检查是否可以反审批入住申请单
+ * @Date 2025/4/27 17:00
+ * @Created by Heyuan
+ */
+public class CheckAgainstByCheckInBillIdsService implements IHRMsfService {
+    private static Logger logger = Logger.getLogger(CheckAgainstByCheckInBillIdsService.class);
+
+    @Override
+    public Object process(
+            Context ctx,
+            Map<String, Object> params
+    ) throws EASBizException, BOSException {
+        String billIds = (String) params.get("billIds");
+        if (StringUtils.isEmpty(billIds)) {
+            logger.error("单据id不能为空!");
+            throw new BOSException("单据id不能为空!");
+        }
+        Map<String, List<Map<String, Date>>> roomListMap = new HashMap<>();
+        //StringBuilder errorMsg = new StringBuilder();
+        List<String> errorMsgList = new ArrayList<>();
+        // HRBillBaseFactory.getLocalInstance()
+        ICoreBillBase iCoreBillBase = (ICoreBillBase) BOSObjectFactory.createBOSObject(ctx,
+                BOSUuid.read(billIds.split(",")[0]).getType());
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("*");
+        sic.add("entrys.*");
+        sic.add("entrys.person.*");
+        sic.add("entrys.person.personType.*");
+        sic.add("entrys.checkInRoom.*");
+        sic.add("entrys.checkInRoom.DormitoryType.*");
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //房间
+        filterItems.add(new FilterItemInfo("id", AtsUtil.toSet(billIds), CompareType.INCLUDE));
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        CoreBillBaseCollection hrBillBaseCollection = iCoreBillBase.getCoreBillBaseCollection(viewInfo);
+        for (int i = 0; i < hrBillBaseCollection.size(); i++) {
+            HRBillBaseInfo hrBillBaseInfo = (HRBillBaseInfo) hrBillBaseCollection.get(i);
+            //String billId = hrBillBaseInfo.getId().toString();
+            String baseInfoNumber = hrBillBaseInfo.getNumber();
+            String bosType = hrBillBaseInfo.getId().getType().toString();
+            AbstractObjectCollection entrys = (AbstractObjectCollection) hrBillBaseInfo.get("entrys");
+            for (int j = 0; j < entrys.size(); j++) {
+                try {
+                    HRBillBaseEntryInfo entryInfo = (HRBillBaseEntryInfo) entrys.getObject(j);
+                    Date checkInDate = null;
+                    if ("B371AC0A".equals(bosType)) {
+                        //换宿单
+                        //入住日期
+                        checkInDate = entryInfo.getDate("adjustmentDate");
+                    } else {
+                        //入住日期
+                        checkInDate = entryInfo.getDate("checkInDate");
+                    }
+                    if (checkInDate == null) {
+                        throw new BOSException("入住日期不能为空!");
+                    }
+                    //退宿日期
+                    Date checkoutDate = entryInfo.getDate("checkoutDate");
+                    if (checkoutDate == null) {
+                        throw new BOSException("退宿日期不能为空!");
+                    }
+                    //人员
+                    PersonInfo personInfo = (PersonInfo) entryInfo.getObjectValue("person");
+                    if (personInfo == null) {
+                        throw new BOSException("人员不能为空!");
+                    }
+                    //房间
+                    DormitoryInfo dormitory = (DormitoryInfo) entryInfo.getObjectValue("checkInRoom");
+                    if (dormitory == null) {
+                        throw new BOSException("房间不能为空!");
+                    }
+                    String roomId = dormitory.getId().toString();
+                    //根据入住日期,性别,员工类别查询可选房间
+                    //人员类型
+                    PersonDormitoryTypeInfo personType = (PersonDormitoryTypeInfo) personInfo.get("personType");
+                    if (personType == null) {
+                        throw new BOSException("员工[" + personInfo.getName() + "]的人员类别为空,请及时维护!");
+                    }
+                    //String personTypeId = personType.getId().toString();
+                    //已住人数
+                    int dormCheckInCount = 0;
+                    //1.校验房间信息
+                    validateDormitoryInfo(ctx, personInfo, dormitory);
+                    //可住人数
+                    int occupancyCapacity = dormitory.getOccupancyCapacity();
+                    //2.根据入住日期和退宿日期算出入住信息房间已住人数
+                    dormCheckInCount += getCheckInInfoByOccupants(ctx, checkInDate, checkoutDate, roomId, personType);
+                    //3.根据入住日期和退宿日期算出入住申请单状态为申请中的已住人数
+                    dormCheckInCount += getCheckInInfoByCheckInApplication(ctx, checkInDate, checkoutDate, roomId, personType);
+                    //4.根据当前参数缓存算出已住人数
+                    if (roomListMap.containsKey(roomId)) {
+                        List<Map<String, Date>> roomMapList = roomListMap.get(roomId);
+                        for (int k = 0; k < roomMapList.size(); k++) {
+                            Map<String, Date> roomMap = roomMapList.get(k);
+                            Date checkInDateOld = roomMap.get("checkInDate");
+                            Date checkoutDateOld = roomMap.get("checkoutDate");
+                            //申请入住日期在入住日期和退宿日期之间
+                            //入住日期在申请入住日期和申请退宿日期之间
+                            if ((checkInDateOld.compareTo(checkInDate) <= 0 && checkoutDateOld.compareTo(checkInDate) >= 0)
+                                    || (checkInDateOld.compareTo(checkInDate) >= 0 && checkInDateOld.compareTo(checkoutDate) <= 0)) {
+                                dormCheckInCount++;
+                            }
+                        }
+                    }
+                    //5.算出房间剩余可住人数: 可住人数 - 已住人数
+                    if (occupancyCapacity - dormCheckInCount <= 0) {
+                        String dormitoryName = dormitory.getName();
+                        throw new BOSException("当前入住人数" + dormCheckInCount + ",已超过房间[" + dormitoryName + "]可住人数" + occupancyCapacity + ",不能入住!");
+                    }
+                    Map roomMap = new HashMap();
+                    roomMap.put("checkInDate", checkInDate);
+                    roomMap.put("checkoutDate", checkoutDate);
+                    if (roomListMap.containsKey(roomId)) {
+                        roomListMap.get(roomId).add(roomMap);
+                    } else {
+                        List list = new ArrayList();
+                        roomListMap.put(roomId, list);
+                        list.add(roomMap);
+                    }
+                } catch (Exception e) {
+                    logger.error("单据编号为" + baseInfoNumber + "校验未通过: " + e.getMessage());
+                    errorMsgList.add("单据编号为" + baseInfoNumber + "校验未通过: " + e.getMessage());
+                    //errorMsg.append("单据编号为").append(baseInfoNumber).append("校验未通过: ").append(e.getMessage()).append(System.lineSeparator());
+                }
+            }
+        }
+        Map result = new HashMap();
+        if (errorMsgList.size() > 0) {
+            result.put("code", 500);
+            result.put("errorMsg", errorMsgList);
+        } else {
+            result.put("code", 200);
+        }
+        return result;
+    }
+
+    /**
+     * 根据入住日期和退宿日期算出入住申请单状态为申请中的已住人数
+     *
+     * @param ctx
+     * @param checkInDate  入住日期
+     * @param checkoutDate 退宿日期
+     * @param roomId       房间id
+     * @param personType   人员类型
+     * @return
+     * @throws BOSException
+     */
+    private int getCheckInInfoByCheckInApplication(
+            Context ctx,
+            Date checkInDate,
+            Date checkoutDate,
+            String roomId,
+            PersonDormitoryTypeInfo personType
+    ) throws BOSException {
+        ICheckInApplicationEntry iCheckInApplicationEntry = CheckInApplicationEntryFactory.getLocalInstance(ctx);
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //房间
+        filterItems.add(new FilterItemInfo("checkInRoom", roomId));
+        //申请入住日期在入住日期和退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.LESS_EQUALS));
+        filterItems.add(new FilterItemInfo("checkoutDate", checkInDate, CompareType.GREATER_EQUALS));
+        //入住日期在申请入住日期和申请退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.GREATER_EQUALS));
+        filterItems.add(new FilterItemInfo("checkInDate", checkoutDate, CompareType.LESS_EQUALS));
+        //单据状态等于审批中
+        filterItems.add(new FilterItemInfo("parent.billState", "3"));
+        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) and #5");
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("checkInRoom.id");
+        sic.add("person.personType.id");
+        sic.add("person.personType.name");
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        CheckInApplicationEntryCollection checkInApplicationEntryCol = iCheckInApplicationEntry.getCheckInApplicationEntryCollection(viewInfo);
+        String personTypeId = personType.getId().toString();
+        String personTypeName = personType.getName();
+        //已住人数
+        int dormCheckInCount = 0;
+        for (int i = 0; i < checkInApplicationEntryCol.size(); i++) {
+            CheckInApplicationEntryInfo checkInApplicationEntryInfo = checkInApplicationEntryCol.get(i);
+            //房间
+            PersonInfo person = checkInApplicationEntryInfo.getPerson();
+            String personName = person.getName();
+            //人员类型
+            PersonDormitoryTypeInfo personDormitoryType = (PersonDormitoryTypeInfo) person.get("personType");
+            if (personDormitoryType == null) {
+                throw new BOSException("员工[" + personName + "]的人员类别为空,请及时维护!");
+            }
+            String personDormitoryTypeId = personDormitoryType.getId().toString();
+            String personDormitoryTypeName = personDormitoryType.getName();
+            if (!personTypeId.equals(personDormitoryTypeId)) {
+                throw new BOSException("人员类别[" + personTypeName + "]与宿舍类型[" + personDormitoryTypeName + "]不符,不能入住!");
+            }
+            //累计已住人数
+            dormCheckInCount++;
+        }
+        return dormCheckInCount;
+    }
+
+
+    /**
+     * 根据入住日期和退宿日期算出入住信息中每个房间已住人数
+     *
+     * @param ctx
+     * @param checkInDate  入住日期
+     * @param checkoutDate 退宿日期
+     * @param roomId       房间id
+     * @param personType   人员类型
+     * @return
+     * @throws BOSException
+     */
+    protected int getCheckInInfoByOccupants(
+            Context ctx,
+            Date checkInDate,
+            Date checkoutDate,
+            String roomId,
+            PersonDormitoryTypeInfo personType
+    ) throws BOSException {
+        IOccupants iOccupants = OccupantsFactory.getLocalInstance(ctx);
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //房间
+        filterItems.add(new FilterItemInfo("Dormitory", roomId));
+        //申请入住日期在入住日期和退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.LESS_EQUALS));
+        filterItems.add(new FilterItemInfo("checkoutDate", checkInDate, CompareType.GREATER_EQUALS));
+        //入住日期在申请入住日期和申请退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.GREATER_EQUALS));
+        filterItems.add(new FilterItemInfo("checkInDate", checkoutDate, CompareType.LESS_EQUALS));
+        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) ");
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("PersonDormitoryType.id");
+        sic.add("PersonDormitoryType.name");
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        OccupantsCollection occupantsCollection = iOccupants.getOccupantsCollection(viewInfo);
+        String personTypeId = personType.getId().toString();
+        String personTypeName = personType.getName();
+        //已住人数
+        int dormCheckInCount = 0;
+        String personDormitoryTypeId = null;
+        for (int i = 0; i < occupantsCollection.size(); i++) {
+            OccupantsInfo occupantsInfo = occupantsCollection.get(i);
+            //人员宿舍分类
+            PersonDormitoryTypeInfo personDormitoryType = occupantsInfo.getPersonDormitoryType();
+            personDormitoryTypeId = personDormitoryType.getId().toString();
+            String personDormitoryTypeName = personDormitoryType.getName();
+            if (!personTypeId.equals(personDormitoryTypeId)) {
+                throw new BOSException("人员类别[" + personTypeName + "]与宿舍类型[" + personDormitoryTypeName + "]不符,不能入住!");
+            }
+            dormCheckInCount++;
+        }
+        return dormCheckInCount;
+    }
+
+    /**
+     * 校验房间信息
+     *
+     * @param ctx
+     * @param personInfo
+     * @param dormitory  房间
+     * @return
+     * @throws BOSException
+     * @throws EASBizException
+     */
+    protected void validateDormitoryInfo(
+            Context ctx,
+            PersonInfo personInfo,
+            DormitoryInfo dormitory
+    ) throws BOSException, EASBizException {
+        Genders gender = personInfo.getGender();
+        String personInfoName = personInfo.getName();
+        IDormitory iDormitory = DormitoryFactory.getLocalInstance(ctx);
+        //查询房间信息
+        String dormitoryName = dormitory.getName();
+        DormitoryClassification roomClassification = dormitory.getRoomClassification();
+        if (!DormitoryClassification.ROOM.equals(roomClassification)) {
+            String classificationAlias = roomClassification.getAlias();
+            throw new BOSException("房间[" + dormitoryName + "]房间归类为" + classificationAlias + ",不能入住!");
+        }
+        BasicItemStateEnum dormitoryInfoState = dormitory.getState();
+        if (BasicItemStateEnum.DISABLE.equals(dormitoryInfoState)) {
+            throw new BOSException("房间[" + dormitoryName + "]未启用,不能入住!");
+        }
+        //宿舍类型
+        DormitoryTypeInfo dormitoryType = dormitory.getDormitoryType();
+        Genders roomGender = dormitoryType.getGender();
+        if (roomGender != null && gender.getValue() != roomGender.getValue()) {
+            String dormitoryTypeName = dormitoryType.getName();
+            throw new BOSException("房间[" + dormitoryName + "]宿舍类型为" + dormitoryTypeName + ",与人员[" + personInfoName + "]的性别不符!");
+        }
+    }
+}

+ 244 - 0
websrc/com/kingdee/eas/custom/dormitorysystem/application/service/CheckDuplicateCheckInByBillIdService.java

@@ -0,0 +1,244 @@
+package com.kingdee.eas.custom.dormitorysystem.application.service;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.BOSObjectFactory;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.bsf.service.app.IHRMsfService;
+import com.kingdee.bos.dao.AbstractObjectCollection;
+import com.kingdee.bos.metadata.entity.*;
+import com.kingdee.bos.metadata.query.util.CompareType;
+import com.kingdee.bos.util.BOSUuid;
+import com.kingdee.eas.basedata.person.PersonInfo;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.custom.dormitorysystem.application.*;
+import com.kingdee.eas.custom.dormitorysystem.occupants.IOccupants;
+import com.kingdee.eas.custom.dormitorysystem.occupants.OccupantsCollection;
+import com.kingdee.eas.custom.dormitorysystem.occupants.OccupantsFactory;
+import com.kingdee.eas.framework.CoreBillBaseCollection;
+import com.kingdee.eas.framework.ICoreBillBase;
+import com.kingdee.eas.hr.ats.AtsUtil;
+import com.kingdee.eas.hr.base.HRBillBaseEntryInfo;
+import com.kingdee.eas.hr.base.HRBillBaseInfo;
+import com.kingdee.util.StringUtils;
+import org.apache.log4j.Logger;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * @Description 检查入住申请单是否重复、入住信息是否重复
+ * @Date 2025/4/29 17:03
+ * @Created by Heyuan
+ */
+public class CheckDuplicateCheckInByBillIdService implements IHRMsfService {
+    private static Logger logger = Logger.getLogger(CheckDuplicateCheckInByBillIdService.class);
+
+    @Override
+    public Object process(
+            Context ctx,
+            Map<String, Object> params
+    ) throws EASBizException, BOSException {
+        String billIds = (String) params.get("billIds");
+        if (StringUtils.isEmpty(billIds)) {
+            logger.error("单据id不能为空!");
+            throw new BOSException("单据id不能为空!");
+        }
+        Map<String, List<Map<String, Date>>> roomListMap = new HashMap<>();
+        List<String> errorMsgList = new ArrayList<>();
+        ICoreBillBase iCoreBillBase = (ICoreBillBase) BOSObjectFactory.createBOSObject(ctx,
+                BOSUuid.read(billIds.split(",")[0]).getType());
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("*");
+        sic.add("entrys.*");
+        sic.add("entrys.person.*");
+        sic.add("entrys.person.personType.*");
+        sic.add("entrys.checkInRoom.*");
+        sic.add("entrys.checkInRoom.DormitoryType.*");
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //房间
+        filterItems.add(new FilterItemInfo("id", AtsUtil.toSet(billIds), CompareType.INCLUDE));
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        CoreBillBaseCollection hrBillBaseCollection = iCoreBillBase.getCoreBillBaseCollection(viewInfo);
+        for (int i = 0; i < hrBillBaseCollection.size(); i++) {
+            HRBillBaseInfo hrBillBaseInfo = (HRBillBaseInfo) hrBillBaseCollection.get(i);
+            String baseInfoNumber = hrBillBaseInfo.getNumber();
+            //分录
+            AbstractObjectCollection entrys = (AbstractObjectCollection) hrBillBaseInfo.get("entrys");
+            for (int j = 0; j < entrys.size(); j++) {
+                try {
+                    HRBillBaseEntryInfo entryInfo = (HRBillBaseEntryInfo) entrys.getObject(j);
+                    //入住日期
+                    Date checkInDate = entryInfo.getDate("checkInDate");
+                    if (checkInDate == null) {
+                        throw new BOSException("入住日期不能为空!");
+                    }
+                    //退宿日期
+                    Date checkoutDate = entryInfo.getDate("checkoutDate");
+                    if (checkoutDate == null) {
+                        throw new BOSException("退宿日期不能为空!");
+                    }
+                    //人员
+                    PersonInfo personInfo = (PersonInfo) entryInfo.getObjectValue("person");
+                    if (personInfo == null) {
+                        throw new BOSException("人员不能为空!");
+                    }
+                    //1.根据人员、入住日期、退宿日期检查入住申请单是否重复
+                    checkDuplicateCheckIn(ctx, personInfo, checkInDate, checkoutDate, entryInfo);
+                    //2.根据人员、入住日期、退宿日期检查入住人员信息是否重复
+                    checkDuplicateOccupants(ctx, personInfo, checkInDate, checkoutDate);
+                    //3.根据人员、入住日期、退宿日期检查换宿单是否重复
+                    checkDuplicateRoomChange(ctx, personInfo, checkInDate, checkoutDate);
+                } catch (Exception e) {
+                    logger.error("单据编号为" + baseInfoNumber + "校验未通过: " + e.getMessage());
+                    errorMsgList.add("单据编号为" + baseInfoNumber + "校验未通过: " + e.getMessage());
+                }
+            }
+        }
+        Map result = new HashMap();
+        if (errorMsgList.size() > 0) {
+            result.put("code", 500);
+            result.put("errorMsg", errorMsgList);
+        } else {
+            result.put("code", 200);
+        }
+        return result;
+    }
+
+    /**
+     * 根据人员、入住日期、退宿日期检查换宿单是否重复
+     *
+     * @param ctx
+     * @param personInfo
+     * @param checkInDate
+     * @param checkoutDate
+     */
+    protected void checkDuplicateRoomChange(
+            Context ctx,
+            PersonInfo personInfo,
+            Date checkInDate,
+            Date checkoutDate
+    ) throws BOSException {
+        String personInfoName = personInfo.getName();
+        IRoomChangeApplicationEntry iRoomChangeApplicationEntry = RoomChangeApplicationEntryFactory.getLocalInstance(ctx);
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //人员
+        filterItems.add(new FilterItemInfo("person", personInfo.getId()));
+        //申请入住日期在入住日期和退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.LESS_EQUALS));
+        filterItems.add(new FilterItemInfo("checkoutDate", checkInDate, CompareType.GREATER_EQUALS));
+        //入住日期在申请入住日期和申请退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.GREATER_EQUALS));
+        filterItems.add(new FilterItemInfo("checkInDate", checkoutDate, CompareType.LESS_EQUALS));
+        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4))");
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("parent.number");
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        RoomChangeApplicationEntryCollection entryCollection = iRoomChangeApplicationEntry.getRoomChangeApplicationEntryCollection(viewInfo);
+        StringBuilder errorMsg = new StringBuilder();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        for (int i = 0; i < entryCollection.size(); i++) {
+            RoomChangeApplicationEntryInfo roomChangeApplicationEntryInfo = entryCollection.get(i);
+            RoomChangeApplicationInfo parent = roomChangeApplicationEntryInfo.getParent();
+            String number = parent.getNumber();
+            errorMsg.append("员工[" + personInfoName + "]在[" + sdf.format(checkInDate) + "] ~ [" + sdf.format(checkoutDate) + "]期间与换宿申请单[" + number + "]日期存在交叉\n");
+        }
+        if (errorMsg.length() > 0) {
+            throw new BOSException(errorMsg.toString());
+        }
+    }
+
+
+    /**
+     * 根据人员、入住日期、退宿日期检查入住人员信息是否重复
+     *
+     * @param ctx
+     * @param personInfo   人员
+     * @param checkInDate  入住日期
+     * @param checkoutDate 退宿日期
+     * @throws BOSException
+     */
+    protected void checkDuplicateOccupants(
+            Context ctx,
+            PersonInfo personInfo,
+            Date checkInDate,
+            Date checkoutDate
+    ) throws BOSException {
+        String personInfoName = personInfo.getName();
+        IOccupants iOccupants = OccupantsFactory.getLocalInstance(ctx);
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //人员
+        filterItems.add(new FilterItemInfo("person", personInfo.getId()));
+        //申请入住日期在入住日期和退宿日期之间
+        filterItems.add(new FilterItemInfo("CheckInDate", checkInDate, CompareType.LESS_EQUALS));
+        filterItems.add(new FilterItemInfo("CheckOutDate", checkInDate, CompareType.GREATER_EQUALS));
+        //入住日期在申请入住日期和申请退宿日期之间
+        filterItems.add(new FilterItemInfo("CheckInDate", checkInDate, CompareType.GREATER_EQUALS));
+        filterItems.add(new FilterItemInfo("CheckInDate", checkoutDate, CompareType.LESS_EQUALS));
+        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4))");
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("parent.number");
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        OccupantsCollection occupantsCollection = iOccupants.getOccupantsCollection(viewInfo);
+        StringBuilder errorMsg = new StringBuilder();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        if (occupantsCollection.size() > 0) {
+            errorMsg.append("员工[" + personInfoName + "]在[" + sdf.format(checkInDate) + "] ~ [" + sdf.format(checkoutDate) + "]期间与入住信息数据存在日期交叉\n");
+            throw new BOSException(errorMsg.toString());
+        }
+    }
+
+    /**
+     * 根据人员、入住日期、退宿日期检查单据状态为已提交、审批中或审批通过的入住申请单是否重复
+     *
+     * @param ctx
+     * @param personInfo   人员
+     * @param checkInDate  入住日期
+     * @param checkoutDate 退宿日期
+     * @throws BOSException
+     * @throws EASBizException
+     */
+    protected void checkDuplicateCheckIn(
+            Context ctx,
+            PersonInfo personInfo,
+            Date checkInDate,
+            Date checkoutDate,
+            HRBillBaseEntryInfo entryInfo
+    ) throws BOSException {
+        String personInfoName = personInfo.getName();
+        String entryId = entryInfo.getId().toString();
+        ICheckInApplicationEntry iCheckInApplicationEntry = CheckInApplicationEntryFactory.getLocalInstance(ctx);
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //单据状态等于已提交、审批中或审批通过
+        filterItems.add(new FilterItemInfo("parent.billState", "1,2,3", CompareType.INCLUDE));
+        //申请入住日期在入住日期和退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.LESS_EQUALS));
+        filterItems.add(new FilterItemInfo("checkoutDate", checkInDate, CompareType.GREATER_EQUALS));
+        //入住日期在申请入住日期和申请退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.GREATER_EQUALS));
+        filterItems.add(new FilterItemInfo("checkInDate", checkoutDate, CompareType.LESS_EQUALS));
+        //人员
+        filterItems.add(new FilterItemInfo("person", personInfo.getId()));
+        //不等于当前分录数据
+        filterItems.add(new FilterItemInfo("id", entryId, CompareType.NOTEQUALS));
+        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) and #5 and #6");
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("parent.number");
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        CheckInApplicationEntryCollection entryCollection = iCheckInApplicationEntry.getCheckInApplicationEntryCollection(viewInfo);
+        StringBuilder errorMsg = new StringBuilder();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        for (int i = 0; i < entryCollection.size(); i++) {
+            CheckInApplicationEntryInfo checkInApplicationEntryInfo = entryCollection.get(i);
+            CheckInApplicationInfo parent = checkInApplicationEntryInfo.getParent();
+            String number = parent.getNumber();
+            errorMsg.append("员工[" + personInfoName + "]在[" + sdf.format(checkInDate) + "] ~ [" + sdf.format(checkoutDate) + "]期间与入住申请单[" + number + "]日期存在交叉\n");
+        }
+        if (errorMsg.length() > 0) {
+            throw new BOSException(errorMsg.toString());
+        }
+    }
+}

+ 336 - 0
websrc/com/kingdee/eas/custom/dormitorysystem/application/service/ValidateRoomAvailableByBillIdsService.java

@@ -0,0 +1,336 @@
+package com.kingdee.eas.custom.dormitorysystem.application.service;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.BOSObjectFactory;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.bsf.service.app.IHRMsfService;
+import com.kingdee.bos.dao.AbstractObjectCollection;
+import com.kingdee.bos.metadata.entity.*;
+import com.kingdee.bos.metadata.query.util.CompareType;
+import com.kingdee.bos.util.BOSUuid;
+import com.kingdee.eas.basedata.person.Genders;
+import com.kingdee.eas.basedata.person.PersonInfo;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.custom.dormitorysystem.application.CheckInApplicationEntryCollection;
+import com.kingdee.eas.custom.dormitorysystem.application.CheckInApplicationEntryFactory;
+import com.kingdee.eas.custom.dormitorysystem.application.CheckInApplicationEntryInfo;
+import com.kingdee.eas.custom.dormitorysystem.application.ICheckInApplicationEntry;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.DormitoryFactory;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.DormitoryInfo;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.IDormitory;
+import com.kingdee.eas.custom.dormitorysystem.enumerationset.DormitoryClassification;
+import com.kingdee.eas.custom.dormitorysystem.occupants.IOccupants;
+import com.kingdee.eas.custom.dormitorysystem.occupants.OccupantsCollection;
+import com.kingdee.eas.custom.dormitorysystem.occupants.OccupantsFactory;
+import com.kingdee.eas.custom.dormitorysystem.occupants.OccupantsInfo;
+import com.kingdee.eas.custom.dormitorysystem.otherbasicdata.DormitoryTypeInfo;
+import com.kingdee.eas.custom.dormitorysystem.otherbasicdata.PersonDormitoryTypeInfo;
+import com.kingdee.eas.framework.*;
+import com.kingdee.eas.hr.ats.AtsUtil;
+import com.kingdee.eas.hr.base.*;
+import com.kingdee.shr.base.syssetting.BasicItemStateEnum;
+import com.kingdee.util.StringUtils;
+import org.apache.log4j.Logger;
+
+import java.util.*;
+
+/**
+ * @Description 根据单据id校验房间是否入住(批量)
+ * @Date 2025/4/27 17:00
+ * @Created by Heyuan
+ */
+public class ValidateRoomAvailableByBillIdsService implements IHRMsfService {
+    private static Logger logger = Logger.getLogger(ValidateRoomAvailableByBillIdsService.class);
+//    private static Map<String, ICoreBase> bizInterface = new HashMap();
+//    static {
+//        bizInterface.put("",)
+//    }
+
+    @Override
+    public Object process(
+            Context ctx,
+            Map<String, Object> params
+    ) throws EASBizException, BOSException {
+        String billIds = (String) params.get("billIds");
+        if (StringUtils.isEmpty(billIds)) {
+            logger.error("单据id不能为空!");
+            throw new BOSException("单据id不能为空!");
+        }
+        //BatchMessageTipsHeader batchMessageTipsHeader = new BatchMessageTipsHeader();
+        // addBatchMessageTips(ids, "面谈通知发送失败", batchMessageTipsHeader);
+        Map<String, List<Map<String, Date>>> roomListMap = new HashMap<String, List<Map<String, Date>>>();
+        //StringBuilder errorMsg = new StringBuilder();
+        List<String> errorMsgList = new ArrayList<String>();
+        // HRBillBaseFactory.getLocalInstance()
+        ICoreBillBase iCoreBillBase = (ICoreBillBase) BOSObjectFactory.createBOSObject(ctx,
+                BOSUuid.read(billIds.split(",")[0]).getType());
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("*");
+        sic.add("entrys.*");
+        sic.add("entrys.person.*");
+        sic.add("entrys.person.personType.*");
+        sic.add("entrys.checkInRoom.*");
+        sic.add("entrys.checkInRoom.DormitoryType.*");
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //房间
+        filterItems.add(new FilterItemInfo("id", AtsUtil.toSet(billIds), CompareType.INCLUDE));
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        CoreBillBaseCollection hrBillBaseCollection = iCoreBillBase.getCoreBillBaseCollection(viewInfo);
+        for (int i = 0; i < hrBillBaseCollection.size(); i++) {
+            HRBillBaseInfo hrBillBaseInfo = (HRBillBaseInfo) hrBillBaseCollection.get(i);
+            //String billId = hrBillBaseInfo.getId().toString();
+            String baseInfoNumber = hrBillBaseInfo.getNumber();
+            String bosType = hrBillBaseInfo.getId().getType().toString();
+            AbstractObjectCollection entrys = (AbstractObjectCollection) hrBillBaseInfo.get("entrys");
+            for (int j = 0; j < entrys.size(); j++) {
+                try {
+                    HRBillBaseEntryInfo entryInfo = (HRBillBaseEntryInfo) entrys.getObject(j);
+                    Date checkInDate = null;
+                    if ("B371AC0A".equals(bosType)) {
+                        //换宿单
+                        //入住日期
+                        checkInDate = entryInfo.getDate("adjustmentDate");
+                    } else {
+                        //入住日期
+                        checkInDate = entryInfo.getDate("checkInDate");
+                    }
+                    if (checkInDate == null) {
+                        throw new BOSException("入住日期不能为空!");
+                    }
+                    //退宿日期
+                    Date checkoutDate = entryInfo.getDate("checkoutDate");
+                    if (checkoutDate == null) {
+                        throw new BOSException("退宿日期不能为空!");
+                    }
+                    //人员
+                    PersonInfo personInfo = (PersonInfo) entryInfo.getObjectValue("person");
+                    if (personInfo == null) {
+                        throw new BOSException("人员不能为空!");
+                    }
+                    //房间
+                    DormitoryInfo dormitory = (DormitoryInfo) entryInfo.getObjectValue("checkInRoom");
+                    if (dormitory == null) {
+                        throw new BOSException("房间不能为空!");
+                    }
+                    String roomId = dormitory.getId().toString();
+                    //根据入住日期,性别,员工类别查询可选房间
+                    //人员类型
+                    PersonDormitoryTypeInfo personType = (PersonDormitoryTypeInfo) personInfo.get("personType");
+                    if (personType == null) {
+                        throw new BOSException("员工[" + personInfo.getName() + "]的人员类别为空,请及时维护!");
+                    }
+                    //String personTypeId = personType.getId().toString();
+                    //已住人数
+                    int dormCheckInCount = 0;
+                    //1.校验房间信息
+                    validateDormitoryInfo(ctx, personInfo, dormitory);
+                    //可住人数
+                    int occupancyCapacity = dormitory.getOccupancyCapacity();
+                    //2.根据入住日期和退宿日期算出入住信息房间已住人数
+                    dormCheckInCount += getCheckInInfoByOccupants(ctx, checkInDate, checkoutDate, roomId, personType);
+                    //3.根据入住日期和退宿日期算出入住申请单状态为申请中的已住人数
+                    dormCheckInCount += getCheckInInfoByCheckInApplication(ctx, checkInDate, checkoutDate, roomId, personType);
+                    //4.根据当前参数缓存算出已住人数
+                    if (roomListMap.containsKey(roomId)) {
+                        List<Map<String, Date>> roomMapList = roomListMap.get(roomId);
+                        for (int k = 0; k < roomMapList.size(); k++) {
+                            Map<String, Date> roomMap = roomMapList.get(k);
+                            Date checkInDateOld = roomMap.get("checkInDate");
+                            Date checkoutDateOld = roomMap.get("checkoutDate");
+                            //申请入住日期在入住日期和退宿日期之间
+                            //入住日期在申请入住日期和申请退宿日期之间
+                            if ((checkInDateOld.compareTo(checkInDate) <= 0 && checkoutDateOld.compareTo(checkInDate) >= 0)
+                                    || (checkInDateOld.compareTo(checkInDate) >= 0 && checkInDateOld.compareTo(checkoutDate) <= 0)) {
+                                dormCheckInCount++;
+                            }
+                        }
+                    }
+                    //5.算出房间剩余可住人数: 可住人数 - 已住人数
+                    if (occupancyCapacity - dormCheckInCount < 0) {
+                        String dormitoryName = dormitory.getName();
+                        throw new BOSException("当前入住人数" + dormCheckInCount + ",已超过房间[" + dormitoryName + "]可住人数" + occupancyCapacity + ",不能入住!");
+                    }
+                    Map roomMap = new HashMap();
+                    roomMap.put("checkInDate", checkInDate);
+                    roomMap.put("checkoutDate", checkoutDate);
+                    if (roomListMap.containsKey(roomId)) {
+                        roomListMap.get(roomId).add(roomMap);
+                    } else {
+                        List list = new ArrayList();
+                        roomListMap.put(roomId, list);
+                        list.add(roomMap);
+                    }
+                } catch (Exception e) {
+                    logger.error("单据编号为" + baseInfoNumber + "校验未通过: " + e.getMessage());
+                    errorMsgList.add("单据编号为" + baseInfoNumber + "校验未通过: " + e.getMessage());
+                    //errorMsg.append("单据编号为").append(baseInfoNumber).append("校验未通过: ").append(e.getMessage()).append(System.lineSeparator());
+                }
+            }
+        }
+        Map result = new HashMap();
+        if (errorMsgList.size() > 0) {
+            result.put("code", 500);
+            result.put("errorMsg", errorMsgList);
+        } else {
+            result.put("code", 200);
+        }
+        return result;
+    }
+
+    /**
+     * 根据入住日期和退宿日期算出入住申请单状态为申请中的已住人数
+     *
+     * @param ctx
+     * @param checkInDate  入住日期
+     * @param checkoutDate 退宿日期
+     * @param roomId       房间id
+     * @param personType   人员类型
+     * @return
+     * @throws BOSException
+     */
+    private int getCheckInInfoByCheckInApplication(
+            Context ctx,
+            Date checkInDate,
+            Date checkoutDate,
+            String roomId,
+            PersonDormitoryTypeInfo personType
+    ) throws BOSException {
+        ICheckInApplicationEntry iCheckInApplicationEntry = CheckInApplicationEntryFactory.getLocalInstance(ctx);
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //房间
+        filterItems.add(new FilterItemInfo("checkInRoom", roomId));
+        //申请入住日期在入住日期和退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.LESS_EQUALS));
+        filterItems.add(new FilterItemInfo("checkoutDate", checkInDate, CompareType.GREATER_EQUALS));
+        //入住日期在申请入住日期和申请退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.GREATER_EQUALS));
+        filterItems.add(new FilterItemInfo("checkInDate", checkoutDate, CompareType.LESS_EQUALS));
+        //单据状态等于审批中
+        filterItems.add(new FilterItemInfo("parent.billState", "3"));
+        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) and #5");
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("checkInRoom.id");
+        sic.add("person.personType.id");
+        sic.add("person.personType.name");
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        CheckInApplicationEntryCollection checkInApplicationEntryCol = iCheckInApplicationEntry.getCheckInApplicationEntryCollection(viewInfo);
+        String personTypeId = personType.getId().toString();
+        String personTypeName = personType.getName();
+        //已住人数
+        int dormCheckInCount = 0;
+        for (int i = 0; i < checkInApplicationEntryCol.size(); i++) {
+            CheckInApplicationEntryInfo checkInApplicationEntryInfo = checkInApplicationEntryCol.get(i);
+            //房间
+            PersonInfo person = checkInApplicationEntryInfo.getPerson();
+            String personName = person.getName();
+            //人员类型
+            PersonDormitoryTypeInfo personDormitoryType = (PersonDormitoryTypeInfo) person.get("personType");
+            if (personDormitoryType == null) {
+                throw new BOSException("员工[" + personName + "]的人员类别为空,请及时维护!");
+            }
+            String personDormitoryTypeId = personDormitoryType.getId().toString();
+            String personDormitoryTypeName = personDormitoryType.getName();
+            if (!personTypeId.equals(personDormitoryTypeId)) {
+                throw new BOSException("人员类别[" + personTypeName + "]与宿舍类型[" + personDormitoryTypeName + "]不符,不能入住!");
+            }
+            //累计已住人数
+            dormCheckInCount++;
+        }
+        return dormCheckInCount;
+    }
+
+
+    /**
+     * 根据入住日期和退宿日期算出入住信息中每个房间已住人数
+     *
+     * @param ctx
+     * @param checkInDate  入住日期
+     * @param checkoutDate 退宿日期
+     * @param roomId       房间id
+     * @param personType   人员类型
+     * @return
+     * @throws BOSException
+     */
+    protected int getCheckInInfoByOccupants(
+            Context ctx,
+            Date checkInDate,
+            Date checkoutDate,
+            String roomId,
+            PersonDormitoryTypeInfo personType
+    ) throws BOSException {
+        IOccupants iOccupants = OccupantsFactory.getLocalInstance(ctx);
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //房间
+        filterItems.add(new FilterItemInfo("Dormitory", roomId));
+        //申请入住日期在入住日期和退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.LESS_EQUALS));
+        filterItems.add(new FilterItemInfo("checkoutDate", checkInDate, CompareType.GREATER_EQUALS));
+        //入住日期在申请入住日期和申请退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.GREATER_EQUALS));
+        filterItems.add(new FilterItemInfo("checkInDate", checkoutDate, CompareType.LESS_EQUALS));
+        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) ");
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("PersonDormitoryType.id");
+        sic.add("PersonDormitoryType.name");
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        OccupantsCollection occupantsCollection = iOccupants.getOccupantsCollection(viewInfo);
+        String personTypeId = personType.getId().toString();
+        String personTypeName = personType.getName();
+        //已住人数
+        int dormCheckInCount = 0;
+        String personDormitoryTypeId = null;
+        for (int i = 0; i < occupantsCollection.size(); i++) {
+            OccupantsInfo occupantsInfo = occupantsCollection.get(i);
+            //人员宿舍分类
+            PersonDormitoryTypeInfo personDormitoryType = occupantsInfo.getPersonDormitoryType();
+            personDormitoryTypeId = personDormitoryType.getId().toString();
+            String personDormitoryTypeName = personDormitoryType.getName();
+            if (!personTypeId.equals(personDormitoryTypeId)) {
+                throw new BOSException("人员类别[" + personTypeName + "]与宿舍类型[" + personDormitoryTypeName + "]不符,不能入住!");
+            }
+            dormCheckInCount++;
+        }
+        return dormCheckInCount;
+    }
+
+    /**
+     * 校验房间信息
+     *
+     * @param ctx
+     * @param personInfo
+     * @param dormitory  房间
+     * @return
+     * @throws BOSException
+     * @throws EASBizException
+     */
+    protected void validateDormitoryInfo(
+            Context ctx,
+            PersonInfo personInfo,
+            DormitoryInfo dormitory
+    ) throws BOSException, EASBizException {
+        Genders gender = personInfo.getGender();
+        String personInfoName = personInfo.getName();
+        IDormitory iDormitory = DormitoryFactory.getLocalInstance(ctx);
+        //查询房间信息
+        String dormitoryName = dormitory.getName();
+        DormitoryClassification roomClassification = dormitory.getRoomClassification();
+        if (!DormitoryClassification.ROOM.equals(roomClassification)) {
+            String classificationAlias = roomClassification.getAlias();
+            throw new BOSException("房间[" + dormitoryName + "]房间归类为" + classificationAlias + ",不能入住!");
+        }
+        BasicItemStateEnum dormitoryInfoState = dormitory.getState();
+        if (BasicItemStateEnum.DISABLE.equals(dormitoryInfoState)) {
+            throw new BOSException("房间[" + dormitoryName + "]未启用,不能入住!");
+        }
+        //宿舍类型
+        DormitoryTypeInfo dormitoryType = dormitory.getDormitoryType();
+        Genders roomGender = dormitoryType.getGender();
+        if (roomGender != null && gender.getValue() != roomGender.getValue()) {
+            String dormitoryTypeName = dormitoryType.getName();
+            throw new BOSException("房间[" + dormitoryName + "]宿舍类型为" + dormitoryTypeName + ",与人员[" + personInfoName + "]的性别不符!");
+        }
+    }
+}

+ 316 - 0
websrc/com/kingdee/eas/custom/dormitorysystem/application/service/ValidateRoomAvailableService.java

@@ -0,0 +1,316 @@
+package com.kingdee.eas.custom.dormitorysystem.application.service;
+
+import com.kingdee.eas.custom.dormitorysystem.enumerationset.DormitoryClassification;
+import com.kingdee.eas.custom.dormitorysystem.otherbasicdata.DormitoryTypeInfo;
+import com.kingdee.shr.base.syssetting.BasicItemStateEnum;
+import org.apache.log4j.Logger;
+import org.json.JSONArray;
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.bsf.service.app.IHRMsfService;
+import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
+import com.kingdee.bos.metadata.entity.*;
+import com.kingdee.bos.metadata.query.util.CompareType;
+import com.kingdee.eas.basedata.person.Genders;
+import com.kingdee.eas.basedata.person.IPerson;
+import com.kingdee.eas.basedata.person.PersonFactory;
+import com.kingdee.eas.basedata.person.PersonInfo;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.custom.dormitorysystem.application.CheckInApplicationEntryCollection;
+import com.kingdee.eas.custom.dormitorysystem.application.CheckInApplicationEntryFactory;
+import com.kingdee.eas.custom.dormitorysystem.application.CheckInApplicationEntryInfo;
+import com.kingdee.eas.custom.dormitorysystem.application.ICheckInApplicationEntry;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.DormitoryFactory;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.DormitoryInfo;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.IDormitory;
+import com.kingdee.eas.custom.dormitorysystem.occupants.IOccupants;
+import com.kingdee.eas.custom.dormitorysystem.occupants.OccupantsCollection;
+import com.kingdee.eas.custom.dormitorysystem.occupants.OccupantsFactory;
+import com.kingdee.eas.custom.dormitorysystem.occupants.OccupantsInfo;
+import com.kingdee.eas.custom.dormitorysystem.otherbasicdata.PersonDormitoryTypeInfo;
+import com.kingdee.util.DateTimeUtils;
+import com.kingdee.util.StringUtils;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.*;
+
+/**
+ * @Description 校验房间是否入住(批量)
+ * @Date 2025/4/27 17:00
+ * @Created by Heyuan
+ */
+public class ValidateRoomAvailableService implements IHRMsfService {
+    private static Logger logger = Logger.getLogger(ValidateRoomAvailableService.class);
+
+    @Override
+    public Object process(
+            Context ctx,
+            Map<String, Object> params
+    ) throws EASBizException, BOSException {
+        String validateDataStr = (String) params.get("validateData");
+        if (StringUtils.isEmpty(validateDataStr)) {
+            logger.error("校验数据不能为空!");
+            throw new BOSException("校验数据不能为空!");
+        }
+        JSONArray validateDatas = null;
+        try {
+            validateDatas = new JSONArray(validateDataStr);
+        } catch (JSONException e) {
+            logger.error(e);
+            throw new RuntimeException(e);
+        }
+        Map<String, List<Map<String, Date>>> roomListMap = new HashMap<String, List<Map<String, Date>>>();
+        StringBuilder errorMsg = new StringBuilder();
+        for (int i = 0; i < validateDatas.length(); i++) {
+            try {
+                JSONObject jsonObject = validateDatas.getJSONObject(i);
+                //入住日期
+                String checkInDateStr = jsonObject.getString("checkInDate");
+                if (StringUtils.isEmpty(checkInDateStr)) {
+                    throw new BOSException("入住日期不能为空!");
+                }
+                //退宿日期
+                String checkoutDateStr = jsonObject.getString("checkoutDate");
+                if (StringUtils.isEmpty(checkInDateStr)) {
+                    throw new BOSException("退宿日期不能为空!");
+                }
+                //人员id
+                String personId = jsonObject.getString("personId");
+                if (StringUtils.isEmpty(personId)) {
+                    throw new BOSException("人员id不能为空!");
+                }
+                //房间id
+                String roomId = jsonObject.getString("roomId");
+                if (StringUtils.isEmpty(personId)) {
+                    throw new BOSException("房间id不能为空!");
+                }
+                //入住日期
+                Date checkInDate = DateTimeUtils.parseDate(checkInDateStr, "yyyy-MM-dd");
+                Date checkoutDate = DateTimeUtils.parseDate(checkoutDateStr, "yyyy-MM-dd");
+                //根据入住日期,性别,员工类别查询可选房间
+                IPerson iPerson = PersonFactory.getLocalInstance(ctx);
+                SelectorItemCollection sic = new SelectorItemCollection();
+                sic.add("gender");
+                sic.add("personType.*");
+                sic.add("name");
+                PersonInfo personInfo = iPerson.getPersonInfo(new ObjectUuidPK(personId), sic);
+                //人员类型
+                PersonDormitoryTypeInfo personType = (PersonDormitoryTypeInfo) personInfo.get("personType");
+                if (personType == null) {
+                    throw new BOSException("员工[" + personInfo.getName() + "]的人员类别为空,请及时维护!");
+                }
+                //String personTypeId = personType.getId().toString();
+                //已住人数
+                int dormCheckInCount = 0;
+                //1.校验房间信息
+                DormitoryInfo dormitoryInfo = validateDormitoryInfo(ctx, personInfo, roomId);
+                //可住人数
+                int occupancyCapacity = dormitoryInfo.getOccupancyCapacity();
+                //2.根据入住日期和退宿日期算出入住信息房间已住人数
+                dormCheckInCount += getCheckInInfoByOccupants(ctx, checkInDate, checkoutDate, roomId, personType);
+                //3.根据入住日期和退宿日期算出入住申请单状态为申请中的已住人数
+                dormCheckInCount += getCheckInInfoByCheckInApplication(ctx, checkInDate, checkoutDate, roomId, personType);
+                //4.根据当前参数缓存算出已住人数
+                if (roomListMap.containsKey(roomId)) {
+                    List<Map<String, Date>> roomMapList = roomListMap.get(roomId);
+                    for (int j = 0; j < roomMapList.size(); j++) {
+                        Map<String, Date> roomMap = roomMapList.get(j);
+                        Date checkInDateOld = roomMap.get("checkInDate");
+                        Date checkoutDateOld = roomMap.get("checkoutDate");
+                        //申请入住日期在入住日期和退宿日期之间
+                        //入住日期在申请入住日期和申请退宿日期之间
+                        if ((checkInDateOld.compareTo(checkInDate) <= 0 && checkoutDateOld.compareTo(checkInDate) >= 0)
+                                || (checkInDateOld.compareTo(checkInDate) >= 0 && checkInDateOld.compareTo(checkoutDate) <= 0)) {
+                            dormCheckInCount++;
+                        }
+                    }
+                }
+                //5.算出房间剩余可住人数: 可住人数 - 已住人数
+                if (occupancyCapacity - dormCheckInCount < 0) {
+                    String dormitoryName = dormitoryInfo.getName();
+                    throw new BOSException("当前入住人数" + dormCheckInCount + ",已超过房间[" + dormitoryName + "]可住人数" + occupancyCapacity + ",不能入住!");
+                }
+                Map roomMap = new HashMap();
+                roomMap.put("checkInDate", checkInDate);
+                roomMap.put("checkoutDate", checkoutDate);
+                if (roomListMap.containsKey(roomId)) {
+                    roomListMap.get(roomId).add(roomMap);
+                } else {
+                    List list = new ArrayList();
+                    roomListMap.put(roomId, list);
+                    list.add(roomMap);
+                }
+            } catch (Exception e) {
+                logger.error(e);
+                errorMsg.append(e.getMessage()).append(System.lineSeparator());
+            }
+        }
+        Map result = new HashMap();
+        if (errorMsg.length() > 0) {
+            result.put("code", 500);
+            result.put("errorMsg", errorMsg.toString());
+        } else {
+            result.put("code", 200);
+        }
+        return result;
+    }
+
+    /**
+     * 根据入住日期和退宿日期算出入住申请单状态为申请中的已住人数
+     *
+     * @param ctx
+     * @param checkInDate  入住日期
+     * @param checkoutDate 退宿日期
+     * @param roomId       房间id
+     * @param personType   人员类型
+     * @return
+     * @throws BOSException
+     */
+    private int getCheckInInfoByCheckInApplication(
+            Context ctx,
+            Date checkInDate,
+            Date checkoutDate,
+            String roomId,
+            PersonDormitoryTypeInfo personType
+    ) throws BOSException {
+        ICheckInApplicationEntry iCheckInApplicationEntry = CheckInApplicationEntryFactory.getLocalInstance(ctx);
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //房间
+        filterItems.add(new FilterItemInfo("checkInRoom", roomId));
+        //申请入住日期在入住日期和退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.LESS_EQUALS));
+        filterItems.add(new FilterItemInfo("checkoutDate", checkInDate, CompareType.GREATER_EQUALS));
+        //入住日期在申请入住日期和申请退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.GREATER_EQUALS));
+        filterItems.add(new FilterItemInfo("checkInDate", checkoutDate, CompareType.LESS_EQUALS));
+        //单据状态等于审批中
+        filterItems.add(new FilterItemInfo("parent.billState", "3"));
+        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) and #5");
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("checkInRoom.id");
+        sic.add("person.personType.id");
+        sic.add("person.personType.name");
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        CheckInApplicationEntryCollection checkInApplicationEntryCol = iCheckInApplicationEntry.getCheckInApplicationEntryCollection(viewInfo);
+        String personTypeId = personType.getId().toString();
+        String personTypeName = personType.getName();
+        //已住人数
+        int dormCheckInCount = 0;
+        for (int i = 0; i < checkInApplicationEntryCol.size(); i++) {
+            CheckInApplicationEntryInfo checkInApplicationEntryInfo = checkInApplicationEntryCol.get(i);
+            //房间
+            PersonInfo person = checkInApplicationEntryInfo.getPerson();
+            String personName = person.getName();
+            //人员类型
+            PersonDormitoryTypeInfo personDormitoryType = (PersonDormitoryTypeInfo) person.get("personType");
+            if (personDormitoryType == null) {
+                throw new BOSException("员工[" + personName + "]的人员类别为空,请及时维护!");
+            }
+            String personDormitoryTypeId = personDormitoryType.getId().toString();
+            String personDormitoryTypeName = personDormitoryType.getName();
+            if (!personTypeId.equals(personDormitoryTypeId)) {
+                throw new BOSException("人员类别[" + personTypeName + "]与宿舍类型[" + personDormitoryTypeName + "]不符,不能入住!");
+            }
+            //累计已住人数
+            dormCheckInCount++;
+        }
+        return dormCheckInCount;
+    }
+
+
+    /**
+     * 根据入住日期和退宿日期算出入住信息中每个房间已住人数
+     *
+     * @param ctx
+     * @param checkInDate  入住日期
+     * @param checkoutDate 退宿日期
+     * @param roomId       房间id
+     * @param personType   人员类型
+     * @return
+     * @throws BOSException
+     */
+    protected int getCheckInInfoByOccupants(
+            Context ctx,
+            Date checkInDate,
+            Date checkoutDate,
+            String roomId,
+            PersonDormitoryTypeInfo personType
+    ) throws BOSException {
+        IOccupants iOccupants = OccupantsFactory.getLocalInstance(ctx);
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        //房间
+        filterItems.add(new FilterItemInfo("Dormitory", roomId));
+        //申请入住日期在入住日期和退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.LESS_EQUALS));
+        filterItems.add(new FilterItemInfo("checkoutDate", checkInDate, CompareType.GREATER_EQUALS));
+        //入住日期在申请入住日期和申请退宿日期之间
+        filterItems.add(new FilterItemInfo("checkInDate", checkInDate, CompareType.GREATER_EQUALS));
+        filterItems.add(new FilterItemInfo("checkInDate", checkoutDate, CompareType.LESS_EQUALS));
+        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) ");
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("PersonDormitoryType.id");
+        sic.add("PersonDormitoryType.name");
+        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+        OccupantsCollection occupantsCollection = iOccupants.getOccupantsCollection(viewInfo);
+        String personTypeId = personType.getId().toString();
+        String personTypeName = personType.getName();
+        //已住人数
+        int dormCheckInCount = 0;
+        String personDormitoryTypeId = null;
+        for (int i = 0; i < occupantsCollection.size(); i++) {
+            OccupantsInfo occupantsInfo = occupantsCollection.get(i);
+            //人员宿舍分类
+            PersonDormitoryTypeInfo personDormitoryType = occupantsInfo.getPersonDormitoryType();
+            personDormitoryTypeId = personDormitoryType.getId().toString();
+            String personDormitoryTypeName = personDormitoryType.getName();
+            if (!personTypeId.equals(personDormitoryTypeId)) {
+                throw new BOSException("人员类别[" + personTypeName + "]与宿舍类型[" + personDormitoryTypeName + "]不符,不能入住!");
+            }
+            dormCheckInCount++;
+        }
+        return dormCheckInCount;
+    }
+
+    /**
+     * 校验房间信息
+     *
+     * @param ctx
+     * @param personInfo
+     * @param roomIds    房间id
+     * @return
+     * @throws BOSException
+     * @throws EASBizException
+     */
+    protected DormitoryInfo validateDormitoryInfo(
+            Context ctx,
+            PersonInfo personInfo,
+            String roomIds
+    ) throws BOSException, EASBizException {
+        Genders gender = personInfo.getGender();
+        String personInfoName = personInfo.getName();
+        IDormitory iDormitory = DormitoryFactory.getLocalInstance(ctx);
+        //查询房间信息
+        DormitoryInfo dormitoryInfo = iDormitory.getDormitoryInfo(new ObjectUuidPK(roomIds));
+        String dormitoryName = dormitoryInfo.getName();
+        DormitoryClassification roomClassification = dormitoryInfo.getRoomClassification();
+        if (!DormitoryClassification.ROOM.equals(roomClassification)) {
+            String classificationAlias = roomClassification.getAlias();
+            throw new BOSException("房间[" + dormitoryName + "]房间归类为" + classificationAlias + ",不能入住!");
+        }
+        BasicItemStateEnum dormitoryInfoState = dormitoryInfo.getState();
+        if (BasicItemStateEnum.DISABLE.equals(dormitoryInfoState)) {
+            throw new BOSException("房间[" + dormitoryName + "]未启用,不能入住!");
+        }
+        //宿舍类型
+        DormitoryTypeInfo dormitoryType = dormitoryInfo.getDormitoryType();
+        Genders roomGender = dormitoryType.getGender();
+        if (roomGender != null && gender.getValue() != roomGender.getValue()) {
+            String dormitoryTypeName = dormitoryType.getName();
+            throw new BOSException("房间[" + dormitoryName + "]宿舍类型为" + dormitoryTypeName + ",与人员[" + personInfoName + "]的性别不符!");
+        }
+        return dormitoryInfo;
+    }
+}

+ 41 - 0
websrc/com/kingdee/eas/custom/dormitorysystem/service/GetLastMWaterPowerService.java

@@ -0,0 +1,41 @@
+package com.kingdee.eas.custom.dormitorysystem.service;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.bsf.service.app.IHRMsfService;
+import com.kingdee.bos.metadata.entity.FilterInfo;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.custom.dormitorysystem.waterpower.utils.WaterPowerUtil;
+import com.kingdee.shr.base.syssetting.exception.SHRWebException;
+import com.kingdee.shr.base.syssetting.web.json.JSONUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+
+
+/**
+ * 获取房间最后一次水电表读数服务
+ */
+public class GetLastMWaterPowerService  implements IHRMsfService {
+    private static final Logger logger = LoggerFactory.getLogger(GetLastMWaterPowerService.class);
+
+    @Override
+    public Object process(Context ctx, Map<String, Object> param) throws EASBizException, BOSException {
+        if (ctx == null) {
+            throw new BOSException("上下文Context不能为空");
+        }
+        String roomId = (String) param.get("roomId");//宿舍编码
+        String years = (String) param.get("years");//年月
+        if (StringUtils.isNotBlank(roomId) && StringUtils.isNotBlank(years)) {
+            Map lastWaterPowerTons = WaterPowerUtil.getLastWaterPowerTons(ctx, years, roomId);
+            return lastWaterPowerTons;
+        }
+        return null;
+    }
+}
+
+
+

+ 72 - 0
websrc/com/kingdee/eas/custom/dormitorysystem/service/GetRoomListService.java

@@ -0,0 +1,72 @@
+package com.kingdee.eas.custom.dormitorysystem.service;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.bsf.service.app.IHRMsfService;
+import com.kingdee.bos.metadata.data.SortType;
+import com.kingdee.bos.metadata.entity.*;
+import com.kingdee.bos.metadata.query.util.CompareType;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.DormitoryCollection;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.DormitoryFactory;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.IDormitory;
+import com.kingdee.eas.custom.dormitorysystem.waterpower.IWaterPowerMeterReading;
+import com.kingdee.eas.custom.dormitorysystem.waterpower.WaterPowerMeterReadingCollection;
+import com.kingdee.eas.custom.dormitorysystem.waterpower.WaterPowerMeterReadingFactory;
+import com.kingdee.shr.base.syssetting.exception.SHRWebException;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAdjusters;
+import java.util.Map;
+
+/**
+ * 获取水电表读数服务
+ */
+public class GetRoomListService implements IHRMsfService {
+
+    private static final Logger logger = LoggerFactory.getLogger(GetRoomListService.class);
+    // 定义日期格式化器,避免重复创建
+
+    @Override
+    public Object process(Context ctx, Map<String, Object> param) throws EASBizException, BOSException {
+
+        if (ctx == null) {
+            throw new BOSException("上下文Context不能为空");
+        }
+        FilterInfo filterInfo = new FilterInfo();
+        // 3. 处理房间号参数
+        Object roomNumberObj = param.get("roomNumber");
+        if (roomNumberObj != null && !StringUtils.isEmpty(roomNumberObj.toString())) {
+            String roomNumber = roomNumberObj.toString().trim();
+            filterInfo.getFilterItems().add(new FilterItemInfo("dormitory.number", "%" + roomNumber+"%", CompareType.LIKE));
+            filterInfo.getFilterItems().add(new FilterItemInfo("dormitory.name", "%" + roomNumber+"%", CompareType.LIKE));
+            logger.info("添加房间号过滤条件:dormitory.id = {}", roomNumber);
+        }
+        // 4. 构建查询结果并返回
+        return buildWaterPowerCollection(ctx, filterInfo);
+    }
+
+    /**
+     * 构建排序条件并查询水电表读数集合
+     * 抽离通用逻辑,提高代码复用性
+     */
+    private DormitoryCollection buildWaterPowerCollection(Context ctx, FilterInfo filterInfo) throws BOSException {
+        // 构建排序条件
+        SorterItemCollection sorterItemCollection = new SorterItemCollection();
+        SorterItemInfo longNum = new SorterItemInfo("longNumber"); //长编码
+        sorterItemCollection.add(longNum);
+        sorterItemCollection.add(new SorterItemInfo("level")); // 层级
+        // 构建视图并查询
+        EntityViewInfo entityViewInfo = new EntityViewInfo();
+        entityViewInfo.setFilter(filterInfo);
+        entityViewInfo.setSorter(sorterItemCollection);
+        IDormitory wpIns = DormitoryFactory.getLocalInstance(ctx);
+        DormitoryCollection wpCol = wpIns.getDormitoryCollection(entityViewInfo);
+        logger.info("查询到水电表读数记录数:{}", wpCol.size());
+        return wpCol;
+    }
+}

+ 224 - 0
websrc/com/kingdee/eas/custom/dormitorysystem/service/GetWaterPowerReadingService.java

@@ -0,0 +1,224 @@
+package com.kingdee.eas.custom.dormitorysystem.service;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.bsf.service.app.IHRMsfService;
+import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
+import com.kingdee.bos.metadata.data.SortType;
+import com.kingdee.bos.metadata.entity.EntityViewInfo;
+import com.kingdee.bos.metadata.entity.FilterInfo;
+import com.kingdee.bos.metadata.entity.FilterItemInfo;
+import com.kingdee.bos.metadata.entity.SelectorItemCollection;
+import com.kingdee.bos.metadata.entity.SelectorItemInfo;
+import com.kingdee.bos.metadata.entity.SorterItemCollection;
+import com.kingdee.bos.metadata.entity.SorterItemInfo;
+import com.kingdee.bos.metadata.query.util.CompareType;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.custom.dormitorysystem.waterpower.IWaterPowerMeterReading;
+import com.kingdee.eas.custom.dormitorysystem.waterpower.WaterPowerMeterReadingCollection;
+import com.kingdee.eas.custom.dormitorysystem.waterpower.WaterPowerMeterReadingFactory;
+import com.kingdee.eas.custom.dormitorysystem.waterpower.WaterPowerMeterReadingInfo;
+import com.kingdee.shr.base.syssetting.exception.SHRWebException;
+import com.kingdee.util.NumericExceptionSubItem;
+import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAdjusters;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 水电表读数查询服务
+ * coyle
+ */
+public class GetWaterPowerReadingService implements IHRMsfService {
+
+    private static final Logger logger = LoggerFactory.getLogger(GetWaterPowerReadingService.class);
+    // 仅保留使用的日期格式化器
+    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+
+
+    @Override
+    public Object process(Context ctx, Map<String, Object> param) throws EASBizException, BOSException {
+        // 1. 基础参数校验,防止空指针
+        if (param == null) {
+            logger.warn("查询水电表读数时,入参param为null,返回空集合");
+            return new WaterPowerMeterReadingCollection();
+        }
+        if (ctx == null) {
+            logger.error("查询水电表读数时,上下文Context为null");
+            throw new BOSException("上下文Context不能为空");
+        }
+
+        
+        FilterInfo filterInfo = new FilterInfo();
+        Object fidObj = param.get("fid");
+        if (fidObj != null && !StringUtils.isEmpty(fidObj.toString())) {
+            String fid = fidObj.toString().trim();
+            fid = getString(fid);
+            buildWaterPowerInfo(ctx, fid);
+        }else{
+
+            // 标记各过滤条件是否存在,用于动态构建maskString
+            boolean hasDateFilter = false;
+            boolean hasRoomFilter = false;
+            boolean hasDataTypeFilter = false;
+            // 存储过滤条件的逻辑片段,最后拼接成maskString
+            List<String> filterLogicSegments = new ArrayList<>();
+
+
+            // 2. 处理日期参数(原years参数,语义为查询月份/日期)
+            Object dateParamObj = param.get("years");
+            if (dateParamObj != null && !StringUtils.isEmpty(dateParamObj.toString())) {
+                String dateParam = dateParamObj.toString().trim();
+                dateParam = getString(dateParam);
+                try {
+                    LocalDate startDate;
+                    LocalDate endDate;
+
+                    // 处理 yyyy-MM 格式(如2025-08)
+                    if (dateParam.matches("\\d{4}-\\d{2}")) {
+                        LocalDate monthDate = LocalDate.parse(dateParam + "-01", DATE_FORMATTER);
+                        startDate = monthDate.with(TemporalAdjusters.firstDayOfMonth());
+                        endDate = monthDate.with(TemporalAdjusters.firstDayOfNextMonth());
+                    }
+                    // 处理 yyyy-MM-dd 格式(如2025-08-15)
+                    else if (dateParam.matches("\\d{4}-\\d{2}-\\d{2}")) {
+                        LocalDate inputDate = LocalDate.parse(dateParam, DATE_FORMATTER);
+                        startDate = inputDate.with(TemporalAdjusters.firstDayOfMonth());
+                        endDate = inputDate.with(TemporalAdjusters.firstDayOfNextMonth());
+                    } else {
+                        logger.warn("日期参数格式不合法,值为:{},支持格式:yyyy-MM 或 yyyy-MM-dd", dateParam);
+                        return buildWaterPowerCollection(ctx, filterInfo);
+                    }
+
+                    // 添加日期过滤项(索引0:>=startTime,索引1:<endTime)
+                    String startTime = startDate.format(DATE_FORMATTER);
+                    String endTime = endDate.format(DATE_FORMATTER);
+                    filterInfo.getFilterItems().add(new FilterItemInfo("years", startTime, CompareType.GREATER_EQUALS));
+                    filterInfo.getFilterItems().add(new FilterItemInfo("years", endTime, CompareType.LESS));
+                    hasDateFilter = true;
+                    // 日期条件逻辑:#0 and #1
+                    filterLogicSegments.add("#0 and #1");
+                    logger.info("添加日期过滤条件:years >= {} 且 years < {}", startTime, endTime);
+
+                } catch (Exception e) {
+                    logger.error("处理日期参数时发生异常,参数值:{}", dateParam, e);
+                    // 直接抛出框架规范的EASBizException,避免嵌套异常和RuntimeException
+                    throw new EASBizException(new NumericExceptionSubItem("00001","日期参数解析失败:" + e.getMessage()));
+                }
+            }
+
+            // 3. 处理房间号参数(模糊查询number/name)
+            Object roomNumberObj = param.get("roomNumber");
+            if (roomNumberObj != null && !StringUtils.isEmpty(roomNumberObj.toString())) {
+                String roomNumber = roomNumberObj.toString().trim();
+                roomNumber = getString(roomNumber);
+                String likePattern = "%" + roomNumber + "%";
+                // 计算房间号过滤项的起始索引(根据前面的日期项数量)
+                int roomFilterStartIndex = hasDateFilter ? 2 : 0;
+                // 添加房间号过滤项
+                filterInfo.getFilterItems().add(new FilterItemInfo("dormitory.number", likePattern, CompareType.LIKE));
+                filterInfo.getFilterItems().add(new FilterItemInfo("dormitory.name", likePattern, CompareType.LIKE));
+                hasRoomFilter = true;
+                // 房间号条件逻辑:(#n or #n+1)
+                String roomLogic = String.format("(#%d or #%d)", roomFilterStartIndex, roomFilterStartIndex + 1);
+                filterLogicSegments.add(roomLogic);
+                logger.info("添加房间号模糊过滤条件:dormitory.number LIKE {} 或 dormitory.name LIKE {}", likePattern, likePattern);
+                logger.info("房间号过滤逻辑片段:{}", roomLogic);
+            }
+
+            // 4. 处理数据类型参数(筛选无水费/无电费记录)
+            Object dataTypeObj = param.get("dataType");
+            if (dataTypeObj != null && !StringUtils.isEmpty(dataTypeObj.toString())) {
+                String dataType = dataTypeObj.toString().trim();
+                // 计算数据类型过滤项的起始索引(日期2项 + 房间号2项 = 4;无前置则0/2)
+                int dataTypeIndex = filterInfo.getFilterItems().size();
+                String dataTypeLogic = "";
+                if(StringUtils.equals(dataType, ShowType.UNPAPER.getValue())){
+                    // 无水费:totalWaterTons为空
+                    filterInfo.getFilterItems().add(new FilterItemInfo("totalWaterTons", null, CompareType.EMPTY));
+                    dataTypeLogic = String.format("#%d", dataTypeIndex);
+                    logger.info("添加数据类型过滤条件:无水费记录(totalWaterTons 为空)");
+                }else if(StringUtils.equals(dataType, ShowType.UNELECTRICITY.getValue())){
+                    // 无电费:totalElecDegrees为空
+                    filterInfo.getFilterItems().add(new FilterItemInfo("totalElecDegrees", null, CompareType.EMPTY));
+                    dataTypeLogic = String.format("#%d", dataTypeIndex);
+                    logger.info("添加数据类型过滤条件:无电费记录(totalElecDegrees 为空)");
+                }
+                if (StringUtils.isNotBlank(dataTypeLogic)) {
+                    hasDataTypeFilter = true;
+                    filterLogicSegments.add(dataTypeLogic);
+                }
+            }
+
+            // 5. 动态构建最终的maskString(所有条件用AND连接)
+            if (!filterLogicSegments.isEmpty()) {
+                String finalMaskString = String.join(" and ", filterLogicSegments);
+                filterInfo.setMaskString(finalMaskString);
+                logger.info("最终过滤条件组合逻辑(maskString):{}", finalMaskString);
+            } else {
+                logger.info("无任何过滤条件,查询全部水电表读数记录");
+            }
+
+        }
+
+        // 6. 构建查询结果并返回
+        return buildWaterPowerCollection(ctx, filterInfo);
+    }
+
+    @NotNull
+    private static String getString(String fid) {
+        if(fid.startsWith("'") && fid.endsWith("'")){
+            fid = fid.substring(1, fid.length() - 1);
+        }else if(fid.startsWith("\"") && fid.endsWith("\"")){
+            fid = fid.substring(1, fid.length() - 1);
+        }
+        return fid;
+    }
+
+    /**
+     * 构建排序条件并查询水电表读数集合
+     * 抽离通用逻辑,提高代码复用性
+     */
+    private WaterPowerMeterReadingCollection buildWaterPowerCollection(Context ctx, FilterInfo filterInfo) throws BOSException {
+        // 构建排序条件
+        SorterItemCollection sorterItemCollection = new SorterItemCollection();
+        SorterItemInfo yearsSorter = new SorterItemInfo("years");
+        yearsSorter.setSortType(SortType.DESCEND);
+        sorterItemCollection.add(yearsSorter);
+        sorterItemCollection.add(new SorterItemInfo("dormitory.number")); // 按房间号升序
+        SelectorItemCollection selectCol = new SelectorItemCollection();
+        selectCol.add(new SelectorItemInfo("*"));
+        selectCol.add(new SelectorItemInfo("dormitory.displayName"));
+        selectCol.add(new SelectorItemInfo("dormitory.name"));
+        // 构建视图并查询
+        EntityViewInfo entityViewInfo = new EntityViewInfo();
+        entityViewInfo.setFilter(filterInfo);
+        entityViewInfo.setSorter(sorterItemCollection);
+        entityViewInfo.setSelector(selectCol);
+        IWaterPowerMeterReading wpIns = WaterPowerMeterReadingFactory.getLocalInstance(ctx);
+        WaterPowerMeterReadingCollection wpCol = wpIns.getWaterPowerMeterReadingCollection(entityViewInfo);
+        logger.info("水电表读数查询完成,共查询到 {} 条记录", wpCol.size());
+        return wpCol;
+    }
+
+
+    
+    /**
+     * 构建排序条件并查询水电表读数集合
+     * 抽离通用逻辑,提高代码复用性
+     */
+    private WaterPowerMeterReadingInfo buildWaterPowerInfo(Context ctx, String fid) throws BOSException, EASBizException {
+        IWaterPowerMeterReading wpIns = WaterPowerMeterReadingFactory.getLocalInstance(ctx);
+        WaterPowerMeterReadingInfo wpCol = wpIns.getWaterPowerMeterReadingInfo(new ObjectUuidPK(fid));
+        logger.info("水电表读数查询完成,共查询到 {} 条记录", wpCol.size());
+        return wpCol;
+    }
+}

+ 184 - 0
websrc/com/kingdee/eas/custom/dormitorysystem/service/SaveWaterPowerReadService.java

@@ -0,0 +1,184 @@
+package com.kingdee.eas.custom.dormitorysystem.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.bsf.service.app.IHRMsfService;
+import com.kingdee.bos.dao.IObjectPK;
+import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
+import com.kingdee.bos.metadata.MetaDataLoaderFactory;
+import com.kingdee.bos.metadata.data.ColumnInfo;
+import com.kingdee.bos.metadata.data.SQLType;
+import com.kingdee.bos.metadata.entity.*;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.DormitoryFactory;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.DormitoryInfo;
+import com.kingdee.eas.custom.dormitorysystem.dormitory.IDormitory;
+import com.kingdee.eas.custom.dormitorysystem.waterpower.IWaterPowerMeterReading;
+import com.kingdee.eas.custom.dormitorysystem.waterpower.WaterPowerMeterReadingFactory;
+import com.kingdee.eas.custom.dormitorysystem.waterpower.WaterPowerMeterReadingInfo;
+import com.kingdee.eas.framework.CoreBaseInfo;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.kingdee.eas.base.core.util.EmptyUtil;
+import com.kingdee.eas.base.permission.UserCollection;
+import com.kingdee.eas.base.permission.UserFactory;
+import com.kingdee.eas.base.permission.UserInfo;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+
+/**
+ * 保存水电读书
+ * coyle
+ * 2025/12/19 10:37
+ */
+public class SaveWaterPowerReadService  implements IHRMsfService {
+
+    private static final Logger logger = LoggerFactory.getLogger(SaveWaterPowerReadService.class);
+    // 定义日期格式化器,避免重复创建
+
+    @Override
+    public Object process(Context ctx, Map<String, Object> param) throws EASBizException, BOSException {
+
+        if (ctx == null) {
+            throw new BOSException("上下文Context不能为空");
+        }
+        IWaterPowerMeterReading localInstance = WaterPowerMeterReadingFactory.getLocalInstance(ctx);
+        WaterPowerMeterReadingInfo info = new WaterPowerMeterReadingInfo();
+        Object fidObj = param.get("fid");
+
+        if (fidObj != null && !StringUtils.isEmpty(fidObj.toString()) && (fidObj.toString()).length()> 5) {
+            String fid = fidObj.toString().trim();
+             info = localInstance.getWaterPowerMeterReadingInfo(new ObjectUuidPK(fid));
+        }
+        EntityObjectInfo enty = MetaDataLoaderFactory.getLocalMetaDataLoader(ctx).getEntity(info.getBOSType());
+        PropertyCollection ps = enty.getInheritedNoDuplicatedPropertiesRuntime();
+        List<String> ColumnNames = new ArrayList<>();
+        List<String> bigCol = new ArrayList<>();
+        for (int j = 0; j < ps.size(); ++j) {
+            PropertyInfo p = ps.get(j);
+            ColumnInfo mappingField = p.getMappingField();
+            SQLType typeName = mappingField.getTypeName();
+          
+            String fkey = p.getName();
+            if (EmptyUtil.isEmpty(fkey)) continue;
+            if(StringUtils.equals( typeName.toString() ,  "NUMERIC")) {
+            	bigCol.add(fkey);
+            }
+            ColumnNames.add(fkey);
+        }
+            // 4. 构建查询结果并返回
+        setObjectPropertyValue (info, param, ColumnNames, bigCol );
+        
+        if (fidObj != null && !StringUtils.isEmpty(fidObj.toString())  && (fidObj.toString()).length()> 5 )
+            localInstance.update(new ObjectUuidPK(fidObj.toString()), info);
+        else {
+        	//抄表人
+        	if(param.containsKey("creatorNum")) {
+        		String creatorNum = String.valueOf(param.get("creatorNum"));
+                UserCollection userCollection = UserFactory.getLocalInstance(ctx).getUserCollection(" where number = '" + creatorNum +"'");
+                if(null != userCollection && userCollection.size() > 0) {
+                	UserInfo userInfo = userCollection.get(0);
+                	info.setMeterReaPerson(userInfo.getPerson());
+                }
+        	}else {
+        		IObjectPK userId = ctx.getCaller();
+            	UserInfo user = UserFactory.getRemoteInstance().getUserByID(userId);
+            	String personId = user.getPerson().getId().toString();
+                info.put("meterReaPerson",personId);
+        	}
+        	
+            IObjectPK addnew = localInstance.addnew(info);
+        }
+        return "success";
+    }
+
+
+
+    protected void setObjectPropertyValue(CoreBaseInfo coreBaseInfo,Map<String, Object> param, List<String> ColumnNames ,List<String> bigCol) {
+        Object data = param.get("data");
+        if (data == null) {
+            return;
+        }
+        String dataStr = data.toString().trim();
+        if(dataStr.startsWith("'") && dataStr.endsWith("'")){
+            dataStr = dataStr.substring(1, dataStr.length() - 1);
+        }else if(dataStr.startsWith("\"") && dataStr.endsWith("\"")){
+            dataStr = dataStr.substring(1, dataStr.length() - 1);
+        }
+        dataStr = dataStr  .replace("\\", "");
+         
+        //转换为json后,再转换为map
+        Map<String, Object> dataMap = (Map<String, Object>) JSONObject.parse(dataStr.toString());
+        // 1. 预处理:生成 小写键 -> 原值 的映射(仅需执行一次)
+        Map<String, Object> lowerCaseDataMap = new HashMap<>();
+        for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
+            // 键转小写,值保留原值
+            String lowerKey = entry.getKey().toLowerCase();
+            lowerCaseDataMap.put(lowerKey, entry.getValue());
+        }
+
+        // 3. 遍历ColumnNames,不区分大小写匹配
+        for (String propName : ColumnNames) {
+            // propName也转小写,匹配预处理后的映射
+            String lowerPropName = propName.toLowerCase();
+            if (lowerCaseDataMap.containsKey(lowerPropName)) {
+                Object value = lowerCaseDataMap.get(lowerPropName);
+                if (value != null && !StringUtils.isAllEmpty(value.toString())) {
+                	if(  bigCol.contains(propName) ) {
+                		coreBaseInfo.put(propName, safeConvertToBigDecimal(value.toString())); // 最终存入的键还是原propName(保持原有命名)
+                	}else {
+                		coreBaseInfo.put(propName, value); // 最终存入的键还是原propName(保持原有命名)
+                	}
+                	 
+//                	if("dormitory".equals(lowerPropName)) {
+//                		 coreBaseInfo.put(propName, "gMIDv2SBRdqAf5nD2B1DzlUo6p0="); // 最终存入的键还是原propName(保持原有命名)
+//                	}
+                }
+            }
+        }
+
+
+
+
+    }
+
+
+    /**
+     * 安全将字符串转换为BigDecimal
+     * @param str 待转换的字符串(可能为空、非数字)
+     * @param defaultValue 转换失败时的默认值(如BigDecimal.ZERO)
+     * @return 合法的BigDecimal值
+     */
+    public static BigDecimal safeConvertToBigDecimal(String str, BigDecimal defaultValue) {
+        // 1. 处理空值(null/空字符串/全空格)
+        if (str == null || str.trim().isEmpty()) {
+            return defaultValue;
+        }
+        try {
+            // 2. 尝试转换为BigDecimal
+            return new BigDecimal(str.trim());
+        } catch (NumberFormatException e) {
+            // 3. 转换失败返回默认值(可记录日志便于排查)
+            System.err.println("字符串转换BigDecimal失败,值为:" + str + ",原因:" + e.getMessage());
+            return defaultValue;
+        }
+    }
+
+    // 重载方法:默认值为0
+    public static BigDecimal safeConvertToBigDecimal(String str) {
+        return safeConvertToBigDecimal(str, BigDecimal.ZERO);
+    }
+
+
+
+
+}

+ 23 - 0
websrc/com/kingdee/eas/custom/dormitorysystem/service/ShowType.java

@@ -0,0 +1,23 @@
+package com.kingdee.eas.custom.dormitorysystem.service;
+
+public enum ShowType {
+        ALL("all"),
+    //未抄水表
+        UNPAPER("unPaper"),
+    //未抄电表
+        UNELECTRICITY("unElectricity");
+	
+        private String value;
+        
+        
+        ShowType(String value) {
+            this.value = value;
+        }
+        
+        public String getValue() {
+            return value;
+        }
+
+
+
+}

+ 2 - 2
websrc/com/kingdee/eas/custom/dormitorysystem/waterelectricity/handler/WaterElectricityBatchListHandler.java

@@ -62,8 +62,8 @@ public abstract class WaterElectricityBatchListHandler extends CommonBatchListHa
      */
     protected CoreBillBaseInfo calculateWaterElectricity(CoreBillBaseInfo waterElectricityInfo, Map<String, Object> map,
                                                              Map<String, Object> occupants) {
-        BigDecimal waterprice = (BigDecimal) map.get("waterprice");//水费单价
-        BigDecimal electricityprice = (BigDecimal) map.get("electricityprice");//电费单价
+        BigDecimal waterprice = (BigDecimal) waterElectricityInfo.get("waterprice");//水费单价
+        BigDecimal electricityprice = (BigDecimal) waterElectricityInfo.get("electricityprice");//电费单价
         BigDecimal curMonthWater = (BigDecimal) map.get("curMonthWater");
         BigDecimal curMonthElecDegrees = (BigDecimal) map.get("curMonthElecDegrees");
 

+ 64 - 60
websrc/com/kingdee/eas/custom/dormitorysystem/waterelectricity/handler/WaterElectricityListHandler.java

@@ -46,7 +46,7 @@ import java.time.format.DateTimeFormatter;
 import java.util.*;
 
 /**
- * 水电费明细计算
+ * 姘寸數璐规槑缁嗚�绠�
  * description: WaterElectricityListHandler <br>
  * date: 2025/4/24 18:09 <br>
  * author: lhbj <br>
@@ -57,7 +57,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
     public static final String TABLENAME ="CT_WOE_WaterElectricity";
 
     /**
-     * 获取水电费详细Sql
+     * 鑾峰彇姘寸數璐硅�缁哠ql
      *
      * @param startPeriodDateStr
      * @param endPeriodDateStr
@@ -116,23 +116,23 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
     
     
 	/**
-	 * 获取水电费详细Sql(SQL Server专用,逻辑已确认:房间向上追溯上级节点单价,水/电独立追溯)
-	 * 核心逻辑:
-	 * 1. 递归CTE遍历房间及所有上级节点(楼栋、小区等),保留起点房间ID关联
-	 * 2. 独立筛选水/电单价:非null优先、层级越近优先
-	 * 3. 优先级:树形节点单价 → 定价表单价
-	 * @param startPeriodDateStr 开始日期(格式:yyyy-MM-dd)
-	 * @param endPeriodDateStr 结束日期(格式:yyyy-MM-dd)
-	 * @param billids 账单ID集合(可为null/空,非空时追加筛选条件)
-	 * @return 拼接后的SQL字符串
+	 * 鑾峰彇姘寸數璐硅�缁哠ql锛圫QL Server涓撶敤锛岄€昏緫宸茬‘璁わ細鎴块棿鍚戜笂杩芥函涓婄骇鑺傜偣鍗曚环锛屾按/鐢电嫭绔嬭拷婧�級
+	 * 鏍稿績閫昏緫锛�
+	 * 1. 閫掑綊CTE閬嶅巻鎴块棿鍙婃墍鏈変笂绾ц妭鐐癸紙妤兼爧銆佸皬鍖虹瓑锛夛紝淇濈暀璧风偣鎴块棿ID鍏宠仈
+	 * 2. 鐙�珛绛涢€夋按/鐢靛崟浠凤細闈瀗ull浼樺厛銆佸眰绾ц秺杩戜紭鍏�
+	 * 3. 浼樺厛绾э細鏍戝舰鑺傜偣鍗曚环 鈫� 瀹氫环琛ㄥ崟浠�
+	 * @param startPeriodDateStr 寮€濮嬫棩鏈燂紙鏍煎紡锛歽yyy-MM-dd锛�
+	 * @param endPeriodDateStr 缁撴潫鏃ユ湡锛堟牸寮忥細yyyy-MM-dd锛�
+	 * @param billids 璐﹀崟ID闆嗗悎锛堝彲涓簄ull/绌猴紝闈炵┖鏃惰拷鍔犵瓫閫夋潯浠讹級
+	 * @return 鎷兼帴鍚庣殑SQL瀛楃�涓�
 	 */
     protected StringBuilder getPersonWaterElectricitySql(String dbType, String startPeriodDateStr, String endPeriodDateStr, Collection<String> billids) {
     
     	    StringBuilder sel = new StringBuilder();
 
-    	    // 1. 递归CTE:追溯房间及所有上级节点(防自引用,避免死循环)
+    	    // 1. 閫掑綊CTE锛氳拷婧�埧闂村強鎵€鏈変笂绾ц妭鐐癸紙闃茶嚜寮曠敤锛岄伩鍏嶆�寰�幆锛�
     	    sel.append("/*dialect*/ WITH DormPriceCTE AS (");
-    	    // 锚点成员:所有节点作为起点(后续主查询关联房间,不影响逻辑)
+    	    // 閿氱偣鎴愬憳锛氭墍鏈夎妭鐐逛綔涓鸿捣鐐癸紙鍚庣画涓绘煡璇㈠叧鑱旀埧闂达紝涓嶅奖鍝嶉€昏緫锛�
     	    sel.append("    SELECT ");
     	    sel.append("        fid AS DormId,");
     	    sel.append("        fparentId,");
@@ -141,7 +141,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
     	    sel.append("        0 AS RecursionLevel");
     	    sel.append("    FROM CT_DOR_Dormitory");
     	    sel.append("    UNION ALL");
-    	    // 递归成员:向上遍历上级节点,保留起点房间ID(核心逻辑)
+    	    // 閫掑綊鎴愬憳锛氬悜涓婇亶鍘嗕笂绾ц妭鐐癸紝淇濈暀璧风偣鎴块棿ID锛堟牳蹇冮€昏緫锛�
     	    sel.append("    SELECT ");
     	    sel.append("        child.DormId AS DormId,");
     	    sel.append("        parent.fparentId,");
@@ -154,7 +154,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
     	    sel.append("        AND parent.fid != child.DormId  ");
     	    sel.append("),");
 
-    	    // 2. 独立筛选「水单价」:按起点房间ID分组,取最近有效水价(非null优先、层级近优先)
+    	    // 2. 鐙�珛绛涢€夈€屾按鍗曚环銆嶏細鎸夎捣鐐规埧闂碔D鍒嗙粍锛屽彇鏈€杩戞湁鏁堟按浠凤紙闈瀗ull浼樺厛銆佸眰绾ц繎浼樺厛锛�
     	    sel.append("WaterLatestPrice AS (");
     	    sel.append("    SELECT ");
     	    sel.append("        DormId,");
@@ -168,7 +168,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
     	    sel.append("    FROM DormPriceCTE");
     	    sel.append("),");
 
-    	    // 3. 独立筛选「电单价」:逻辑同水单价,独立判断电单价字段
+    	    // 3. 鐙�珛绛涢€夈€岀數鍗曚环銆嶏細閫昏緫鍚屾按鍗曚环锛岀嫭绔嬪垽鏂�數鍗曚环瀛楁�
     	    sel.append("ElecLatestPrice AS (");
     	    sel.append("    SELECT ");
     	    sel.append("        DormId,");
@@ -182,7 +182,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
     	    sel.append("    FROM DormPriceCTE");
     	    sel.append(")");
 
-    	    // 4. 主查询:关联各表,返回结果字段(优先级:树形单价 → 定价表单价)
+    	    // 4. 涓绘煡璇�細鍏宠仈鍚勮〃锛岃繑鍥炵粨鏋滃瓧娈碉紙浼樺厛绾э細鏍戝舰鍗曚环 鈫� 瀹氫环琛ㄥ崟浠凤級
     	    sel.append(" SELECT ");
     	    sel.append("    p.fid pid,");
     	    sel.append("    p.fname_l2 pName,");
@@ -218,27 +218,27 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
     	    sel.append(" LEFT JOIN CT_DOR_Dormitory dy ON ops.CFDormitoryID = dy.fid");
     	    sel.append(" LEFT JOIN WaterLatestPrice wlp ON dy.fid = wlp.DormId AND wlp.WaterRowNum = 1");
     	    sel.append(" LEFT JOIN ElecLatestPrice elp ON dy.fid = elp.DormId AND elp.ElecRowNum = 1");
-    	    // 定价表关联:日期参数用传入的start/endPeriodDateStr,显式转换为date类型
+    	    // 瀹氫环琛ㄥ叧鑱旓細鏃ユ湡鍙傛暟鐢ㄤ紶鍏ョ殑start/endPeriodDateStr锛屾樉寮忚浆鎹�负date绫诲瀷
     	    sel.append(" LEFT JOIN CT_WAT_WaterPowerPricing wpp ");
     	    sel.append("    ON wpp.CFStartDate <= CONVERT(date, '").append(startPeriodDateStr).append("')");
     	    sel.append("    AND wpp.CFEndDate >= CONVERT(date, '").append(endPeriodDateStr).append("')");
-    	    // 抄表记录关联:按房间ID+日期范围匹配
+    	    // 鎶勮〃璁板綍鍏宠仈锛氭寜鎴块棿ID+鏃ユ湡鑼冨洿鍖归厤
     	    sel.append(" LEFT JOIN CT_MAN_WaterPowerMeterReading wpmr ");
     	    sel.append("    ON wpmr.CFDormitoryID = ops.CFDormitoryID");
     	    sel.append("    AND wpmr.CFYears <= ops.CFCheckOutDate");
     	    sel.append("    AND DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, wpmr.CFYears) + 1, 0)) >= ops.CFCheckInDate");
-    	    // 水电账单关联:按占用ID+人员ID+日期范围匹配(日期参数用传入值)
+    	    // 姘寸數璐﹀崟鍏宠仈锛氭寜鍗犵敤ID+浜哄憳ID+鏃ユ湡鑼冨洿鍖归厤锛堟棩鏈熷弬鏁扮敤浼犲叆鍊硷級
     	    sel.append(" LEFT JOIN CT_WOE_WaterElectricity wey ");
     	    sel.append("    ON wey.FSourceFunction = ops.fid ");
     	    sel.append("    AND wey.CFPersonID = pp.FPERSONID");
     	    sel.append("    AND wey.CFStartDate = CONVERT(date, '").append(startPeriodDateStr).append("')");
     	    sel.append("    AND wey.CFEndDate = CONVERT(date, '").append(endPeriodDateStr).append("')");
-    	    // 筛选条件:占用周期与查询周期重叠(SQL Server用CONVERT替代to_char)
+    	    // 绛涢€夋潯浠讹細鍗犵敤鍛ㄦ湡涓庢煡璇㈠懆鏈熼噸鍙狅紙SQL Server鐢–ONVERT鏇夸唬to_char锛�
     	    sel.append(" WHERE ");
     	    sel.append("    CONVERT(varchar(10), ops.CFCheckOutDate, 23) >= '").append(startPeriodDateStr).append("'");
     	    sel.append("    AND CONVERT(varchar(10), ops.CFCheckInDate, 23) <= '").append(endPeriodDateStr).append("'");
 
-    	    // 账单ID筛选:若传入billids集合,追加IN条件(避免空集合报错)
+    	    // 璐﹀崟ID绛涢€夛細鑻ヤ紶鍏�illids闆嗗悎锛岃拷鍔營N鏉′欢锛堥伩鍏嶇┖闆嗗悎鎶ラ敊锛�
     	    if (null != billids && (!billids.isEmpty())) {
     	        sel.append("    AND wey.fid IN ('') ");
     	        for (String id : billids) {
@@ -247,7 +247,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
     	        sel.append(")");
     	    }
 
-    	    // 递归深度限制:10层足够覆盖日常树形(房间→楼栋→小区→...),避免异常
+    	    // 閫掑綊娣卞害闄愬埗锛�10灞傝冻澶熻�鐩栨棩甯告爲褰�紙鎴块棿鈫掓ゼ鏍嬧啋灏忓尯鈫�...锛夛紝閬垮厤寮傚父
     	    sel.append(" OPTION (MAXRECURSION 10)");
 
     	    System.out.println("getPersonWaterElectricitySql:" + sel);
@@ -267,7 +267,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
     
 
     /**
-     * 获取水电费详细集合
+     * 鑾峰彇姘寸數璐硅�缁嗛泦鍚�
      *
      * @param ctx
      * @param startPeriodDateStr
@@ -290,17 +290,17 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
             String pNumber = rs.getString("pNumber");
             String opsid = rs.getString("opsid");
             String InService = rs.getString("InService");
-            Date checkInDate = rs.getDate("CFCheckInDate");//入住日期
-            Date checkOutDate = rs.getDate("CFCheckOutDate");//离宿日期
-            String dormitoryID = rs.getString("dormitoryID");//宿舍
-            String wppid = rs.getString("wppid");//标准id
-            Date startDate = rs.getDate("CFStartDate");//标准开始日期
-            Date endDate = rs.getDate("CFEndDate");//标准结束日期
-            BigDecimal waterprice = rs.getBigDecimal("CFWaterprice");//水费单价
+            Date checkInDate = rs.getDate("CFCheckInDate");//鍏ヤ綇鏃ユ湡
+            Date checkOutDate = rs.getDate("CFCheckOutDate");//绂诲�鏃ユ湡
+            String dormitoryID = rs.getString("dormitoryID");//瀹胯垗
+            String wppid = rs.getString("wppid");//鏍囧噯id
+            Date startDate = rs.getDate("CFStartDate");//鏍囧噯寮€濮嬫棩鏈�
+            Date endDate = rs.getDate("CFEndDate");//鏍囧噯缁撴潫鏃ユ湡
+            BigDecimal waterprice = rs.getBigDecimal("CFWaterprice");//姘磋垂鍗曚环
             if (null==waterprice){
-                throw new ShrWebBizException("没有找到水费电费标准单据,请在水电定价标准中维护!");
+                throw new ShrWebBizException("娌℃湁鎵惧埌姘磋垂鐢佃垂鏍囧噯鍗曟嵁锛岃�鍦ㄦ按鐢靛畾浠锋爣鍑嗕腑缁存姢锛�");
             }
-            BigDecimal electricityprice = rs.getBigDecimal("CFElectricityprice");//电费单价
+            BigDecimal electricityprice = rs.getBigDecimal("CFElectricityprice");//鐢佃垂鍗曚环
             String wpmrid = rs.getString("wpmrid");
             Date wpmrStartDate = rs.getDate("wpmrStartDate");
             Date wpmrEndDate = rs.getDate("wpmrEndDate");
@@ -340,8 +340,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
 
 
     /**
-     * 获取人员入住详情
-     *
+     * 鑾峰彇浜哄憳鍏ヤ綇璇︽儏
      * @param we
      * @param periodDate
      * @param pid
@@ -394,14 +393,14 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
             String pNumber = (String) map.get("pNumber");
             String opsid = (String) map.get("opsid");
             String InService = (String) map.get("InService");
-            Date checkInDate = (Date) map.get("checkInDate");//入住日期
-            Date checkOutDate = (Date) map.get("checkOutDate");//离宿日期
-            String dormitoryID = (String) map.get("dormitoryID");//宿舍
-            String wppid = (String) map.get("wppid");//标准id
-            Date startDate = (Date) map.get("startDate");//标准开始日期
-            Date endDate = (Date) map.get("endDate");//标准结束日期
-            BigDecimal waterprice = (BigDecimal) map.get("waterprice");//水费单价
-            BigDecimal electricityprice = (BigDecimal) map.get("electricityprice");//电费单价
+            Date checkInDate = (Date) map.get("checkInDate");//鍏ヤ綇鏃ユ湡
+            Date checkOutDate = (Date) map.get("checkOutDate");//绂诲�鏃ユ湡
+            String dormitoryID = (String) map.get("dormitoryID");//瀹胯垗
+            String wppid = (String) map.get("wppid");//鏍囧噯id
+            Date startDate = (Date) map.get("startDate");//鏍囧噯寮€濮嬫棩鏈�
+            Date endDate = (Date) map.get("endDate");//鏍囧噯缁撴潫鏃ユ湡
+            BigDecimal waterprice = (BigDecimal) map.get("waterprice");//姘磋垂鍗曚环
+            BigDecimal electricityprice = (BigDecimal) map.get("electricityprice");//鐢佃垂鍗曚环
             String wpmrid = (String) map.get("wpmrid");
             Date wpmrStartDate = (Date) map.get("wpmrStartDate");
             Date wpmrEndDate = (Date) map.get("wpmrEndDate");
@@ -416,7 +415,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
                 waterElectricityInfo = new WaterElectricityInfo();
             }
             waterElectricityInfo.setSourceFunction(opsid);
-            //处理当月入住天数
+            //澶勭悊褰撴湀鍏ヤ綇澶╂暟
             Map<String, Object> occupants = occupantsMap.get(dormitoryID);
             HROrgUnitInfo hrOrgUnitInfo = new HROrgUnitInfo();
             hrOrgUnitInfo.setId(BOSUuid.read("00000000-0000-0000-0000-000000000000CCE7AED4"));
@@ -445,16 +444,19 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
             positionInfo.setId(BOSUuid.read(primaryPositionID));
             waterElectricityInfo.setPosition(positionInfo);
             Instant instant1 = startPeriodDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
-            // 获取时间戳(毫秒)
+            // 鑾峰彇鏃堕棿鎴筹紙姣��锛�
             long timestamp1 = instant1.toEpochMilli();
             waterElectricityInfo.setStartDate(new Date(timestamp1));
             Instant instant2 = endPeriodDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
-            // 获取时间戳(毫秒)
+            // 鑾峰彇鏃堕棿鎴筹紙姣��锛�
             long timestamp2 = instant2.toEpochMilli();
             waterElectricityInfo.setEndDate(new Date(timestamp2));
             waterElectricityInfo.setApplyDate(checkInDate);
             PersonInfo applier = SHRBillUtil.getCurrPersonInfo();
             waterElectricityInfo.setApplier(applier);
+            //姘寸數鍗曚环
+            waterElectricityInfo.setWaterprice(waterprice);
+            waterElectricityInfo.setElectricityprice(electricityprice); 
 
             BOSUuid id = waterElectricityInfo.getId();
             if (null == id) {
@@ -475,6 +477,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
                 }
             }
         }
+        
         resutMap.put("alls", alls);
         resutMap.put("errs", errs);
         resutMap.put("sess", sess);
@@ -482,7 +485,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
     }
 
     /**
-     * 生成水电费明细
+     * 鐢熸垚姘寸數璐规槑缁�
      *
      * @param request
      * @param response
@@ -501,7 +504,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
             LocalDate startPeriodDate = LocalDate.parse(periodDate + "-01", DateTimeFormatter.ISO_LOCAL_DATE);
             Month month = startPeriodDate.getMonth();
             LocalDate endPeriodDate = LocalDate.of(startPeriodDate.getYear(), month, month.length(startPeriodDate.isLeapYear()));
-            //获取开始时间,结束时间
+            //鑾峰彇寮€濮嬫椂闂达紝缁撴潫鏃堕棿
             String startPeriodDateStr = startPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
             String endPeriodDateStr = endPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
             Map<String, Object> param = Maps.newHashMap();
@@ -511,14 +514,14 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
             param.put("startPeriodDateStr", startPeriodDateStr);
             param.put("endPeriodDateStr", endPeriodDateStr);
 
-            //获取水电费详细集合
+            //鑾峰彇姘寸數璐硅�缁嗛泦鍚�
             List<Map<String, Object>> mapList = this.getPersonWaterElectricityList(ctx, startPeriodDateStr, endPeriodDateStr, billids);
             Set<String> dormitorySet = Sets.newHashSet();
             for (Map<String, Object> map : mapList) {
-                String dormitoryID = (String) map.get("dormitoryID");//宿舍
+                String dormitoryID = (String) map.get("dormitoryID");//瀹胯垗
                 dormitorySet.add(dormitoryID);
             }
-            //获取当前宿舍的总入住天数
+            //鑾峰彇褰撳墠瀹胯垗鐨勬€诲叆浣忓ぉ鏁�
             Map<String, Map<String, Object>> occupantsMap = this.getPersonOccupantsList(ctx, dormitorySet, startPeriodDate, endPeriodDate);
             Map<String, Set<String>> result = this.createUpdateWE(ctx, mapList, param, occupantsMap, "create");
             this.returnMessage(request, batchMessageTipsHeader, result,billids);
@@ -527,9 +530,10 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
         } catch (BOSException | EASBizException | SQLException e) {
             e.printStackTrace();
         }
+        
     }
     /**
-     * 计算
+     * 璁$畻
      {"startDate":
      {"values":{"date":"2025-04-01"},"isSaveToScheme":true,"dataType":"Date","queryDateType":""},
      "applyDate":
@@ -563,7 +567,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
                 periodDate = periodDate.substring(0, 7);
                 Month month = startPeriodDate.getMonth();
                 LocalDate endPeriodDate = LocalDate.of(startPeriodDate.getYear(), month, month.length(startPeriodDate.isLeapYear()));
-                //获取开始时间,结束时间
+                //鑾峰彇寮€濮嬫椂闂达紝缁撴潫鏃堕棿
                 String startPeriodDateStr = startPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
                 String endPeriodDateStr = endPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
                 Map<String, Object> param = Maps.newHashMap();
@@ -573,14 +577,14 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
                 param.put("startPeriodDateStr", startPeriodDateStr);
                 param.put("endPeriodDateStr", endPeriodDateStr);
 
-                //获取水电费详细集合
+                //鑾峰彇姘寸數璐硅�缁嗛泦鍚�
                 List<Map<String, Object>> mapList = this.getPersonWaterElectricityList(ctx, startPeriodDateStr, endPeriodDateStr, billids);
                 Set<String> dormitorySet = Sets.newHashSet();
                 for (Map<String, Object> map : mapList) {
-                    String dormitoryID = (String) map.get("dormitoryID");//宿舍
+                    String dormitoryID = (String) map.get("dormitoryID");//瀹胯垗
                     dormitorySet.add(dormitoryID);
                 }
-                //获取当前宿舍的总入住天数
+                //鑾峰彇褰撳墠瀹胯垗鐨勬€诲叆浣忓ぉ鏁�
                 Map<String, Map<String, Object>> occupantsMap = this.getPersonOccupantsList(ctx, dormitorySet, startPeriodDate, endPeriodDate);
                 Map<String, Set<String>> result = this.createUpdateWE(ctx, mapList, param, occupantsMap, "update");
                 this.returnMessage(request, batchMessageTipsHeader, result, billids);
@@ -602,7 +606,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
         return TABLENAME;
     }
     /**
-     * 锁定
+     * 閿佸畾
      *
      * @param request
      * @param response
@@ -630,7 +634,7 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
         return billId;
     }
     /**
-     * 解锁
+     * 瑙i攣
      *
      * @param request
      * @param response
@@ -667,11 +671,11 @@ public class WaterElectricityListHandler extends WaterElectricityBatchListHandle
             state = conn.createStatement();
             if ("enable".equals(math)) {
 
-                //薪酬锁定
+                //钖�叕閿佸畾
                 state.execute("update "+TABLENAME+" set FBillState='2' where fid='" + uuid + "' and FBillState < 2 ");
 
             } else if ("disable".equals(math)) {
-                //薪酬解锁
+                //钖�叕瑙i攣
                 state.execute("update "+TABLENAME+" set FBillState='0' where fid='" + uuid + "' and FBillState < 3 ");
             }
         } catch (SQLException var32) {

+ 165 - 3
websrc/com/kingdee/eas/custom/dormitorysystem/waterelectricity/handler/WaterElectricitySpecialEditHandler.java

@@ -1,17 +1,179 @@
 package com.kingdee.eas.custom.dormitorysystem.waterelectricity.handler;
 
+import java.sql.SQLException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.kingdee.eas.base.codingrule.CodingRuleManagerFactory;
+import com.kingdee.eas.base.codingrule.ICodingRuleManager;
+import com.kingdee.eas.basedata.org.HROrgUnitInfo;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.ui.ModelMap;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
+import com.kingdee.bos.metadata.entity.SelectorItemCollection;
+import com.kingdee.bos.metadata.entity.SelectorItemInfo;
+import com.kingdee.bos.util.BOSUuid;
+import com.kingdee.eas.basedata.person.IPerson;
+import com.kingdee.eas.basedata.person.PersonFactory;
+import com.kingdee.eas.basedata.person.PersonInfo;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.custom.dormitorysystem.waterelectricity.WaterElectricitySpecialInfo;
+import com.kingdee.eas.custom.dormitorysystem.waterelectricity.WaterElectricityStutas;
+import com.kingdee.eas.framework.CoreBaseInfo;
+import com.kingdee.eas.util.app.DbUtil;
+import com.kingdee.jdbc.rowset.IRowSet;
+import com.kingdee.shr.base.syssetting.context.SHRContext;
+import com.kingdee.shr.base.syssetting.exception.SHRWebException;
 import com.kingdee.shr.base.syssetting.web.handler.EditHandler;
+import com.kingdee.shr.base.syssetting.web.json.JSONUtils;
+
 
 /**
  * description: WaterElectricitySpecialEditHandler <br>
- * date: 2025/5/6 10:38 <br>
+ * date: 20251227
  * author: lhbj <br>
  * version: 1.0 <br>
  */
 public class WaterElectricitySpecialEditHandler extends EditHandler {
-    public WaterElectricitySpecialEditHandler() {
+   
+	private static Logger logger = LoggerFactory.getLogger(WaterElectricitySpecialEditHandler.class);
+ 
+	
+	@Override
+	protected void beforeSave(HttpServletRequest request, HttpServletResponse response, CoreBaseInfo model)
+			throws SHRWebException {
+		super.beforeSave(request, response, model);
+		Context ctx = SHRContext.getInstance().getContext();
+		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM");
+		WaterElectricitySpecialInfo  info = (WaterElectricitySpecialInfo)model ;
+		
+		try {
+			Date startDate = info.getStartDate();
+			String format = dateFormat.format(startDate);
+			info.setYearMonth(format);
+			//根据startdate获取这个月的最后一天
+			String endDate = dateFormat.format(startDate);
+			endDate = endDate + "-31";
+			dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+			info.setEndDate(dateFormat.parse(endDate));
+			//
+			info.setStutas(WaterElectricityStutas.UnLock);
+			SelectorItemCollection selectCol = new SelectorItemCollection(); 
+			selectCol.add(new SelectorItemInfo("number"));
+			selectCol.add(new SelectorItemInfo("name"));
+			selectCol.add(new SelectorItemInfo("employeeType.name"));
+			IPerson personIns  = PersonFactory.getLocalInstance(ctx);
+			PersonInfo  personInfo = personIns.getPersonInfo(new ObjectUuidPK(info.getPerson().getId()), selectCol);
+			info.setEmpNumber(personInfo.getNumber());
+			info.setEmpName (personInfo.getName());
+			info.setPositionStatus(personInfo.getString("employeeType"));
+			//编码规则
+			if(StringUtils.isEmpty(info.getNumber())){
+				HROrgUnitInfo hrOrgUnit = info.getHrOrgUnit();
+				ICodingRuleManager iCodingRuleManager = CodingRuleManagerFactory.getLocalInstance(ctx);
+				if (iCodingRuleManager.isExist(info, hrOrgUnit.getId().toString())) {
+					String  number = iCodingRuleManager.getNumber(info, hrOrgUnit.getId().toString());
+					info.setNumber(number);
+				}
+			}
+		} catch (EASBizException e) {
+			e.printStackTrace();
+		} catch (BOSException e) {
+			e.printStackTrace();
+		} catch (ParseException e) {
+			throw new RuntimeException(e);
+		}
 
-    }
 
+	}
+	
+	
+        /**
+         * 根据房间ID获取水电单价
+         * @return Map<String, Double>  key:CFWaterprice(水单价)、CFElectricityprice(电单价);value:对应单价(无数据返回0.0D)
+         * @throws BOSException 金蝶BOS异常
+         * @throws SQLException 数据库异常
+         */
+    public void getWaterElecPriceAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap ) throws SHRWebException, BOSException, SQLException {
+        Context ctx = SHRContext.getInstance().getContext();
+        String dormFid = request.getParameter("dormFid");
+        String startDate = request.getParameter("startDate");
+        try {
+        	Map<String, Double> priceMap  = getDormWaterElectricityPrice(ctx, dormFid, startDate);
+        	JSONUtils.writeJson(response, priceMap);
+        } catch (ParseException e) {
+        	e.printStackTrace();
+        }
+     }
+    
+    
+    
+    
+    
+    public Map<String, Double> getDormWaterElectricityPrice (Context ctx, String dormFid, String dateStr)
+            throws BOSException, SQLException, ParseException   {
+        Map<String, Double> priceMap = new HashMap<>(2);
+        priceMap.put("CFWaterprice", 0.0D);
+        priceMap.put("CFElectricityprice", 0.0D);
 
+        if (dormFid == null || dormFid.trim().isEmpty() || dateStr == null || dateStr.trim().isEmpty()) {
+            return priceMap;
+        }
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        dateFormat.parse(dateStr);
+
+        // 参数化SQL模板(用?占位符,避免拼接)
+        String sqlTemplate = "/*dialect*/ WITH DormPriceCTE AS (" +
+                "    SELECT fid AS DormId, fparentId, CFWaterprice, CFElectricityprice, 0 AS RecursionLevel " +
+                "    FROM CT_DOR_Dormitory WHERE fid = ? " +
+                "    UNION ALL " +
+                "    SELECT child.DormId, parent.fparentId, parent.CFWaterprice, parent.CFElectricityprice, child.RecursionLevel + 1 " +
+                "    FROM DormPriceCTE child INNER JOIN CT_DOR_Dormitory parent ON child.fparentId = parent.fid AND parent.fid != child.DormId " +
+                "), WaterLatestPrice AS (" +
+                "    SELECT DormId, CFWaterprice AS LatestWaterPrice, " +
+                "           ROW_NUMBER() OVER (PARTITION BY DormId ORDER BY CASE WHEN CFWaterprice IS NOT NULL THEN 0 ELSE 1 END, RecursionLevel ASC) AS WaterRowNum " +
+                "    FROM DormPriceCTE " +
+                "), ElecLatestPrice AS (" +
+                "    SELECT DormId, CFElectricityprice AS LatestElecPrice, " +
+                "           ROW_NUMBER() OVER (PARTITION BY DormId ORDER BY CASE WHEN CFElectricityprice IS NOT NULL THEN 0 ELSE 1 END, RecursionLevel ASC) AS ElecRowNum " +
+                "    FROM DormPriceCTE " +
+                ") " +
+                "SELECT COALESCE(wlp.LatestWaterPrice, wpp.CFWaterprice, 0.0) AS CFWaterprice, " +
+                "       COALESCE(elp.LatestElecPrice, wpp.CFElectricityprice, 0.0) AS CFElectricityprice " +
+                "FROM WaterLatestPrice wlp " +
+                "INNER JOIN ElecLatestPrice elp ON wlp.DormId = elp.DormId " +
+                "LEFT JOIN CT_WAT_WaterPowerPricing wpp ON wpp.CFStartDate <= CONVERT(date, ?) AND wpp.CFEndDate >= CONVERT(date, ?) " +
+                "WHERE wlp.WaterRowNum = 1 AND elp.ElecRowNum = 1 AND wlp.DormId = ? " +
+                "OPTION (MAXRECURSION 10)";
+
+        // 执行参数化查询
+        
+        IRowSet rowSet = DbUtil.executeQuery(ctx, sqlTemplate, new Object[]{dormFid, dateStr, dateStr, dormFid});
+
+        if (rowSet.next()) {
+            priceMap.put("CFWaterprice", rowSet.getDouble("CFWaterprice"));
+            priceMap.put("CFElectricityprice", rowSet.getDouble("CFElectricityprice"));
+        }
+        return priceMap;
+    }
 }
+    
+    
+    
+    
+    
+    
+ 
+    
+    

+ 45 - 45
websrc/com/kingdee/eas/custom/dormitorysystem/waterelectricity/handler/WaterElectricitySpecialListHandler.java

@@ -46,7 +46,7 @@ import java.time.format.DateTimeFormatter;
 import java.util.*;
 
 /**
- * 特殊水电费明细计算
+ * 鐗规畩姘寸數璐规槑缁嗚�绠�
  * description: WaterElectricityListHandler <br>
  * date: 2025/4/24 18:09 <br>
  * author: lhbj <br>
@@ -57,7 +57,7 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
     public static final String TABLENAME = "CT_WOE_WaterElectricitySpecial";
 
     /**
-     * 获取水电费详细Sql
+     * 鑾峰彇姘寸數璐硅�缁哠ql
      * wey.FBizDate CFCheckInDate,wey.CFLeaveDate CFCheckOutDate,wey.CFDormitoryID dormitoryID
      * @param startPeriodDateStr
      * @param endPeriodDateStr
@@ -74,12 +74,12 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
 //        sel.append(" isnull(wpmr.CFTotalWaterTons,0) CFTotalWaterTons,isnull(wpmr.CFTotalElecDegrees,0) CFTotalElecDegrees, ");
 //        sel.append(" isnull(wpmr.CFCurMonthWater,0) CFCurMonthWater,isnull(wpmr.CFCurMonthElecDegrees,0) CFCurMonthElecDegrees, ");
         sel.append(" pp.FPrimaryPositionID,pp.FPersonDep, ");
-        sel.append(" case ");
-        sel.append(" bt.finservice ");
-        sel.append(" when 1 then 'active' ");
-        sel.append(" when 4 then 'active' ");
-        sel.append(" else 'inactive' ");
-        sel.append(" end as InService ");
+//        sel.append(" case ");
+        sel.append(" bt.fname_l2  InService  ");
+//        sel.append(" when 1 then 'active' ");
+//        sel.append(" when 4 then 'active' ");
+//        sel.append(" else 'inactive' ");
+//        sel.append(" end as InService ");
         sel.append(" from CT_WOE_WaterElectricitySpecial wey ");
         sel.append(" left join t_bd_person p on wey.CFPERSONID = p.fid ");
         sel.append(" left join T_HR_PersonPosition pp on pp.FPERSONID = p.fid ");
@@ -111,7 +111,7 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
     }
 
     /**
-     * 获取水电费详细集合
+     * 鑾峰彇姘寸數璐硅�缁嗛泦鍚�
      *
      * @param ctx
      * @param startPeriodDateStr
@@ -134,17 +134,17 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
             String pNumber = rs.getString("pNumber");
             String opsid = rs.getString("opsid");
             String InService = rs.getString("InService");
-            Date checkInDate = rs.getDate("CFCheckInDate");//入住日期
-            Date checkOutDate = rs.getDate("CFCheckOutDate");//离宿日期
-            String dormitoryID = rs.getString("dormitoryID");//宿舍
-            String wppid = rs.getString("wppid");//标准id
-            Date startDate = rs.getDate("CFStartDate");//标准开始日期
-            Date endDate = rs.getDate("CFEndDate");//标准结束日期
-            BigDecimal waterprice = rs.getBigDecimal("CFWaterprice");//水费单价
+            Date checkInDate = rs.getDate("CFCheckInDate");//鍏ヤ綇鏃ユ湡
+            Date checkOutDate = rs.getDate("CFCheckOutDate");//绂诲�鏃ユ湡
+            String dormitoryID = rs.getString("dormitoryID");//瀹胯垗
+            String wppid = rs.getString("wppid");//鏍囧噯id
+            Date startDate = rs.getDate("CFStartDate");//鏍囧噯寮€濮嬫棩鏈�
+            Date endDate = rs.getDate("CFEndDate");//鏍囧噯缁撴潫鏃ユ湡
+            BigDecimal waterprice = rs.getBigDecimal("CFWaterprice");//姘磋垂鍗曚环
             if (null==waterprice){
-                throw new ShrWebBizException("没有找到水费电费标准单据,请在水电定价标准中维护!");
+                throw new ShrWebBizException("娌℃湁鎵惧埌姘磋垂鐢佃垂鏍囧噯鍗曟嵁锛岃�鍦ㄦ按鐢靛畾浠锋爣鍑嗕腑缁存姢锛�");
             }
-            BigDecimal electricityprice = rs.getBigDecimal("CFElectricityprice");//电费单价
+            BigDecimal electricityprice = rs.getBigDecimal("CFElectricityprice");//鐢佃垂鍗曚环
             String wpmrid = rs.getString("wpmrid");
             Date wpmrStartDate = rs.getDate("wpmrStartDate");
             Date wpmrEndDate = rs.getDate("wpmrEndDate");
@@ -182,7 +182,7 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
     }
 
     /**
-     * 生成水电费明细
+     * 鐢熸垚姘寸數璐规槑缁�
      *
      * @param request
      * @param response
@@ -194,7 +194,7 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
     }
 
     /**
-     * 计算
+     * 璁$畻
      * {"startDate":
      * {"values":{"date":"2025-04-01"},"isSaveToScheme":true,"dataType":"Date","queryDateType":""},
      * "applyDate":
@@ -218,7 +218,7 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
             LocalDate startPeriodDate = LocalDate.parse(periodDate + "-01", DateTimeFormatter.ISO_LOCAL_DATE);
             Month month = startPeriodDate.getMonth();
             LocalDate endPeriodDate = LocalDate.of(startPeriodDate.getYear(), month, month.length(startPeriodDate.isLeapYear()));
-            //获取开始时间,结束时间
+            //鑾峰彇寮€濮嬫椂闂达紝缁撴潫鏃堕棿
             String startPeriodDateStr = startPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
             String endPeriodDateStr = endPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
             Map<String, Object> param = Maps.newHashMap();
@@ -228,19 +228,19 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
             param.put("startPeriodDateStr", startPeriodDateStr);
             param.put("endPeriodDateStr", endPeriodDateStr);
 
-            //获取水电费详细集合
+            //鑾峰彇姘寸數璐硅�缁嗛泦鍚�
             List<Map<String, Object>> mapList = this.getPersonWaterElectricityList(ctx, startPeriodDateStr, endPeriodDateStr, billids);
             Set<String> dormitorySet = Sets.newHashSet();
             for (Map<String, Object> map : mapList) {
-                String dormitoryID = (String) map.get("dormitoryID");//宿舍
+                String dormitoryID = (String) map.get("dormitoryID");//瀹胯垗
                 dormitorySet.add(dormitoryID);
             }
-            logger.error("获取水电费详细集合:" + JSONUtils.convertObjectToJson(ctx, mapList));
-            //获取当前宿舍的总入住天数
+            logger.error("鑾峰彇姘寸數璐硅�缁嗛泦鍚�:" + JSONUtils.convertObjectToJson(ctx, mapList));
+            //鑾峰彇褰撳墠瀹胯垗鐨勬€诲叆浣忓ぉ鏁�
             Map<String, Map<String, Object>> occupantsMap = this.getPersonOccupantsList(ctx, dormitorySet, startPeriodDate, endPeriodDate);
-            logger.error("获取当前宿舍的总入住天数:" + JSONUtils.convertObjectToJson(ctx, occupantsMap));
+            logger.error("鑾峰彇褰撳墠瀹胯垗鐨勬€诲叆浣忓ぉ鏁�:" + JSONUtils.convertObjectToJson(ctx, occupantsMap));
             Map<String, Set<String>> result = this.createUpdateWE(ctx, mapList, param, occupantsMap, "update");
-            logger.error("结果:" + JSONUtils.convertObjectToJson(ctx, result));
+            logger.error("缁撴灉:" + JSONUtils.convertObjectToJson(ctx, result));
             this.returnMessage(request, batchMessageTipsHeader, result, billids);
 
         } catch (BOSException e) {
@@ -276,14 +276,14 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
             String pNumber = (String) map.get("pNumber");
             String opsid = (String) map.get("opsid");
             String InService = (String) map.get("InService");
-            Date checkInDate = (Date) map.get("checkInDate");//入住日期
-            Date checkOutDate = (Date) map.get("checkOutDate");//离宿日期
-            String dormitoryID = (String) map.get("dormitoryID");//宿舍
-            String wppid = (String) map.get("wppid");//标准id
-            Date startDate = (Date) map.get("startDate");//标准开始日期
-            Date endDate = (Date) map.get("endDate");//标准结束日期
-            BigDecimal waterprice = (BigDecimal) map.get("waterprice");//水费单价
-            BigDecimal electricityprice = (BigDecimal) map.get("electricityprice");//电费单价
+            Date checkInDate = (Date) map.get("checkInDate");//鍏ヤ綇鏃ユ湡
+            Date checkOutDate = (Date) map.get("checkOutDate");//绂诲�鏃ユ湡
+            String dormitoryID = (String) map.get("dormitoryID");//瀹胯垗
+            String wppid = (String) map.get("wppid");//鏍囧噯id
+            Date startDate = (Date) map.get("startDate");//鏍囧噯寮€濮嬫棩鏈�
+            Date endDate = (Date) map.get("endDate");//鏍囧噯缁撴潫鏃ユ湡
+            BigDecimal waterprice = (BigDecimal) map.get("waterprice");//姘磋垂鍗曚环
+            BigDecimal electricityprice = (BigDecimal) map.get("electricityprice");//鐢佃垂鍗曚环
             String wpmrid = (String) map.get("wpmrid");
             Date wpmrStartDate = (Date) map.get("wpmrStartDate");
             Date wpmrEndDate = (Date) map.get("wpmrEndDate");
@@ -300,9 +300,9 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
             if (StringUtils.isEmpty(waterElectricityInfo.getNumber())) {
                 waterElectricityInfo.setNumber("TWE" + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE) + index);
             }
-            logger.error("获取waterElectricityInfo:" + JSONUtils.convertObjectToJson(ctx, waterElectricityInfo));
+            logger.error("鑾峰彇waterElectricityInfo:" + JSONUtils.convertObjectToJson(ctx, waterElectricityInfo));
             waterElectricityInfo.setSourceFunction(opsid);
-            //处理当月入住天数
+            //澶勭悊褰撴湀鍏ヤ綇澶╂暟
             Map<String, Object> occupants = occupantsMap.get(dormitoryID);
             HROrgUnitInfo hrOrgUnitInfo = new HROrgUnitInfo();
             hrOrgUnitInfo.setId(BOSUuid.read("00000000-0000-0000-0000-000000000000CCE7AED4"));
@@ -333,11 +333,11 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
             positionInfo.setId(BOSUuid.read(primaryPositionID));
             waterElectricityInfo.setPosition(positionInfo);
             Instant instant1 = startPeriodDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
-            // 获取时间戳(毫秒)
+            // 鑾峰彇鏃堕棿鎴筹紙姣��锛�
             long timestamp1 = instant1.toEpochMilli();
             waterElectricityInfo.setStartDate(new Date(timestamp1));
             Instant instant2 = endPeriodDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
-            // 获取时间戳(毫秒)
+            // 鑾峰彇鏃堕棿鎴筹紙姣��锛�
             long timestamp2 = instant2.toEpochMilli();
             waterElectricityInfo.setEndDate(new Date(timestamp2));
             waterElectricityInfo.setApplyDate(checkInDate);
@@ -349,7 +349,7 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
                 waterElectricityInfo.setStutas(WaterElectricityStutas.UnLock);
                 waterElectricityInfo.setBillState(HRBillStateEnum.SAVED);
             }
-            logger.error("保存前waterElectricityInfo:" + JSONUtils.convertObjectToJson(ctx, waterElectricityInfo));
+            logger.error("淇濆瓨鍓峸aterElectricityInfo:" + JSONUtils.convertObjectToJson(ctx, waterElectricityInfo));
             if ("update".equals(createUpdate)) {
                 if (null != id && WaterElectricityStutas.UnLock.equals(waterElectricityInfo.getStutas())) {
                     IObjectPK pk = we.save(waterElectricityInfo);
@@ -372,7 +372,7 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
     }
 
     /**
-     * 获取人员入住详情
+     * 鑾峰彇浜哄憳鍏ヤ綇璇︽儏
      *
      * @param we
      * @param periodDate
@@ -412,7 +412,7 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
     }
 
     /**
-     * 锁定
+     * 閿佸畾
      *
      * @param request
      * @param response
@@ -442,7 +442,7 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
     }
 
     /**
-     * 解锁
+     * 瑙i攣
      *
      * @param request
      * @param response
@@ -481,11 +481,11 @@ public class WaterElectricitySpecialListHandler extends WaterElectricityBatchLis
             state = conn.createStatement();
             if ("enable".equals(math)) {
 
-                //薪酬锁定
+                //钖�叕閿佸畾
                 state.execute("update " + TABLENAME + " set FBillState='2' where fid='" + uuid + "' and FBillState < 2 ");
 
             } else if ("disable".equals(math)) {
-                //薪酬解锁
+                //钖�叕瑙i攣
                 state.execute("update " + TABLENAME + " set FBillState='0' where fid='" + uuid + "' and FBillState < 3 ");
             }
         } catch (SQLException var32) {

+ 21 - 24
websrc/com/kingdee/eas/custom/dormitorysystem/waterpower/handler/WaterPowerMeterReadingEditHandler.java

@@ -24,7 +24,7 @@ import java.util.Map;
 /**
  * @author qingwu
  * @date 2025/4/21
- * @apiNote 水电每月抄表信息  com.kingdee.eas.custom.dormitorysystem.waterpower.app.WaterPowerMeterReading89.form
+ * @apiNote 姘寸數姣忔湀鎶勮〃淇℃伅  com.kingdee.eas.custom.dormitorysystem.waterpower.app.WaterPowerMeterReading89.form
  */
 public class WaterPowerMeterReadingEditHandler extends EditHandler {
     Context ctx = SHRContext.getInstance().getContext();
@@ -65,19 +65,19 @@ public class WaterPowerMeterReadingEditHandler extends EditHandler {
     
 
     /**
-     * 获取当月用水电吨数
+     * 鑾峰彇褰撴湀鐢ㄦ按鐢靛惃鏁�
      * @param request
      * @param response
      * @param modelMap
      */
     public void getThisMonthWaterPowerTonsAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws BOSException, SHRWebException {
-        String years = request.getParameter("years");//年月
+        String years = request.getParameter("years");//骞存湀
         String totalWaterTonsStr = request.getParameter("totalWaterTons") == "" ? "0" : request.getParameter("totalWaterTons");
-        BigDecimal totalWaterTons = new BigDecimal(totalWaterTonsStr);//用水总吨数
+        BigDecimal totalWaterTons = new BigDecimal(totalWaterTonsStr);//鐢ㄦ按鎬诲惃鏁�
         String totalElecDegreesStr = request.getParameter("totalElecDegrees") == "" ? "0" : request.getParameter("totalElecDegrees");
-        BigDecimal totalElecDegrees = new BigDecimal(totalElecDegreesStr);//用电总吨数
-        String dormNumber = request.getParameter("dormNumber");//宿舍编码
-        boolean calcInterval = request.getParameter("calcInterval").isEmpty();//是否取消自动计算当月水电
+        BigDecimal totalElecDegrees = new BigDecimal(totalElecDegreesStr);//鐢ㄧ數鎬诲惃鏁�
+        String dormNumber = request.getParameter("dormNumber");//瀹胯垗缂栫爜
+        boolean calcInterval = request.getParameter("calcInterval").isEmpty();//鏄�惁鍙栨秷鑷�姩璁$畻褰撴湀姘寸數
         Map result = WaterPowerUtil.getThisMonthWaterPowerTons(ctx, years, dormNumber, totalWaterTons, totalElecDegrees);
         JSONUtils.writeJson(response, result);
     }
@@ -85,28 +85,28 @@ public class WaterPowerMeterReadingEditHandler extends EditHandler {
     
     
 //    /**
-//     * 获取当月用水电吨数
+//     * 鑾峰彇褰撴湀鐢ㄦ按鐢靛惃鏁�
 //     * @param request
 //     * @param response
 //     * @param modelMap
 //     */
 //    public void getWaterPowerNewAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws BOSException, SHRWebException {
-//        String years = request.getParameter("years");//年月
-//        //用水抄表数
+//        String years = request.getParameter("years");//骞存湀
+//        //鐢ㄦ按鎶勮〃鏁�
 //        String totalWaterTonsStr = request.getParameter("totalWaterTons") == "" ? "0" : request.getParameter("totalWaterTons");
 //        BigDecimal totalWaterTons = new BigDecimal(totalWaterTonsStr);
-//        //用电抄表数
+//        //鐢ㄧ數鎶勮〃鏁�
 //        String totalElecDegreesStr = request.getParameter("totalElecDegrees") == "" ? "0" : request.getParameter("totalElecDegrees");
 //        BigDecimal totalElecDegrees = new BigDecimal(totalElecDegreesStr);
-//      //用水基准数
+//      //鐢ㄦ按鍩哄噯鏁�
 //        String waterBaseRead = request.getParameter("waterBaseRead") == "" ? "0" : request.getParameter("waterBaseRead");
 //        BigDecimal waterBaseReads = new BigDecimal(waterBaseRead);
-//      //用电基准数
+//      //鐢ㄧ數鍩哄噯鏁�
 //        String elecBaseRead = request.getParameter("elecBaseRead") == "" ? "0" : request.getParameter("elecBaseRead");
 //        BigDecimal elecBaseReads = new BigDecimal(elecBaseRead);
 //        
-//        String dormNumber = request.getParameter("dormNumber");//宿舍编码
-//        boolean calcInterval = request.getParameter("calcInterval").isEmpty();//是否取消自动计算当月水电
+//        String dormNumber = request.getParameter("dormNumber");//瀹胯垗缂栫爜
+//        boolean calcInterval = request.getParameter("calcInterval").isEmpty();//鏄�惁鍙栨秷鑷�姩璁$畻褰撴湀姘寸數
 //        Map result = WaterPowerUtil.getThisMonthWaterPowerTons(ctx, years, dormNumber, totalWaterTons, totalElecDegrees);
 //        JSONUtils.writeJson(response, result);
 //    }
@@ -115,15 +115,12 @@ public class WaterPowerMeterReadingEditHandler extends EditHandler {
     
 
     /**
-     * 获取上月用水电吨数
-     * @param date
-     * @param dormNumber
-     * @return
+     * 鑾峰彇鏈€鍚庝竴娆℃按鐢靛惃鏁�
      * @throws BOSException
      */
     public void getLastMWaterPowerAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws BOSException {
-    	  String dormNumber = request.getParameter("dormNumber");//宿舍编码
-    	  String years = request.getParameter("years");//年月
+    	  String dormNumber = request.getParameter("dormNumber");//瀹胯垗缂栫爜
+    	  String years = request.getParameter("years");//骞存湀
     	  try {
     		  if(StringUtils.isNotBlank(dormNumber) && StringUtils.isNotBlank(years) ) {
     			  Map lastWaterPowerTons = WaterPowerUtil.getLastWaterPowerTons(ctx, years, dormNumber);
@@ -139,14 +136,14 @@ public class WaterPowerMeterReadingEditHandler extends EditHandler {
     
     
 //    /**
-//     * 获取上次用水电数
+//     * 鑾峰彇涓婃�鐢ㄦ按鐢垫暟
 //     * @param request
 //     * @param response
 //     * @param modelMap
 //     */
 //    public void getLastWEValAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws BOSException, SHRWebException {
-//    	String years = request.getParameter("years");//年月
-//    	String dormNumber = request.getParameter("dormNumber");//宿舍编码
+//    	String years = request.getParameter("years");//骞存湀
+//    	String dormNumber = request.getParameter("dormNumber");//瀹胯垗缂栫爜
 //    	Map result = WaterPowerUtil.getLastWEValue(ctx, years, dormNumber );
 //    	JSONUtils.writeJson(response, result);
 //    }

+ 12 - 12
websrc/com/kingdee/eas/custom/dormitorysystem/waterpower/importService/WaterPowerMeterReadingImportService.java

@@ -19,7 +19,7 @@ import java.util.Map;
 /**
  * @author qingwu
  * @date 2025/4/22
- * @apiNote 水电每月抄表
+ * @apiNote 姘寸數姣忔湀鎶勮〃
  */
 public class WaterPowerMeterReadingImportService extends BaseImportService {
     Logger logger = Logger.getLogger(this.getClass());
@@ -27,39 +27,39 @@ public class WaterPowerMeterReadingImportService extends BaseImportService {
     @Override
     protected void verifyRow(BaseRowInfo row) throws ImportException {
         super.verifyRow(row);
-        String dormNumber = row.getValueOfString("dormitory");//房间房号
+        String dormNumber = row.getValueOfString("dormitory");//鎴块棿鎴垮彿
         logger.error("verifyRow--dormNumber--" + dormNumber);
         String[] parts = dormNumber.split("##");
-        String years = row.getValueOfString("years");//年月
-        String totalWaterTons = row.getValueOfString("totalWaterTons");//用水总吨数
-        String totalElecDegrees = row.getValueOfString("totalElecDegrees");//用电总度数
+        String years = row.getValueOfString("years");//骞存湀
+        String totalWaterTons = row.getValueOfString("totalWaterTons");//鐢ㄦ按鎬诲惃鏁�
+        String totalElecDegrees = row.getValueOfString("totalElecDegrees");//鐢ㄧ數鎬诲害鏁�
         Map dataMap = WaterPowerUtil.getDate(years.substring(0, years.lastIndexOf("-")));
         String previousMonth = (String) dataMap.get("previousMonth");
         try {
             Map<String, BigDecimal> waterPowerMap = WaterPowerUtil.getWaterPower(this.getContext(), previousMonth, dormNumber,true);
             if (waterPowerMap.size() > 0) {
-                BigDecimal water = waterPowerMap.get("water");//上月总水费
-                BigDecimal power = waterPowerMap.get("power");//上月总电费
+                BigDecimal water = waterPowerMap.get("water");//涓婃湀鎬绘按璐�
+                BigDecimal power = waterPowerMap.get("power");//涓婃湀鎬荤數璐�
                 BigDecimal waterTons = new BigDecimal(totalWaterTons);
                 BigDecimal elecDegrees = new BigDecimal(totalElecDegrees);
-                //用水总吨数:水表累计读数,≥上月总吨数,且≥0;
-                //用电总度数:电表累计读数,≥上月总度数,且≥0;
+                //鐢ㄦ按鎬诲惃鏁帮細姘磋〃绱��璇绘暟锛屸墺涓婃湀鎬诲惃鏁帮紝涓斺墺0锛�
+                //鐢ㄧ數鎬诲害鏁帮細鐢佃〃绱��璇绘暟锛屸墺涓婃湀鎬诲害鏁帮紝涓斺墺0锛�
                 if ((waterTons.compareTo(BigDecimal.ZERO) > 0 && elecDegrees.compareTo(BigDecimal.ZERO) > 0) &&
                         (elecDegrees.compareTo(power) < 0 && elecDegrees.compareTo(water) < 0)
                 ) {
-                    throw new ImportException("本月水电总吨数不可小于上月水电总吨数!");
+                    throw new ImportException("鏈�湀姘寸數鎬诲惃鏁颁笉鍙�皬浜庝笂鏈堟按鐢垫€诲惃鏁帮紒");
                 }
             }
             IDormitory iDormitory = DormitoryFactory.getLocalInstance(this.getContext());
             boolean exists = iDormitory.exists("where number ='" + dormNumber + "'");
             if (!exists) {
-                throw new ImportException(dormNumber + "该房间不存在!");
+                throw new ImportException(dormNumber + "璇ユ埧闂翠笉瀛樺湪锛�");
             }
         } catch (Exception e) {
             e.printStackTrace();
             throw new ImportException(e);
         }
-        //throw new ImportException(housePlace + roomNumber + "房间不存在,请在员工信息人才房信息进行维护!!");
+        //throw new ImportException(housePlace + roomNumber + "鎴块棿涓嶅瓨鍦�紝璇峰湪鍛樺伐淇℃伅浜烘墠鎴夸俊鎭�繘琛岀淮鎶わ紒锛�");
     }
 
     @Override

+ 27 - 24
websrc/com/kingdee/eas/custom/dormitorysystem/waterpower/utils/WaterPowerUtil.java

@@ -21,6 +21,7 @@ import com.kingdee.eas.custom.dormitorysystem.waterpower.WaterPowerMeterReadingC
 import com.kingdee.eas.custom.dormitorysystem.waterpower.WaterPowerMeterReadingFactory;
 import com.kingdee.eas.custom.dormitorysystem.waterpower.WaterPowerMeterReadingInfo;
 import com.kingdee.shr.base.syssetting.exception.ShrWebBizException;
+import org.apache.commons.lang3.StringUtils;
 
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
@@ -52,7 +53,7 @@ public class WaterPowerUtil {
             IWaterPowerMeterReading iWaterPowerMeterReading = WaterPowerMeterReadingFactory.getLocalInstance(ctx);
             boolean exists = iWaterPowerMeterReading.exists(filterInfo);
             if (exists) {
-                throw new ShrWebBizException(dormitoryInfo.getName() + "房间已经存在" + formatter.format(years) + "月的抄表信息!");
+                throw new ShrWebBizException(dormitoryInfo.getName() + "鎴块棿宸茬粡瀛樺湪" + formatter.format(years) + "鏈堢殑鎶勮〃淇℃伅锛�");
             }
         } catch (
                 Exception e) {
@@ -66,14 +67,14 @@ public class WaterPowerUtil {
         Map<String, String> dateMap = getDate(years);
         String previousMonth = dateMap.get("previousMonth");
         String twoMonthsAgo = dateMap.get("twoMonthsAgo");
-        //获取上个月的水电总吨数
-        //水总吨数
+        //鑾峰彇涓婁釜鏈堢殑姘寸數鎬诲惃鏁�
+        //姘存€诲惃鏁�
         BigDecimal water = BigDecimal.ZERO;
-        //电总吨数
+        //鐢垫€诲惃鏁�
         BigDecimal power = BigDecimal.ZERO;
-        //当月水吨数 ?本月实际用水量,计算(本月-上月,如上月无数据-上上月,如还无数据则直接显示“用水总吨数”);
+        //褰撴湀姘村惃鏁� ?鏈�湀瀹為檯鐢ㄦ按閲忥紝璁$畻锛堟湰鏈�-涓婃湀锛屽�涓婃湀鏃犳暟鎹�-涓婁笂鏈堬紝濡傝繕鏃犳暟鎹�垯鐩存帴鏄剧ず鈥滅敤姘存€诲惃鏁扳€濓級锛�
         BigDecimal curMonthWater = BigDecimal.ZERO;
-        //当月电度数 ?本月实际用电量,计算(本月-上月,如上月无数据-上上月,如还无数据则直接显示“用电总度数”);
+        //褰撴湀鐢靛害鏁� ?鏈�湀瀹為檯鐢ㄧ數閲忥紝璁$畻锛堟湰鏈�-涓婃湀锛屽�涓婃湀鏃犳暟鎹�-涓婁笂鏈堬紝濡傝繕鏃犳暟鎹�垯鐩存帴鏄剧ず鈥滅敤鐢垫€诲害鏁扳€濓級锛�
         BigDecimal curMonthElecDegrees = BigDecimal.ZERO;
         Map<String, BigDecimal> previousMonthMap = getWaterPower(ctx, previousMonth, dormNumber,true);
         if (previousMonthMap.size() > 0) {
@@ -82,7 +83,7 @@ public class WaterPowerUtil {
             curMonthWater = totalWaterTons.subtract(water);
             curMonthElecDegrees = totalElecDegrees.subtract(power);
         } else {
-            //获取上上个月的水电总吨数
+            //鑾峰彇涓婁笂涓�湀鐨勬按鐢垫€诲惃鏁�
             previousMonthMap = getWaterPower(ctx, twoMonthsAgo, dormNumber,true);
             if (previousMonthMap.size() > 0) {
                 water = previousMonthMap.get("water");
@@ -94,31 +95,34 @@ public class WaterPowerUtil {
             curMonthElecDegrees = totalElecDegrees;
         }
         Map result = new HashMap();
-        result.put("curMonthWater", curMonthWater.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : curMonthWater);//当月水吨数
-        result.put("curMonthElecDegrees", curMonthElecDegrees.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : curMonthElecDegrees);//当月电度数
+        result.put("curMonthWater", curMonthWater.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : curMonthWater);//褰撴湀姘村惃鏁�
+        result.put("curMonthElecDegrees", curMonthElecDegrees.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : curMonthElecDegrees);//褰撴湀鐢靛害鏁�
         return result;
     }
 
     /**
-     * 获取上月用水电吨数
-     *
+     * 鑾峰彇涓婃湀鐢ㄦ按鐢靛惃鏁�
      * @param date
      * @param dormNumber
      * @return
      * @throws BOSException
      */
-    public static Map getWaterPower(Context ctx, String date, String dormNumber,boolean isEquals) throws BOSException {
+    public static Map getWaterPower(Context ctx, String date, String roomId,boolean isEquals) throws BOSException {
         Map<String, String> map = new HashMap();
+        if(StringUtils.isEmpty(date) || StringUtils.isEmpty(roomId)){
+            return map;
+        }
+
         FilterInfo filterInfo = new FilterInfo();
         FilterItemCollection filterItems = filterInfo.getFilterItems();
-        //上个月:previousMonth   上上个月:
+        //涓婁釜鏈�:previousMonth   涓婁笂涓�湀:
         if(isEquals) {
         	filterItems.add(new FilterItemInfo("years", date + "-01 00:00:00"));
         }else {
         	filterItems.add(new FilterItemInfo("years", date + "-01 00:00:00",CompareType.LESS_EQUALS));
         }
-        filterItems.add(new FilterItemInfo("dormitory.number", dormNumber));
-        //获取最大数
+        filterItems.add(new FilterItemInfo("dormitory.id", roomId));
+        //鑾峰彇鏈€澶ф暟
         SorterItemCollection sorter = new  SorterItemCollection();
         SorterItemInfo sorterItemInfo = new SorterItemInfo("years");
         sorterItemInfo.setSortType(SortType.DESCEND);
@@ -129,7 +133,7 @@ public class WaterPowerUtil {
         selectItem.add(new SelectorItemInfo("createTime"));
         EntityViewInfo entityViewInfo = EntityViewInfo.getInstance(filterInfo, selectItem, sorter);
         
-        //水电每月抄表信息
+        //姘寸數姣忔湀鎶勮〃淇℃伅
         IWaterPowerMeterReading iWaterPowerMeterReading = WaterPowerMeterReadingFactory.getLocalInstance(ctx);
         WaterPowerMeterReadingCollection waterPowerMeterReadingCollection = iWaterPowerMeterReading.getWaterPowerMeterReadingCollection(entityViewInfo);
         if(null != waterPowerMeterReadingCollection && waterPowerMeterReadingCollection.size()>0) {
@@ -146,14 +150,14 @@ public class WaterPowerUtil {
 
     public static Map getDate(String dateStr) {
         Map map = new HashMap();
-        // 定义日期格式
+        // 瀹氫箟鏃ユ湡鏍煎紡
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
-        // 将字符串转换为 YearMonth 对象
+        // 灏嗗瓧绗︿覆杞�崲涓� YearMonth 瀵硅薄
         YearMonth targetDate = YearMonth.parse(dateStr, formatter);
-        // 获取上个月
+        // 鑾峰彇涓婁釜鏈�
         YearMonth previousMonth = targetDate.minusMonths(1);
         map.put("previousMonth", formatter.format(previousMonth));
-        // 获取上上个月
+        // 鑾峰彇涓婁笂涓�湀
         YearMonth twoMonthsAgo = targetDate.minusMonths(2);
         map.put("twoMonthsAgo", formatter.format(twoMonthsAgo));
         return map;
@@ -163,9 +167,8 @@ public class WaterPowerUtil {
     
     
     
-    
     /**
-     * 获取上次抄表数据 
+     * 鑾峰彇涓婃�鎶勮〃鏁版嵁 
      * @param ctx
      * @param years
      * @param dormNumber
@@ -173,8 +176,8 @@ public class WaterPowerUtil {
      * @throws BOSException
      * 20251124
      */
-    public static Map getLastWaterPowerTons(Context ctx, String years, String dormNumber ) throws BOSException {
-        Map<String, String> previousMonthMap = getWaterPower(ctx, years, dormNumber,false);
+    public static Map getLastWaterPowerTons(Context ctx, String years, String roomId ) throws BOSException {
+        Map<String, String> previousMonthMap = getWaterPower(ctx, years, roomId,false);
         return previousMonthMap;
     }