Просмотр исходного кода

修复 退宿单反审批报错:操作失败:单据编号为TSD-20260512-00000008校验未通过:房间不能为空!

heyuan 1 месяц назад
Родитель
Сommit
af4a76893f

+ 394 - 276
src/com/kingdee/eas/custom/dormitorysystem/application/utils/ValidateRoomAvailableByBillIdsUtil.java

@@ -4,6 +4,7 @@ import com.kingdee.bos.BOSException;
 import com.kingdee.bos.BOSObjectFactory;
 import com.kingdee.bos.Context;
 import com.kingdee.bos.dao.AbstractObjectCollection;
+import com.kingdee.bos.dao.IObjectPK;
 import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
 import com.kingdee.bos.metadata.entity.*;
 import com.kingdee.bos.metadata.query.util.CompareType;
@@ -30,6 +31,7 @@ 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 com.kingdee.util.UuidException;
 import org.apache.log4j.Logger;
 
 import java.util.*;
@@ -42,10 +44,9 @@ import java.util.*;
 public class ValidateRoomAvailableByBillIdsUtil {
     private static Logger logger = Logger.getLogger(ValidateRoomAvailableByBillIdsUtil.class);
     private static String CHECKOUTAPPLICATIONBOSTYPE = "EBE6D24D";//退宿单bosType
-    private static String ROOMCHANGEAPPLICATIONBOSTYPE = "0CDEF948";  //换宿单 coyle
+    private static String ROOMCHANGEAPPLICATIONBOSTYPE = "0CDEF948";
     private static String CHECKINAPPLICATIONBOSTYPE = "412D7440";//入住单bosType
 
-    
     /**
      * 开始校验
      *
@@ -62,138 +63,147 @@ public class ValidateRoomAvailableByBillIdsUtil {
             logger.error("单据id不能为空!");
             throw new BOSException("单据id不能为空!");
         }
-        Map<String, List<Map<String, Date>>> roomListMap = new HashMap<String, List<Map<String, Date>>>();
-        List<String> errorMsgList = new ArrayList<String>();
-        BOSObjectType bosType = BOSUuid.read(billIds.split(",")[0]).getType();
-        ICoreBillBase iCoreBillBase = (ICoreBillBase) BOSObjectFactory.createBOSObject(ctx, bosType);
-        SelectorItemCollection sic = new SelectorItemCollection();
-        sic.add("*");
-        sic.add("entrys.*");
-        sic.add("entrys.person.*");
-        sic.add("entrys.person.personType.*");
-        if(CHECKOUTAPPLICATIONBOSTYPE.equals(bosType.toString())) {
-            //退宿单
-            sic.add("entrys.currentRoom.DormitoryType.*");
-            sic.add("entrys.currentRoom.*");
-        }else if(CHECKINAPPLICATIONBOSTYPE.equals(bosType.toString())) {
-            //入住单
-            sic.add("entrys.checkInRoom.DormitoryType.*");
-            sic.add("entrys.checkInRoom.*");
-        }
-        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();
-            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.toString())) {
-                        //换宿单
-                        //入住日期
-                        checkInDate = entryInfo.getDate("adjustmentDate");
-                    } else {
-                        //入住日期
-                        checkInDate = entryInfo.getDate("checkInDate");
-                    }
-                    if (checkInDate == null) {
-                        throw new BOSException("入住日期不能为空!");
-                    }
-                    //退宿日期
-                    Date checkoutDate = null;
-                    if (CHECKOUTAPPLICATIONBOSTYPE.equals(bosType.toString())) {
-                        //退宿单
-                        checkoutDate = entryInfo.getDate("checkoutDate");
-                    } else {
-                    	checkoutDate = entryInfo.getDate("checkoutDate");
-                    }
-                    if (checkoutDate == null) {
-                        throw new BOSException("退宿日期不能为空!");
-                    }
-                    //人员
-                    PersonInfo personInfo = (PersonInfo) entryInfo.getObjectValue("person");
-                    if (personInfo == null) {
-                        throw new BOSException("人员不能为空!");
-                    }
-                    //房间
-                    DormitoryInfo dormitory = null;
-                    if (CHECKOUTAPPLICATIONBOSTYPE.equals(bosType.toString())) {
-                        //退宿单
-                        dormitory = (DormitoryInfo) entryInfo.getObjectValue("currentRoom");
-                    } else {
-                        dormitory = (DormitoryInfo) entryInfo.getObjectValue("checkInRoom");
-                    }
-                    if (dormitory == null) {
-                        throw new BOSException("房间不能为空!");
-                    }
-                    IDormitory dorIns = DormitoryFactory.getLocalInstance(ctx);
-                    dormitory = dorIns.getDormitoryInfo(new ObjectUuidPK(dormitory.getId()));
-                    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;
-                    //存放已累加的人员入住信息数据id,避免重复累加
-                    Set<String> occupantsIds = new HashSet<String>();
-                    //1.校验房间信息
-                    validateDormitoryInfo(ctx, personInfo, dormitory);
-                    //可住人数
-                    int occupancyCapacity = dormitory.getOccupancyCapacity();
-                    //2.根据入住日期和退宿日期算出入住信息房间已住人数
-                    dormCheckInCount += getCheckInInfoByOccupants(ctx, checkInDate, checkoutDate, roomId, personType, occupantsIds);
-                    //3.根据入住日期和退宿日期算出入住申请单状态为申请中的已住人数
-                    dormCheckInCount += getCheckInInfoByCheckInApplication(ctx, checkInDate, checkoutDate, roomId, personType, billId);
-                    //4.根据入住日期和退宿日期算出换宿申请单状态为申请中的已住人数
-                    dormCheckInCount += getRoomChangeInfoByRoomChangeApplication(ctx, checkInDate, checkoutDate, roomId, personType, billId);
-                    //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++;
+        List<String> errorMsgList = null;
+        try {
+            Map<String, List<Map<String, Date>>> roomListMap = new HashMap<String, List<Map<String, Date>>>();
+            errorMsgList = new ArrayList<String>();
+            BOSObjectType bosType = BOSUuid.read(billIds.split(",")[0]).getType();
+
+            if (CHECKOUTAPPLICATIONBOSTYPE.equals(bosType)) {
+                //退宿单反审批业务
+                validateCheckoutUnAudit(ctx, billIds);
+                return;
+            }
+
+            ICoreBillBase iCoreBillBase = (ICoreBillBase) BOSObjectFactory.createBOSObject(ctx, bosType);
+            IDormitory iDormitory = DormitoryFactory.getLocalInstance(ctx);
+            SelectorItemCollection sic = new SelectorItemCollection();
+            sic.add("*");
+            sic.add("entrys.*");
+            sic.add("entrys.person.*");
+            sic.add("entrys.person.personType.*");
+            if (CHECKOUTAPPLICATIONBOSTYPE.equals(bosType)) {
+                //退宿单
+                sic.add("entrys.currentRoom.DormitoryType.*");
+                sic.add("entrys.currentRoom.*");
+            } else if (CHECKINAPPLICATIONBOSTYPE.equals(bosType)) {
+                //入住单
+                sic.add("entrys.checkInRoom.DormitoryType.*");
+                sic.add("entrys.checkInRoom.*");
+            }
+            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();
+                AbstractObjectCollection entrys = (AbstractObjectCollection) hrBillBaseInfo.get("entrys");
+                for (int j = 0; j < entrys.size(); j++) {
+                    try {
+                        HRBillBaseEntryInfo entryInfo = (HRBillBaseEntryInfo) entrys.getObject(j);
+                        Date checkInDate;
+                        if ("B371AC0A".equals(bosType)) {
+                            //换宿单
+                            //入住日期
+                            checkInDate = entryInfo.getDate("adjustmentDate");
+                        } else {
+                            //入住日期
+                            checkInDate = entryInfo.getDate("checkInDate");
+                        }
+                        //退宿日期
+                        Date checkoutDate =null;
+                        if (CHECKOUTAPPLICATIONBOSTYPE.equals(bosType)) {
+                            //退宿单
+                            checkInDate = entryInfo.getDate("oldCheckoutDate");
+                        } else {
+                            checkoutDate = entryInfo.getDate("checkoutDate");
+                        }
+                        //人员
+                        PersonInfo personInfo = (PersonInfo) entryInfo.getObjectValue("person");
+                        if (personInfo == null) {
+                            throw new BOSException("人员不能为空!");
+                        }
+                        //房间
+                        DormitoryInfo dormitory = null;
+                        if (CHECKOUTAPPLICATIONBOSTYPE.equals(bosType)) {
+                            //退宿单
+                            dormitory = (DormitoryInfo) entryInfo.getObjectValue("currentRoom");
+                        } else {
+                            dormitory = (DormitoryInfo) entryInfo.getObjectValue("checkInRoom");
+                        }
+                        if (dormitory == null) {
+                            throw new BOSException("房间不能为空!");
+                        }
+                        String roomId = dormitory.getId().toString();
+                        dormitory = iDormitory.getDormitoryInfo(new ObjectUuidPK(dormitory.getId()));
+                        //根据入住日期,性别,员工类别查询可选房间
+                        //人员类型
+                        PersonDormitoryTypeInfo personType = (PersonDormitoryTypeInfo) personInfo.get("personType");
+                        if (personType == null) {
+                            throw new BOSException("员工[" + personInfo.getName() + "]的人员类别为空,请及时维护!");
+                        }
+                        //String personTypeId = personType.getId().toString();
+                        //已住人数
+                        int dormCheckInCount = 0;
+                        //存放已累加的人员入住信息数据id,避免重复累加
+                        Set<String> occupantsIds = new HashSet<String>();
+                        //1.校验房间信息
+                        validateDormitoryInfo(ctx, personInfo, dormitory);
+                        //可住人数
+                        int occupancyCapacity = dormitory.getOccupancyCapacity();
+                        //2.根据入住日期和退宿日期算出入住信息房间已住人数
+                        dormCheckInCount += getCheckInInfoByOccupants(ctx, checkInDate, checkoutDate, roomId, personType, occupantsIds);
+                        //3.根据入住日期和退宿日期算出入住申请单状态为申请中的已住人数
+                        dormCheckInCount += getCheckInInfoByCheckInApplication(ctx, checkInDate, checkoutDate, roomId, personType, billId);
+                        //4.根据入住日期和退宿日期算出换宿申请单状态为申请中的已住人数
+                        dormCheckInCount += getRoomChangeInfoByRoomChangeApplication(ctx, checkInDate, checkoutDate, roomId, personType, billId);
+                        //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++;
+                                }
                             }
                         }
+                        //累加当前单据人员
+                        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());
                     }
-                    //累加当前单据人员
-                    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());
                 }
             }
+        } catch (Exception e) {
+            logger.error(e.getMessage(), e);
+            e.printStackTrace();
+            throw e;
         }
         if (!errorMsgList.isEmpty()) {
             StringBuilder errorMsgBuilder = new StringBuilder();
@@ -212,8 +222,6 @@ public class ValidateRoomAvailableByBillIdsUtil {
      * @param checkoutDate 退宿日期
      * @param roomId       房间id
      * @param personType   人员类型
-     * @return
-     * @throws BOSException
      */
     private static int getRoomChangeInfoByRoomChangeApplication(
             Context ctx,
@@ -223,52 +231,58 @@ public class ValidateRoomAvailableByBillIdsUtil {
             PersonDormitoryTypeInfo personType,
             String billId
     ) 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", CompareType.INCLUDE));
-        //不包含当前单据
-        filterItems.add(new FilterItemInfo("parent.id", billId, CompareType.NOTEQUALS));
-        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) and #5  and #6");
-        SelectorItemCollection sic = new SelectorItemCollection();
-        sic.add("checkInRoom.id");
-        sic.add("person.personType.id");
-        sic.add("person.personType.name");
-        sic.add("occupants.id");
-        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);
+        try {
+            IRoomChangeApplicationEntry iRoomChangeApplicationEntry = RoomChangeApplicationEntryFactory.getLocalInstance(ctx);
+            FilterInfo filterInfo = new FilterInfo();
+            FilterItemCollection filterItems = filterInfo.getFilterItems();
             //房间
-            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 + "]不符,不能入住!");
+            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", CompareType.INCLUDE));
+            //不包含当前单据
+            filterItems.add(new FilterItemInfo("parent.id", billId, CompareType.NOTEQUALS));
+            filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) and #5  and #6");
+            SelectorItemCollection sic = new SelectorItemCollection();
+            sic.add("checkInRoom.id");
+            sic.add("person.personType.id");
+            sic.add("person.personType.name");
+            sic.add("occupants.id");
+            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++;
             }
-            //累计已住人数
-            dormCheckInCount++;
+            return dormCheckInCount;
+        } catch (BOSException e) {
+            logger.error(e.getMessage(), e);
+            e.printStackTrace();
+            throw e;
         }
-        return dormCheckInCount;
     }
 
     /**
@@ -279,8 +293,6 @@ public class ValidateRoomAvailableByBillIdsUtil {
      * @param checkoutDate 退宿日期
      * @param roomId       房间id
      * @param personType   人员类型
-     * @return
-     * @throws BOSException
      */
     private static int getCheckInInfoByCheckInApplication(
             Context ctx,
@@ -290,52 +302,58 @@ public class ValidateRoomAvailableByBillIdsUtil {
             PersonDormitoryTypeInfo personType,
             String billId
     ) 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", "1,2", CompareType.INCLUDE));
-        //不包含当前单据
-        filterItems.add(new FilterItemInfo("parent.id", billId, CompareType.NOTEQUALS));
-        filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) and #5 and #6");
-        SelectorItemCollection sic = new SelectorItemCollection();
-        sic.add("checkInRoom.id");
-        sic.add("person.personType.id");
-        sic.add("person.personType.name");
-        //sic.add("occupants.id");
-        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);
+        try {
+            ICheckInApplicationEntry iCheckInApplicationEntry = CheckInApplicationEntryFactory.getLocalInstance(ctx);
+            FilterInfo filterInfo = new FilterInfo();
+            FilterItemCollection filterItems = filterInfo.getFilterItems();
             //房间
-            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 + "]不符,不能入住!");
+            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", "1,2", CompareType.INCLUDE));
+            //不包含当前单据
+            filterItems.add(new FilterItemInfo("parent.id", billId, CompareType.NOTEQUALS));
+            filterInfo.setMaskString("#0 and ((#1 and #2) or (#3 and #4)) and #5 and #6");
+            SelectorItemCollection sic = new SelectorItemCollection();
+            sic.add("checkInRoom.id");
+            sic.add("person.personType.id");
+            sic.add("person.personType.name");
+            //sic.add("occupants.id");
+            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++;
             }
-            //累计已住人数
-            dormCheckInCount++;
+            return dormCheckInCount;
+        } catch (BOSException e) {
+            logger.error(e.getMessage(), e);
+            e.printStackTrace();
+            throw e;
         }
-        return dormCheckInCount;
     }
 
 
@@ -358,42 +376,48 @@ public class ValidateRoomAvailableByBillIdsUtil {
             PersonDormitoryTypeInfo personType,
             Set<String> occupantsIds
     ) 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");
-        sic.add("id");
-        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 + "]不符,不能入住!");
+        try {
+            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");
+            sic.add("id");
+            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 + "]不符,不能入住!");
+                }
+                occupantsIds.add(occupantsInfo.getId().toString());
+                dormCheckInCount++;
             }
-            occupantsIds.add(occupantsInfo.getId().toString());
-            dormCheckInCount++;
+            return dormCheckInCount;
+        } catch (BOSException e) {
+            logger.error(e.getMessage(), e);
+            e.printStackTrace();
+            throw e;
         }
-        return dormCheckInCount;
     }
 
     /**
@@ -411,30 +435,124 @@ public class ValidateRoomAvailableByBillIdsUtil {
             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 + "]未启用,不能入住!");
+        try {
+            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 + "]的性别不符!");
+            }
+        } catch (BOSException e) {
+            logger.error(e.getMessage(), e);
+            e.printStackTrace();
+            throw e;
         }
-        //宿舍类型
-        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 + "]的性别不符!");
+    }
+
+    /**
+     * 校验退宿单反审批
+     *
+     * @param ctx
+     * @param billIds
+     * @throws BOSException
+     */
+    private static void validateCheckoutUnAudit(
+            Context ctx,
+            String billIds
+    ) throws BOSException {
+        IDormitory iDormitory = DormitoryFactory.getLocalInstance(ctx);
+        ICheckoutApplication iCheckoutApplication = CheckoutApplicationFactory.getLocalInstance(ctx);
+        SelectorItemCollection sic = new SelectorItemCollection();
+        sic.add("*");
+        sic.add("entrys.*");
+        sic.add("entrys.person.*");
+        sic.add("entrys.person.personType.*");
+        //退宿单
+        sic.add("entrys.currentRoom.DormitoryType.*");
+        sic.add("entrys.currentRoom.*");
+
+        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);
+
+        CheckoutApplicationCollection checkoutApplicationCol = iCheckoutApplication.getCheckoutApplicationCollection(viewInfo);
+
+        for (int i = 0; i < checkoutApplicationCol.size(); i++) {
+            CheckoutApplicationInfo checkoutApplicationInfo = checkoutApplicationCol.get(i);
+            String billNo = checkoutApplicationInfo.getNumber();
+            CheckoutApplicationEntryCollection entrys = checkoutApplicationInfo.getEntrys();
+            for (int j = 0; j < entrys.size(); j++) {
+                CheckoutApplicationEntryInfo entryInfo = entrys.get(j);
+                try {
+                    PersonInfo person = entryInfo.getPerson();
+                    if (person == null) {
+                        throw new BOSException("人员不能为空!");
+                    }
+                    DormitoryInfo currentRoom = entryInfo.getCurrentRoom();
+                    if (currentRoom == null) {
+                        throw new BOSException("原退宿房间不能为空!");
+                    }
+                    currentRoom = iDormitory.getDormitoryInfo(new ObjectUuidPK(currentRoom.getId()));
+
+                    // 校验房间基础属性
+                    validateDormitoryInfo(ctx, person, currentRoom);
+                    int capacity = currentRoom.getOccupancyCapacity();
+                    // 当前已入住人数
+                    int currentCount = getCurrentOccupancyCount(ctx, currentRoom.getId().toString());
+
+                    // 反审批后需要恢复当前人员
+                    currentCount++;
+                    if (currentCount > capacity) {
+                        throw new BOSException("房间[" + currentRoom.getName() + "]当前已满,不能反审批退宿单!");
+                    }
+                } catch (Exception e) {
+                    logger.error("单据编号[" + billNo + "]反审批校验失败:" + e.getMessage(), e);
+                    throw new BOSException("单据编号[" + billNo + "]反审批校验失败:" + e.getMessage(), e);
+                }
+            }
         }
     }
+
+    /**
+     * 获取当前房间已入住人数
+     *
+     * @param ctx
+     * @param roomId
+     * @return
+     * @throws BOSException
+     */
+    private static int getCurrentOccupancyCount(
+            Context ctx,
+            String roomId) throws BOSException {
+        IOccupants iOccupants = OccupantsFactory.getLocalInstance(ctx);
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection items = filterInfo.getFilterItems();
+        items.add(new FilterItemInfo("Dormitory", roomId));
+        // 当前仍有效入住
+        items.add(new FilterItemInfo("checkoutDate", new Date(), CompareType.GREATER_EQUALS));
+        EntityViewInfo viewInfo = new EntityViewInfo();
+        viewInfo.setFilter(filterInfo);
+        OccupantsCollection col = iOccupants.getOccupantsCollection(viewInfo);
+        return col.size();
+    }
 }