9060 4 days ago
parent
commit
94659626fd

+ 437 - 0
metadata/com/kingdee/eas/custom/dormitorysystem/application/app/CT_APP_CheckInApplicationEntry.table

@@ -0,0 +1,437 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dataTable xmlns="com.kingdee.bos.metadata">
+    <package>com.kingdee.eas.custom.dormitorysystem.application.app</package>
+    <name>CT_APP_CheckInApplicationEntry</name>
+    <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].alias</alias>
+    <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].description</description>
+    <userDefined>true</userDefined>
+    <bizUnitPK />
+    <columns>
+        <column>
+            <name>FParentID</name>
+            <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FParentID].alias</alias>
+            <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FParentID].description</description>
+            <userDefined>true</userDefined>
+            <isMultilingual>false</isMultilingual>
+            <isEncoded>false</isEncoded>
+            <isNullable>true</isNullable>
+            <defaultValue />
+            <sqlType>VARCHAR</sqlType>
+            <length>44</length>
+            <scale>0</scale>
+            <precision>44</precision>
+        </column>
+        <column>
+            <name>CFPersonID</name>
+            <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFPersonID].alias</alias>
+            <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFPersonID].description</description>
+            <userDefined>true</userDefined>
+            <isMultilingual>false</isMultilingual>
+            <isEncoded>false</isEncoded>
+            <isNullable>true</isNullable>
+            <defaultValue />
+            <sqlType>VARCHAR</sqlType>
+            <length>44</length>
+            <scale>0</scale>
+            <precision>0</precision>
+        </column>
+        <column>
+            <name>CFAdminOrgID</name>
+            <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFAdminOrgID].alias</alias>
+            <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFAdminOrgID].description</description>
+            <userDefined>true</userDefined>
+            <isMultilingual>false</isMultilingual>
+            <isEncoded>false</isEncoded>
+            <isNullable>true</isNullable>
+            <defaultValue />
+            <sqlType>VARCHAR</sqlType>
+            <length>44</length>
+            <scale>0</scale>
+            <precision>0</precision>
+        </column>
+        <column>
+            <name>CFPositionID</name>
+            <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFPositionID].alias</alias>
+            <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFPositionID].description</description>
+            <userDefined>true</userDefined>
+            <isMultilingual>false</isMultilingual>
+            <isEncoded>false</isEncoded>
+            <isNullable>true</isNullable>
+            <defaultValue />
+            <sqlType>VARCHAR</sqlType>
+            <length>44</length>
+            <scale>0</scale>
+            <precision>0</precision>
+        </column>
+        <column>
+            <name>CFCheckInRoomID</name>
+            <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckInRoomID].alias</alias>
+            <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckInRoomID].description</description>
+            <userDefined>true</userDefined>
+            <isMultilingual>false</isMultilingual>
+            <isEncoded>false</isEncoded>
+            <isNullable>true</isNullable>
+            <defaultValue />
+            <sqlType>VARCHAR</sqlType>
+            <length>44</length>
+            <scale>0</scale>
+            <precision>0</precision>
+        </column>
+        <column>
+            <name>CFNotes</name>
+            <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFNotes].alias</alias>
+            <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFNotes].description</description>
+            <userDefined>true</userDefined>
+            <isMultilingual>false</isMultilingual>
+            <isEncoded>false</isEncoded>
+            <isNullable>true</isNullable>
+            <defaultValue />
+            <sqlType>VARCHAR</sqlType>
+            <length>2000</length>
+            <scale>0</scale>
+            <precision>2000</precision>
+        </column>
+        <column>
+            <name>FSeq</name>
+            <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FSeq].alias</alias>
+            <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FSeq].description</description>
+            <userDefined>true</userDefined>
+            <isMultilingual>false</isMultilingual>
+            <isEncoded>false</isEncoded>
+            <isNullable>true</isNullable>
+            <defaultValue />
+            <sqlType>INT</sqlType>
+            <length>4</length>
+            <scale>0</scale>
+            <precision>4</precision>
+        </column>
+        <column>
+            <name>FID</name>
+            <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FID].alias</alias>
+            <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FID].description</description>
+            <userDefined>true</userDefined>
+            <isMultilingual>false</isMultilingual>
+            <isEncoded>false</isEncoded>
+            <isNullable>false</isNullable>
+            <defaultValue />
+            <sqlType>VARCHAR</sqlType>
+            <length>44</length>
+            <scale>0</scale>
+            <precision>44</precision>
+        </column>
+        <column>
+            <name>CFCheckInDate</name>
+            <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckInDate].alias</alias>
+            <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckInDate].description</description>
+            <userDefined>true</userDefined>
+            <isMultilingual>false</isMultilingual>
+            <isEncoded>false</isEncoded>
+            <isNullable>true</isNullable>
+            <defaultValue />
+            <sqlType>DATETIME</sqlType>
+            <length>8</length>
+            <scale>0</scale>
+            <precision>0</precision>
+        </column>
+        <column>
+            <name>CFCheckoutDate</name>
+            <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckoutDate].alias</alias>
+            <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckoutDate].description</description>
+            <userDefined>true</userDefined>
+            <isMultilingual>false</isMultilingual>
+            <isEncoded>false</isEncoded>
+            <isNullable>true</isNullable>
+            <defaultValue />
+            <sqlType>DATETIME</sqlType>
+            <length>8</length>
+            <scale>0</scale>
+            <precision>0</precision>
+        </column>
+        <column>
+            <name>CFOccupantsID</name>
+            <alias>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFOccupantsID].alias</alias>
+            <description>dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFOccupantsID].description</description>
+            <userDefined>true</userDefined>
+            <isMultilingual>false</isMultilingual>
+            <isEncoded>false</isEncoded>
+            <isNullable>true</isNullable>
+            <defaultValue />
+            <sqlType>VARCHAR</sqlType>
+            <length>44</length>
+            <scale>0</scale>
+            <precision>0</precision>
+        </column>
+    </columns>
+    <primaryKey>
+        <name>PK_CheckInApplicat</name>
+        <userDefined>true</userDefined>
+        <primaryKeyColumns>
+            <primaryKeyColumn>
+                <indexID>0</indexID>
+                <sortType>ASC</sortType>
+                <column>
+                    <key name="name" value="FID" />
+                </column>
+            </primaryKeyColumn>
+        </primaryKeyColumns>
+    </primaryKey>
+    <foreignKeys>
+        <foreignKey>
+            <name>CFK_APP_APPCIAEArn</name>
+            <userDefined>true</userDefined>
+            <refTable>
+                <key name="package" value="com.kingdee.eas.custom.dormitorysystem.application.app" />
+                <key name="name" value="CT_APP_CheckInApplication" />
+            </refTable>
+            <fkColumnPairs>
+                <fkColumnPair>
+                    <sequence>0</sequence>
+                    <refColumn>
+                        <key name="name" value="FID" />
+                    </refColumn>
+                    <fkColumn>
+                        <key name="name" value="FParentID" />
+                    </fkColumn>
+                </fkColumnPair>
+            </fkColumnPairs>
+        </foreignKey>
+        <foreignKey>
+            <name>CFK_APP_APPCIAEErs</name>
+            <userDefined>true</userDefined>
+            <refTable>
+                <key name="package" value="com.kingdee.eas.basedata.person" />
+                <key name="name" value="T_BD_Person" />
+            </refTable>
+            <fkColumnPairs>
+                <fkColumnPair>
+                    <sequence>0</sequence>
+                    <refColumn>
+                        <key name="name" value="FID" />
+                    </refColumn>
+                    <fkColumn>
+                        <key name="name" value="CFPersonID" />
+                    </fkColumn>
+                </fkColumnPair>
+            </fkColumnPairs>
+        </foreignKey>
+        <foreignKey>
+            <name>CFK_APP_APPCIAEDmO</name>
+            <userDefined>true</userDefined>
+            <refTable>
+                <key name="package" value="com.kingdee.eas.basedata.org" />
+                <key name="name" value="T_ORG_Admin" />
+            </refTable>
+            <fkColumnPairs>
+                <fkColumnPair>
+                    <sequence>0</sequence>
+                    <refColumn>
+                        <key name="name" value="FID" />
+                    </refColumn>
+                    <fkColumn>
+                        <key name="name" value="CFAdminOrgID" />
+                    </fkColumn>
+                </fkColumnPair>
+            </fkColumnPairs>
+        </foreignKey>
+        <foreignKey>
+            <name>CFK_APP_APPCIAEOsx</name>
+            <userDefined>true</userDefined>
+            <refTable>
+                <key name="package" value="com.kingdee.eas.basedata.org" />
+                <key name="name" value="T_ORG_Position" />
+            </refTable>
+            <fkColumnPairs>
+                <fkColumnPair>
+                    <sequence>0</sequence>
+                    <refColumn>
+                        <key name="name" value="FID" />
+                    </refColumn>
+                    <fkColumn>
+                        <key name="name" value="CFPositionID" />
+                    </fkColumn>
+                </fkColumnPair>
+            </fkColumnPairs>
+        </foreignKey>
+        <foreignKey>
+            <name>CFK_APP_APPCIAEHIR</name>
+            <userDefined>true</userDefined>
+            <refTable>
+                <key name="package" value="com.kingdee.eas.custom.dormitorysystem.dormitory.app" />
+                <key name="name" value="CT_DOR_Dormitory" />
+            </refTable>
+            <fkColumnPairs>
+                <fkColumnPair>
+                    <sequence>0</sequence>
+                    <refColumn>
+                        <key name="name" value="FID" />
+                    </refColumn>
+                    <fkColumn>
+                        <key name="name" value="CFCheckInRoomID" />
+                    </fkColumn>
+                </fkColumnPair>
+            </fkColumnPairs>
+        </foreignKey>
+        <foreignKey>
+            <name>CFK_APP_APPCIAEChh</name>
+            <userDefined>true</userDefined>
+            <refTable>
+                <key name="package" value="com.kingdee.eas.custom.dormitorysystem.occupants.app" />
+                <key name="name" value="CT_OCC_Occupants" />
+            </refTable>
+            <fkColumnPairs>
+                <fkColumnPair>
+                    <sequence>0</sequence>
+                    <refColumn>
+                        <key name="name" value="FID" />
+                    </refColumn>
+                    <fkColumn>
+                        <key name="name" value="CFOccupantsID" />
+                    </fkColumn>
+                </fkColumnPair>
+            </fkColumnPairs>
+        </foreignKey>
+    </foreignKeys>
+    <resource>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="分录" />
+            <lang locale="zh_HK" value="分錄" />
+            <lang locale="zh_TW" value="分錄" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFAdminOrgID].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="所在部门" />
+            <lang locale="zh_HK" value="所在部門" />
+            <lang locale="zh_TW" value="所在部門" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFAdminOrgID].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="所在部门" />
+            <lang locale="zh_HK" value="所在部門" />
+            <lang locale="zh_TW" value="所在部門" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckInDate].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="入住日期" />
+            <lang locale="zh_HK" value="入住日期" />
+            <lang locale="zh_TW" value="入住日期" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckInDate].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="入住日期" />
+            <lang locale="zh_HK" value="入住日期" />
+            <lang locale="zh_TW" value="入住日期" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckInRoomID].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="入住房间" />
+            <lang locale="zh_HK" value="入住房間" />
+            <lang locale="zh_TW" value="入住房間" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckInRoomID].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="入住房间" />
+            <lang locale="zh_HK" value="入住房間" />
+            <lang locale="zh_TW" value="入住房間" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckoutDate].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="退宿日期" />
+            <lang locale="zh_HK" value="退宿日期" />
+            <lang locale="zh_TW" value="退宿日期" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFCheckoutDate].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="退宿日期" />
+            <lang locale="zh_HK" value="退宿日期" />
+            <lang locale="zh_TW" value="退宿日期" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFNotes].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="注意事项" />
+            <lang locale="zh_HK" value="注意事項" />
+            <lang locale="zh_TW" value="注意事項" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFNotes].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="注意事项" />
+            <lang locale="zh_HK" value="注意事項" />
+            <lang locale="zh_TW" value="注意事項" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFOccupantsID].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="入住人员信息" />
+            <lang locale="zh_HK" value="入住人員信息" />
+            <lang locale="zh_TW" value="入住人員信息" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFOccupantsID].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="入住人员信息" />
+            <lang locale="zh_HK" value="入住人員信息" />
+            <lang locale="zh_TW" value="入住人員信息" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFPersonID].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="人员" />
+            <lang locale="zh_HK" value="人員" />
+            <lang locale="zh_TW" value="人員" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFPersonID].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="人员" />
+            <lang locale="zh_HK" value="人員" />
+            <lang locale="zh_TW" value="人員" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFPositionID].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="所属职位" />
+            <lang locale="zh_HK" value="所屬職位" />
+            <lang locale="zh_TW" value="所屬職位" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[CFPositionID].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="所属职位" />
+            <lang locale="zh_HK" value="所屬職位" />
+            <lang locale="zh_TW" value="所屬職位" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FID].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="ID" />
+            <lang locale="zh_HK" value="ID" />
+            <lang locale="zh_TW" value="ID" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FID].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="" />
+            <lang locale="zh_TW" value="null" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FParentID].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="null" />
+            <lang locale="zh_HK" value="null" />
+            <lang locale="zh_TW" value="null" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FParentID].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="" />
+            <lang locale="zh_TW" value="null" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FSeq].alias">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="单据分录序列号" />
+            <lang locale="zh_HK" value="單據分錄序列號" />
+            <lang locale="zh_TW" value="單據分錄序列號" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].columns.column[FSeq].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="单据分录序列号(定义为序列属性即使用{seq})" />
+            <lang locale="zh_HK" value="單據分錄序列號(定義為序列屬性即使用{seq})" />
+            <lang locale="zh_TW" value="單據分錄序列號(定義為序列屬性即使用{seq})" />
+        </rs>
+        <rs key="dataTable[com.kingdee.eas.custom.dormitorysystem.application.app.CT_APP_CheckInApplicationEntry].description">
+            <lang locale="en_US" value="null" />
+            <lang locale="zh_CN" value="" />
+            <lang locale="zh_TW" value="null" />
+        </rs>
+    </resource>
+</dataTable>

+ 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;
+    }
+}

+ 86 - 0
websrc/com/kingdee/shr/ats/web/util/io/FillCardFileNewServiceEx.java

@@ -0,0 +1,86 @@
+package com.kingdee.shr.ats.web.util.io;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.framework.CoreBaseCollection;
+import com.kingdee.eas.framework.CoreBaseInfo;
+import com.kingdee.eas.hr.ats.*;
+import com.kingdee.eas.hr.ats.util.AtsDateUtils;
+import com.kingdee.eas.hr.ats.util.common.AtsCollectionUtile;
+import com.kingdee.shr.base.syssetting.app.io.fileImport.BaseRowInfo;
+import com.kingdee.shr.base.syssetting.app.io.fileImport.ImportException;
+
+import java.util.Date;
+
+/**fillcard
+ * description: FillCardFileNewServiceEx <br>
+ * date: 2025/6/30 11:03 <br>
+ * author: lhbj <br>
+ * version: 1.0 <br>
+ */
+public class FillCardFileNewServiceEx extends FillCardFileNewService {
+
+    public void importRow(BaseRowInfo row) throws ImportException {
+        super.importRow(row);
+        try {
+            CoreBaseCollection insertColls1 = this.insertColls;
+            CoreBaseCollection punchColls1 = this.punchColls;
+            CoreBaseCollection insertCollsTemp1 = this.insertCollsTemp;
+            FillSignCardInfo fillSignCardInfo1 = this.fillSignCardInfo;
+            System.out.println("FillCardFileNewServiceEx:insertColls1->" + insertColls1.size());
+            IFillSignCard fillSignCard = FillSignCardFactory.getLocalInstance(this.getContext());
+            IFillSignCardEntry fillSignCardEntry = FillSignCardEntryFactory.getLocalInstance(this.getContext());
+            for (int i = 0; i < insertColls1.size(); i++) {
+                FillSignCardInfo cardInfo = (FillSignCardInfo) insertColls1.get(i);
+                CoreBaseCollection collection = new CoreBaseCollection();
+                collection.add(cardInfo);
+                fillSignCard.saveBatchData(collection);
+                fillSignCardEntry.saveBatchData(AtsCollectionUtile.toCoreCollection(cardInfo.getEntries()));
+            }
+            System.out.println("FillCardFileNewServiceEx:punchColls1->" + punchColls1.size());
+            System.out.println("FillCardFileNewServiceEx:insertCollsTemp1->" + insertCollsTemp1.size());
+            System.out.println("FillCardFileNewServiceEx:fillSignCardInfo1->" + fillSignCardInfo1.size());
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    public AttencePolicyInfo getAttencePolicyInfo(Context ctx, AttendanceFileHISInfo atsFileHis, String personID, Date attendDate) {
+        AttencePolicyInfo attencePolicyInfo = null;
+        AttendanceFileHISInfo atsFileHisPre = null;
+        String attencePolicyId;
+        if (atsFileHis == null) {
+            try {
+                String attendDateStr =  AtsDateUtils.dateShortToString(attendDate);
+                attencePolicyId =  "{ts '" + attendDateStr + " 00:00:00'}";
+                String PredateStr = "{ts '" + AtsDateUtils.getPreDay(attendDateStr) + " 00:00:00'}";
+                atsFileHis = AttendanceFileHISFactory.getLocalInstance(this.getContext()).getAttendanceFileHISInfo(" where proposer.id = '" + personID + "' and effdt <= " + attencePolicyId + "and leffdt >= " + attencePolicyId + " ");
+                atsFileHisPre = AttendanceFileHISFactory.getLocalInstance(this.getContext()).getAttendanceFileHISInfo(" where proposer.id = '" + personID + "' and effdt <= " + PredateStr + "and leffdt >= " + PredateStr + " ");
+            } catch (EASBizException var11) {
+                var11.printStackTrace();
+            } catch (BOSException var12) {
+                var12.printStackTrace();
+            }
+        }
+
+        if (null == atsFileHis && atsFileHisPre != null) {
+            atsFileHis = atsFileHisPre;
+        }
+
+        if (atsFileHis != null && atsFileHis.getAttencePolicy() != null) {
+            attencePolicyId = atsFileHis.getAttencePolicy().getId().toString();
+
+            try {
+                attencePolicyInfo = AttencePolicyFactory.getLocalInstance(this.getContext()).getAttencePolicyInfo(new ObjectUuidPK(attencePolicyId));
+            } catch (EASBizException var9) {
+                var9.printStackTrace();
+            } catch (BOSException var10) {
+                var10.printStackTrace();
+            }
+        }
+
+        return attencePolicyInfo;
+    }
+}