package com.kingdee.eas.custom.dormitorysystem.waterelectricity.handler;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.dao.IObjectPK;
import com.kingdee.bos.framework.ejb.EJBFactory;
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.org.AdminOrgUnitInfo;
import com.kingdee.eas.basedata.org.HROrgUnitInfo;
import com.kingdee.eas.basedata.org.PositionInfo;
import com.kingdee.eas.basedata.person.PersonInfo;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.dormitorysystem.dormitory.DormitoryInfo;
import com.kingdee.eas.custom.dormitorysystem.waterelectricity.*;
import com.kingdee.eas.hr.base.HRBillStateEnum;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.shr.ats.web.util.SHRBillUtil;
import com.kingdee.shr.base.syssetting.api.bean.BatchMessageTipsHeader;
import com.kingdee.shr.base.syssetting.context.SHRContext;
import com.kingdee.shr.base.syssetting.exception.SHRWebException;
import com.kingdee.shr.base.syssetting.exception.ShrWebBizException;
import com.kingdee.shr.base.syssetting.web.json.JSONUtils;
import com.kingdee.shr.compensation.request.ParseRequestHelper;
import com.kingdee.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.ModelMap;
import shaded.com.google.common.collect.Lists;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 水电费明细计算
 * description: WaterElectricityListHandler <br>
 * date: 2025/4/24 18:09 <br>
 * author: lhbj <br>
 * version: 1.0 <br>
 */
public class WaterElectricityListHandler extends WaterElectricityBatchListHandler {
    private static Logger logger = LoggerFactory.getLogger(WaterElectricityListHandler.class);
    public static final String TABLENAME ="CT_WOE_WaterElectricity";

    /**
     * 获取水电费详细Sql
     *
     * @param startPeriodDateStr
     * @param endPeriodDateStr
     * @return
     */
    protected StringBuilder getPersonWaterElectricitySql1(String startPeriodDateStr, String endPeriodDateStr, Collection<String> billids) {
        StringBuilder sel = new StringBuilder();
        sel.append(" select  p.fid pid,p.fname_l2 pName,p.fnumber pNumber,ops.fid opsid,ops.CFCheckInDate,ops.CFCheckOutDate,ops.CFDormitoryID dormitoryID, ");
        sel.append(" wpp.fid wppid,wpp.CFStartDate,wpp.CFEndDate,wpp.CFWaterprice,wpp.CFElectricityprice, ");
        sel.append(" wpmr.fid wpmrid,wpmr.CFYears wpmrStartDate,DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,0,wpmr.CFYears)+1,0)) wpmrEndDate," +
                "isnull(wpmr.CFTotalWaterTons,0) CFTotalWaterTons,isnull(wpmr.CFTotalElecDegrees,0) CFTotalElecDegrees, ");
        sel.append(" isnull(wpmr.CFCurMonthWater,0) CFCurMonthWater,isnull(wpmr.CFCurMonthElecDegrees,0) CFCurMonthElecDegrees," +
                "wpmr.CFMeterReaPersonID,pp.FPrimaryPositionID,pp.FPersonDep, ");
        sel.append(" case ");
        sel.append("  bt.finservice ");
        sel.append("  when 1 then 'active' ");
        sel.append("  when 4 then 'active' ");
        sel.append("  else 'inactive' ");
        sel.append(" end as InService ");
        sel.append(" from CT_OCC_Occupants ops ");
        sel.append(" left join T_HR_PersonPosition pp on pp.fid =ops.CFPersonPositionID ");
        sel.append(" left join t_bd_person p on pp.FPERSONID = p.fid ");
        sel.append(" left join T_HR_BDEmployeeType bt on bt.fid = p.FEmployeeTypeID ");
        sel.append(" left join CT_DOR_Dormitory dy on ops.CFDormitoryID=dy.fid ");
        sel.append(" left join CT_WAT_WaterPowerPricing wpp on wpp.CFEndDate>='" + startPeriodDateStr + "' ");
        sel.append(" and wpp.CFStartDate<='" + endPeriodDateStr + "' ");
        sel.append(" left join CT_MAN_WaterPowerMeterReading wpmr on wpmr.CFDormitoryID=ops.CFDormitoryID ");
        sel.append(" and wpmr.CFYears<=ops.CFCheckOutDate ");
        sel.append(" and DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,0,wpmr.CFYears)+1,0))>= ops.CFCheckInDate ");
        sel.append(" left join CT_WOE_WaterElectricity wey on wey.FSourceFunction=ops.fid and wey.CFPersonID=pp.FPERSONID ");
        sel.append(" and wey.CFStartDate='" + startPeriodDateStr + "' ");
        sel.append(" and wey.CFEndDate='" + endPeriodDateStr + "' ");
        sel.append(" where ");
        sel.append(" to_char(ops.CFCheckOutDate,'yyyy-MM-dd') >= '" + startPeriodDateStr + "' ");
        sel.append(" and to_char(ops.CFCheckInDate ,'yyyy-MM-dd') <='" + endPeriodDateStr + "' ");
        if (null != billids && (!billids.isEmpty())) {
            sel.append(" and wey.fid in('' ");
            for (String id : billids) {
                sel.append(",'");
                sel.append(id);
                sel.append("'");
            }
            sel.append(")");
        }
        System.out.println("getPersonWaterElectricitySql:" + sel);
        return sel;
    }
    
    
    
    
    
    
    
    
    
    
	/**
	 * 获取水电费详细Sql（SQL Server专用，逻辑已确认：房间向上追溯上级节点单价，水/电独立追溯）
	 * 核心逻辑：
	 * 1. 递归CTE遍历房间及所有上级节点（楼栋、小区等），保留起点房间ID关联
	 * 2. 独立筛选水/电单价：非null优先、层级越近优先
	 * 3. 优先级：树形节点单价 → 定价表单价
	 * @param startPeriodDateStr 开始日期（格式：yyyy-MM-dd）
	 * @param endPeriodDateStr 结束日期（格式：yyyy-MM-dd）
	 * @param billids 账单ID集合（可为null/空，非空时追加筛选条件）
	 * @return 拼接后的SQL字符串
	 */
    protected StringBuilder getPersonWaterElectricitySql(String dbType, String startPeriodDateStr, String endPeriodDateStr, Collection<String> billids) {
    
    	    StringBuilder sel = new StringBuilder();

    	    // 1. 递归CTE：追溯房间及所有上级节点（防自引用，避免死循环）
    	    sel.append("/*dialect*/ WITH DormPriceCTE AS (");
    	    // 锚点成员：所有节点作为起点（后续主查询关联房间，不影响逻辑）
    	    sel.append("    SELECT ");
    	    sel.append("        fid AS DormId,");
    	    sel.append("        fparentId,");
    	    sel.append("        CFWaterprice,");
    	    sel.append("        CFElectricityprice,");
    	    sel.append("        0 AS RecursionLevel");
    	    sel.append("    FROM CT_DOR_Dormitory");
    	    sel.append("    UNION ALL");
    	    // 递归成员：向上遍历上级节点，保留起点房间ID（核心逻辑）
    	    sel.append("    SELECT ");
    	    sel.append("        child.DormId AS DormId,");
    	    sel.append("        parent.fparentId,");
    	    sel.append("        parent.CFWaterprice,");
    	    sel.append("        parent.CFElectricityprice,");
    	    sel.append("        child.RecursionLevel + 1 AS RecursionLevel");
    	    sel.append("    FROM DormPriceCTE child");
    	    sel.append("    INNER JOIN CT_DOR_Dormitory parent ");
    	    sel.append("        ON child.fparentId = parent.fid ");
    	    sel.append("        AND parent.fid != child.DormId  ");
    	    sel.append("),");

    	    // 2. 独立筛选「水单价」：按起点房间ID分组，取最近有效水价（非null优先、层级近优先）
    	    sel.append("WaterLatestPrice AS (");
    	    sel.append("    SELECT ");
    	    sel.append("        DormId,");
    	    sel.append("        CFWaterprice AS LatestWaterPrice,");
    	    sel.append("        ROW_NUMBER() OVER (");
    	    sel.append("            PARTITION BY DormId");
    	    sel.append("            ORDER BY ");
    	    sel.append("                CASE WHEN CFWaterprice IS NOT NULL THEN 0 ELSE 1 END,");
    	    sel.append("                RecursionLevel ASC");
    	    sel.append("        ) AS WaterRowNum");
    	    sel.append("    FROM DormPriceCTE");
    	    sel.append("),");

    	    // 3. 独立筛选「电单价」：逻辑同水单价，独立判断电单价字段
    	    sel.append("ElecLatestPrice AS (");
    	    sel.append("    SELECT ");
    	    sel.append("        DormId,");
    	    sel.append("        CFElectricityprice AS LatestElecPrice,");
    	    sel.append("        ROW_NUMBER() OVER (");
    	    sel.append("            PARTITION BY DormId");
    	    sel.append("            ORDER BY ");
    	    sel.append("                CASE WHEN CFElectricityprice IS NOT NULL THEN 0 ELSE 1 END,");
    	    sel.append("                RecursionLevel ASC");
    	    sel.append("        ) AS ElecRowNum");
    	    sel.append("    FROM DormPriceCTE");
    	    sel.append(")");

    	    // 4. 主查询：关联各表，返回结果字段（优先级：树形单价 → 定价表单价）
    	    sel.append(" SELECT ");
    	    sel.append("    p.fid pid,");
    	    sel.append("    p.fname_l2 pName,");
    	    sel.append("    p.fnumber pNumber,");
    	    sel.append("    ops.fid opsid,");
    	    sel.append("    ops.CFCheckInDate,");
    	    sel.append("    ops.CFCheckOutDate,");
    	    sel.append("    ops.CFDormitoryID dormitoryID,");
    	    sel.append("    wpp.fid wppid,");
    	    sel.append("    wpp.CFStartDate,");
    	    sel.append("    wpp.CFEndDate,");
    	    sel.append("    COALESCE(wlp.LatestWaterPrice, wpp.CFWaterprice) AS CFWaterprice,");
    	    sel.append("    COALESCE(elp.LatestElecPrice, wpp.CFElectricityprice) AS CFElectricityprice,");
    	    sel.append("    wpmr.fid wpmrid,");
    	    sel.append("    wpmr.CFYears wpmrStartDate,");
    	    sel.append("    DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, wpmr.CFYears) + 1, 0)) AS wpmrEndDate,");
    	    sel.append("    ISNULL(wpmr.CFTotalWaterTons, 0) CFTotalWaterTons,");
    	    sel.append("    ISNULL(wpmr.CFTotalElecDegrees, 0) CFTotalElecDegrees,");
    	    sel.append("    ISNULL(wpmr.CFCurMonthWater, 0) CFCurMonthWater,");
    	    sel.append("    ISNULL(wpmr.CFCurMonthElecDegrees, 0) CFCurMonthElecDegrees,");
    	    sel.append("    wpmr.CFMeterReaPersonID,");
    	    sel.append("    pp.FPrimaryPositionID,");
    	    sel.append("    pp.FPersonDep,");
    	    sel.append("    CASE bt.finservice ");
    	    sel.append("        WHEN 1 THEN 'active' ");
    	    sel.append("        WHEN 4 THEN 'active' ");
    	    sel.append("        ELSE 'inactive' ");
    	    sel.append("    END AS InService");
    	    sel.append(" FROM CT_OCC_Occupants ops");
    	    sel.append(" LEFT JOIN T_HR_PersonPosition pp ON pp.fid = ops.CFPersonPositionID");
    	    sel.append(" LEFT JOIN t_bd_person p ON pp.FPERSONID = p.fid");
    	    sel.append(" LEFT JOIN T_HR_BDEmployeeType bt ON bt.fid = p.FEmployeeTypeID");
    	    sel.append(" LEFT JOIN CT_DOR_Dormitory dy ON ops.CFDormitoryID = dy.fid");
    	    sel.append(" LEFT JOIN WaterLatestPrice wlp ON dy.fid = wlp.DormId AND wlp.WaterRowNum = 1");
    	    sel.append(" LEFT JOIN ElecLatestPrice elp ON dy.fid = elp.DormId AND elp.ElecRowNum = 1");
    	    // 定价表关联：日期参数用传入的start/endPeriodDateStr，显式转换为date类型
    	    sel.append(" LEFT JOIN CT_WAT_WaterPowerPricing wpp ");
    	    sel.append("    ON wpp.CFStartDate <= CONVERT(date, '").append(startPeriodDateStr).append("')");
    	    sel.append("    AND wpp.CFEndDate >= CONVERT(date, '").append(endPeriodDateStr).append("')");
    	    // 抄表记录关联：按房间ID+日期范围匹配
    	    sel.append(" LEFT JOIN CT_MAN_WaterPowerMeterReading wpmr ");
    	    sel.append("    ON wpmr.CFDormitoryID = ops.CFDormitoryID");
    	    sel.append("    AND wpmr.CFYears <= ops.CFCheckOutDate");
    	    sel.append("    AND DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, wpmr.CFYears) + 1, 0)) >= ops.CFCheckInDate");
    	    // 水电账单关联：按占用ID+人员ID+日期范围匹配（日期参数用传入值）
    	    sel.append(" LEFT JOIN CT_WOE_WaterElectricity wey ");
    	    sel.append("    ON wey.FSourceFunction = ops.fid ");
    	    sel.append("    AND wey.CFPersonID = pp.FPERSONID");
    	    sel.append("    AND wey.CFStartDate = CONVERT(date, '").append(startPeriodDateStr).append("')");
    	    sel.append("    AND wey.CFEndDate = CONVERT(date, '").append(endPeriodDateStr).append("')");
    	    // 筛选条件：占用周期与查询周期重叠（SQL Server用CONVERT替代to_char）
    	    sel.append(" WHERE ");
    	    sel.append("    CONVERT(varchar(10), ops.CFCheckOutDate, 23) >= '").append(startPeriodDateStr).append("'");
    	    sel.append("    AND CONVERT(varchar(10), ops.CFCheckInDate, 23) <= '").append(endPeriodDateStr).append("'");

    	    // 账单ID筛选：若传入billids集合，追加IN条件（避免空集合报错）
    	    if (null != billids && (!billids.isEmpty())) {
    	        sel.append("    AND wey.fid IN ('') ");
    	        for (String id : billids) {
    	            sel.append(",'").append(id).append("'");
    	        }
    	        sel.append(")");
    	    }

    	    // 递归深度限制：10层足够覆盖日常树形（房间→楼栋→小区→...），避免异常
    	    sel.append(" OPTION (MAXRECURSION 10)");

    	    System.out.println("getPersonWaterElectricitySql:" + sel);
    	    return sel;
    	}

    
    
    
    
    
    
    
    
    
    
    

    /**
     * 获取水电费详细集合
     *
     * @param ctx
     * @param startPeriodDateStr
     * @param endPeriodDateStr
     * @return
     * @throws BOSException
     * @throws SQLException
     */
    protected List<Map<String, Object>> getPersonWaterElectricityList(Context ctx,
                                                                      String startPeriodDateStr, String endPeriodDateStr, Collection<String> billids)
            throws BOSException, SQLException, ShrWebBizException {

        StringBuilder sel = this.getPersonWaterElectricitySql("sqlserver",startPeriodDateStr, endPeriodDateStr, billids);
        IRowSet rs = DbUtil.executeQuery(ctx, sel.toString());
        List<Map<String, Object>> list = Lists.newArrayList();
        while (rs.next()) {
            Map<String, Object> rowMap = Maps.newHashMap();
            String pid = rs.getString("pid");
            String pName = rs.getString("pName");
            String pNumber = rs.getString("pNumber");
            String opsid = rs.getString("opsid");
            String InService = rs.getString("InService");
            Date checkInDate = rs.getDate("CFCheckInDate");//入住日期
            Date checkOutDate = rs.getDate("CFCheckOutDate");//离宿日期
            String dormitoryID = rs.getString("dormitoryID");//宿舍
            String wppid = rs.getString("wppid");//标准id
            Date startDate = rs.getDate("CFStartDate");//标准开始日期
            Date endDate = rs.getDate("CFEndDate");//标准结束日期
            BigDecimal waterprice = rs.getBigDecimal("CFWaterprice");//水费单价
            if (null==waterprice){
                throw new ShrWebBizException("没有找到水费电费标准单据，请在水电定价标准中维护！");
            }
            BigDecimal electricityprice = rs.getBigDecimal("CFElectricityprice");//电费单价
            String wpmrid = rs.getString("wpmrid");
            Date wpmrStartDate = rs.getDate("wpmrStartDate");
            Date wpmrEndDate = rs.getDate("wpmrEndDate");
            BigDecimal totalWaterTons = rs.getBigDecimal("CFTotalWaterTons");
            BigDecimal totalElecDegrees = rs.getBigDecimal("CFTotalElecDegrees");
            BigDecimal curMonthWater = rs.getBigDecimal("CFCurMonthWater");
            BigDecimal curMonthElecDegrees = rs.getBigDecimal("CFCurMonthElecDegrees");
            String FPrimaryPositionID = rs.getString("FPrimaryPositionID");
            String FPersonDep = rs.getString("FPersonDep");
            rowMap.put("pid", pid);
            rowMap.put("pName", pName);
            rowMap.put("pNumber", pNumber);
            rowMap.put("opsid", opsid);
            rowMap.put("InService", InService);
            rowMap.put("checkInDate", checkInDate);
            rowMap.put("checkOutDate", checkOutDate);
            rowMap.put("dormitoryID", dormitoryID);
            rowMap.put("wppid", wppid);
            rowMap.put("startDate", startDate);
            rowMap.put("endDate", endDate);
            rowMap.put("waterprice", waterprice);
            rowMap.put("electricityprice", electricityprice);
            rowMap.put("wpmrid", wpmrid);
            rowMap.put("wpmrStartDate", wpmrStartDate);
            rowMap.put("wpmrEndDate", wpmrEndDate);
            rowMap.put("totalWaterTons", totalWaterTons);
            rowMap.put("totalElecDegrees", totalElecDegrees);
            rowMap.put("curMonthWater", curMonthWater);
            rowMap.put("curMonthElecDegrees", curMonthElecDegrees);
            rowMap.put("primaryPositionID", FPrimaryPositionID);
            rowMap.put("personDep", FPersonDep);
            list.add(rowMap);
        }
        return list;
    }



    /**
     * 获取人员入住详情
     * @param we
     * @param periodDate
     * @param pid
     * @param dormitoryID
     * @return
     * @throws BOSException
     */
    protected WaterElectricityInfo getWaterElectricityInfo(IWaterElectricity we,
                                                           String periodDate, String pid, String dormitoryID
    ) throws BOSException {
        FilterInfo filter = new FilterInfo();
        filter.getFilterItems().add(new FilterItemInfo("yearMonth", periodDate, CompareType.EQUALS));
        filter.getFilterItems().add(new FilterItemInfo("person.id", pid, CompareType.EQUALS));
        filter.getFilterItems().add(new FilterItemInfo("dormitory.id", dormitoryID, CompareType.EQUALS));
        SelectorItemCollection selector = new SelectorItemCollection();
        selector.add(new SelectorItemInfo("*"));
        selector.add(new SelectorItemInfo("entrys.*"));
        selector.add(new SelectorItemInfo("person.*"));
        selector.add(new SelectorItemInfo("dormitory.*"));
        selector.add(new SelectorItemInfo("adminOrg.*"));
        selector.add(new SelectorItemInfo("position.*"));
        SorterItemCollection sorter = new SorterItemCollection();
        sorter.add(new SorterItemInfo("yearMonth"));
        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filter, selector, sorter);
        WaterElectricityCollection wec = we.getWaterElectricityCollection(viewInfo);
        WaterElectricityInfo waterElectricityInfo = null;
        if (null != wec && wec.size() > 0) {
            waterElectricityInfo = wec.get(0);
        }
        return waterElectricityInfo;
    }

    protected Map<String, Set<String>> createUpdateWE(Context ctx, List<Map<String, Object>> mapList, Map<String, Object> param,
                                                      Map<String, Map<String, Object>> occupantsMap, String createUpdate
    ) throws BOSException, ShrWebBizException, EASBizException {
        Map<String, Set<String>> resutMap = Maps.newHashMap();
        Set<String> alls = Sets.newHashSet();
        Set<String> sess = Sets.newHashSet();
        Set<String> errs = Sets.newHashSet();
        LocalDate startPeriodDate = (LocalDate) param.get("startPeriodDate");
        LocalDate endPeriodDate = (LocalDate) param.get("endPeriodDate");
        String startPeriodDateStr = (String) param.get("startPeriodDateStr");
        String endPeriodDateStr = (String) param.get("endPeriodDateStr");
        String periodDate = (String) param.get("periodDate");
        IWaterElectricity we = WaterElectricityFactory.getLocalInstance(ctx);
        for (Map<String, Object> map : mapList) {
            map.putAll(param);
            String pid = (String) map.get("pid");
            String pName = (String) map.get("pName");
            String pNumber = (String) map.get("pNumber");
            String opsid = (String) map.get("opsid");
            String InService = (String) map.get("InService");
            Date checkInDate = (Date) map.get("checkInDate");//入住日期
            Date checkOutDate = (Date) map.get("checkOutDate");//离宿日期
            String dormitoryID = (String) map.get("dormitoryID");//宿舍
            String wppid = (String) map.get("wppid");//标准id
            Date startDate = (Date) map.get("startDate");//标准开始日期
            Date endDate = (Date) map.get("endDate");//标准结束日期
            BigDecimal waterprice = (BigDecimal) map.get("waterprice");//水费单价
            BigDecimal electricityprice = (BigDecimal) map.get("electricityprice");//电费单价
            String wpmrid = (String) map.get("wpmrid");
            Date wpmrStartDate = (Date) map.get("wpmrStartDate");
            Date wpmrEndDate = (Date) map.get("wpmrEndDate");
            BigDecimal totalWaterTons = (BigDecimal) map.get("totalWaterTons");
            BigDecimal totalElecDegrees = (BigDecimal) map.get("totalElecDegrees");
            BigDecimal curMonthWater = (BigDecimal) map.get("curMonthWater");
            BigDecimal curMonthElecDegrees = (BigDecimal) map.get("curMonthElecDegrees");
            String primaryPositionID = (String) map.get("primaryPositionID");
            String personDep = (String) map.get("personDep");
            WaterElectricityInfo waterElectricityInfo = this.getWaterElectricityInfo(we, periodDate, pid, dormitoryID);
            if (null == waterElectricityInfo) {
                waterElectricityInfo = new WaterElectricityInfo();
            }
            waterElectricityInfo.setSourceFunction(opsid);
            //处理当月入住天数
            Map<String, Object> occupants = occupantsMap.get(dormitoryID);
            HROrgUnitInfo hrOrgUnitInfo = new HROrgUnitInfo();
            hrOrgUnitInfo.setId(BOSUuid.read("00000000-0000-0000-0000-000000000000CCE7AED4"));
            waterElectricityInfo.setHrOrgUnit(hrOrgUnitInfo);
            waterElectricityInfo.setYearMonth(periodDate);
            PersonInfo personInfo = new PersonInfo();
            personInfo.setId(BOSUuid.read(pid));
            waterElectricityInfo.setPerson(personInfo);
            waterElectricityInfo.setEmpName(pName);
            waterElectricityInfo.setEmpNumber(pNumber);
            waterElectricityInfo.setPositionStatus(InService);
            AdminOrgUnitInfo adminOrgUnitInfo = new AdminOrgUnitInfo();
            adminOrgUnitInfo.setId(BOSUuid.read(personDep));
            waterElectricityInfo.setAdminOrg(adminOrgUnitInfo);
            waterElectricityInfo.setBizDate(checkInDate);
            waterElectricityInfo.setLeaveDate(checkOutDate);
            DormitoryInfo dormitoryInfo = new DormitoryInfo();
            dormitoryInfo.setId(BOSUuid.read(dormitoryID));
            waterElectricityInfo.setDormitory(dormitoryInfo);

            this.calculateWaterElectricity(waterElectricityInfo, map, occupants);

            waterElectricityInfo.setMeterReading(wpmrid);
            waterElectricityInfo.setHydropowerStandards(wppid);
            PositionInfo positionInfo = new PositionInfo();
            positionInfo.setId(BOSUuid.read(primaryPositionID));
            waterElectricityInfo.setPosition(positionInfo);
            Instant instant1 = startPeriodDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
            // 获取时间戳（毫秒）
            long timestamp1 = instant1.toEpochMilli();
            waterElectricityInfo.setStartDate(new Date(timestamp1));
            Instant instant2 = endPeriodDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
            // 获取时间戳（毫秒）
            long timestamp2 = instant2.toEpochMilli();
            waterElectricityInfo.setEndDate(new Date(timestamp2));
            waterElectricityInfo.setApplyDate(checkInDate);
            PersonInfo applier = SHRBillUtil.getCurrPersonInfo();
            waterElectricityInfo.setApplier(applier);
            //水电单价
            waterElectricityInfo.setWaterprice(waterprice);
            waterElectricityInfo.setElectricityprice(electricityprice); 

            BOSUuid id = waterElectricityInfo.getId();
            if (null == id) {
                waterElectricityInfo.setStutas(WaterElectricityStutas.UnLock);
                waterElectricityInfo.setBillState(HRBillStateEnum.SAVED);
            }
            if ("update".equals(createUpdate)) {
                if (null != id && WaterElectricityStutas.UnLock.equals(waterElectricityInfo.getStutas())) {
                    IObjectPK pk = we.save(waterElectricityInfo);
                    sess.add(pk.toString());
                } else if (null != id) {
                    errs.add(id.toString());
                }
            } else {
                if (WaterElectricityStutas.UnLock.equals(waterElectricityInfo.getStutas())) {
                    IObjectPK pk = we.save(waterElectricityInfo);
                    sess.add(pk.toString());
                }
            }
        }
        
        resutMap.put("alls", alls);
        resutMap.put("errs", errs);
        resutMap.put("sess", sess);
        return resutMap;
    }

    /**
     * 生成水电费明细
     *
     * @param request
     * @param response
     * @param modelMap
     * @throws Exception
     */
    public void createMonthAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap, BatchMessageTipsHeader batchMessageTipsHeader) throws SHRWebException {
        Context ctx = SHRContext.getInstance().getContext();
        try {
            String billidStr = this.getBillId(request);
            Set<String> billids = Sets.newHashSet();
            if(!StringUtils.isEmpty(billidStr)) {
                billids.addAll(Arrays.asList(billidStr.split(",")));
            }
            String periodDate = (String) ParseRequestHelper.getParameterByRequest(request, "periodDate");
            LocalDate startPeriodDate = LocalDate.parse(periodDate + "-01", DateTimeFormatter.ISO_LOCAL_DATE);
            Month month = startPeriodDate.getMonth();
            LocalDate endPeriodDate = LocalDate.of(startPeriodDate.getYear(), month, month.length(startPeriodDate.isLeapYear()));
            //获取开始时间，结束时间
            String startPeriodDateStr = startPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
            String endPeriodDateStr = endPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
            Map<String, Object> param = Maps.newHashMap();
            param.put("periodDate", periodDate);
            param.put("startPeriodDate", startPeriodDate);
            param.put("endPeriodDate", endPeriodDate);
            param.put("startPeriodDateStr", startPeriodDateStr);
            param.put("endPeriodDateStr", endPeriodDateStr);

            //获取水电费详细集合
            List<Map<String, Object>> mapList = this.getPersonWaterElectricityList(ctx, startPeriodDateStr, endPeriodDateStr, billids);
            Set<String> dormitorySet = Sets.newHashSet();
            for (Map<String, Object> map : mapList) {
                String dormitoryID = (String) map.get("dormitoryID");//宿舍
                dormitorySet.add(dormitoryID);
            }
            //获取当前宿舍的总入住天数
            Map<String, Map<String, Object>> occupantsMap = this.getPersonOccupantsList(ctx, dormitorySet, startPeriodDate, endPeriodDate);
            Map<String, Set<String>> result = this.createUpdateWE(ctx, mapList, param, occupantsMap, "create");
            this.returnMessage(request, batchMessageTipsHeader, result,billids);
            //String SUCCESS_MESSAGE = SHRPerfWebResourceUtil.getRes(SHRPerfWebResource.OPERATESUCCESS, SHRContext.getInstance().getContext());
            //addBatchMessageSuccessTips((new HashSet<>(list)), SUCCESS_MESSAGE, batchMessageTipsHeader);
        } catch (BOSException | EASBizException | SQLException e) {
            e.printStackTrace();
        }
        
    }
    /**
     * 计算
     {"startDate":
     {"values":{"date":"2025-04-01"},"isSaveToScheme":true,"dataType":"Date","queryDateType":""},
     "applyDate":
     {"values":"","isSaveToScheme":true,"dataType":"Date","dataItem":"","queryDateType":""}}
     *
     * @param request
     * @param response
     * @param modelMap
     * @return
     * @throws SHRWebException
     */
    public void calculateAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap, BatchMessageTipsHeader batchMessageTipsHeader) throws SHRWebException {
        Context ctx = SHRContext.getInstance().getContext();
        try {
            String billId = this.getBillId(request);
            String billidStr = this.getBillId(request);
            Set<String> billids = Sets.newHashSet();
            if (!StringUtils.isEmpty(billidStr)) {
                billids.addAll(Arrays.asList(billidStr.split(",")));
            }
            String fastFilterItems = (String) ParseRequestHelper.getParameterByRequest(request, "fastFilterItems");
            logger.error(fastFilterItems);
            Map fastFilterItemsMap = JSONUtils.convertJsonToObject(SHRContext.getInstance().getContext(), fastFilterItems);
            Map<String, Object> bizDateMap = (Map<String, Object>) fastFilterItemsMap.get("startDate");
            if (null != bizDateMap.get("values")
                    && (!String.class.equals(bizDateMap.get("values").getClass())
                    || !StringUtils.isEmpty(String.valueOf(bizDateMap.get("values"))))) {
                Map<String, Object> subMap = (Map<String, Object>) bizDateMap.get("values");
                String periodDate = (String) subMap.get("date");
                LocalDate startPeriodDate = LocalDate.parse(periodDate, DateTimeFormatter.ISO_LOCAL_DATE);
                periodDate = periodDate.substring(0, 7);
                Month month = startPeriodDate.getMonth();
                LocalDate endPeriodDate = LocalDate.of(startPeriodDate.getYear(), month, month.length(startPeriodDate.isLeapYear()));
                //获取开始时间，结束时间
                String startPeriodDateStr = startPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
                String endPeriodDateStr = endPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
                Map<String, Object> param = Maps.newHashMap();
                param.put("periodDate", periodDate);
                param.put("startPeriodDate", startPeriodDate);
                param.put("endPeriodDate", endPeriodDate);
                param.put("startPeriodDateStr", startPeriodDateStr);
                param.put("endPeriodDateStr", endPeriodDateStr);

                //获取水电费详细集合
                List<Map<String, Object>> mapList = this.getPersonWaterElectricityList(ctx, startPeriodDateStr, endPeriodDateStr, billids);
                Set<String> dormitorySet = Sets.newHashSet();
                for (Map<String, Object> map : mapList) {
                    String dormitoryID = (String) map.get("dormitoryID");//宿舍
                    dormitorySet.add(dormitoryID);
                }
                //获取当前宿舍的总入住天数
                Map<String, Map<String, Object>> occupantsMap = this.getPersonOccupantsList(ctx, dormitorySet, startPeriodDate, endPeriodDate);
                Map<String, Set<String>> result = this.createUpdateWE(ctx, mapList, param, occupantsMap, "update");
                this.returnMessage(request, batchMessageTipsHeader, result, billids);
            }

        } catch (BOSException e) {
            e.printStackTrace();
            throw new ShrWebBizException(e);
        } catch (EASBizException e) {
            e.printStackTrace();
            throw new ShrWebBizException(e);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new ShrWebBizException(e);
        }
    }
        @Override
    public String getTableName() {
        return TABLENAME;
    }
    /**
     * 锁定
     *
     * @param request
     * @param response
     * @param modelMap
     * @return
     * @throws SHRWebException
     */
    public String enableAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException {
        String billId = this.getBillId(request);
        Context ctx = SHRContext.getInstance().getContext();
        enable(ctx,billId);
        return null;
    }
    public static String enable(Context ctx ,String billId) {
        if(null!=billId) {
            String[] ids = billId.split(",");
            for (String id : ids) {
                try {
                    updateBillState(ctx, "enable", id);
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
        return billId;
    }
    /**
     * 解锁
     *
     * @param request
     * @param response
     * @param modelMap
     * @return
     * @throws SHRWebException
     */
    public String disableAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException {
        String billId = this.getBillId(request);
        Context ctx = SHRContext.getInstance().getContext();
        disable(ctx,billId);
        return null;
    }
    public static String disable(Context ctx ,String billId) {
        if(null!=billId) {
            String[] ids = billId.split(",");

            for (String id : ids) {
                try {
                    updateBillState(ctx, "disable", id);
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
        return billId;
    }
    public static void updateBillState(Context ctx, String math, String uuid) throws SQLException {
        Connection conn = null;
        Statement state = null;

        try {
            conn = EJBFactory.getQueryConnection(ctx);
            state = conn.createStatement();
            if ("enable".equals(math)) {

                //薪酬锁定
                state.execute("update "+TABLENAME+" set FBillState='2' where fid='" + uuid + "' and FBillState < 2 ");

            } else if ("disable".equals(math)) {
                //薪酬解锁
                state.execute("update "+TABLENAME+" set FBillState='0' where fid='" + uuid + "' and FBillState < 3 ");
            }
        } catch (SQLException var32) {
            var32.printStackTrace();
        } finally {
            if (state != null) {
                try {
                    state.close();
                } finally {
                    if (conn != null) {
                        conn.close();
                    }
                }
            }
        }
    }

}
