package com.kingdee.eas.custom.perfweb.handler;
import com.alibaba.fastjson.JSONObject;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.ctrl.swing.StringUtils;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.eas.custom.perfweb.util.ReportDateUtil;
import com.kingdee.eas.custom.perfweb.util.ReportFilterUtil;
import com.kingdee.eas.custom.perfweb.util.ReportOrgUtil;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.shr.base.syssetting.context.SHRContext;
import com.kingdee.shr.base.syssetting.exception.ShrWebBizException;
import com.kingdee.shr.base.syssetting.json.GridDataEntity;
import com.kingdee.shr.base.syssetting.web.handler.ListHandler;
import org.apache.log4j.Logger;
import org.springframework.ui.ModelMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 类名称: IndirectPersonnelOvertimeReportHandler
* 功能描述: 间接人员加班工时报表(打卡计算平时/周末加班工时)
* 创建日期: 2026-06-23
* 作 者: 青梧
* 版 本: 1.0
*
* 返回字段说明:
* month - 月份(合计行显示合计)
* personNumber - 员工工号
* centerName - 所属中心名称(沿FParentID向上找,FLevel=2,列表列名沿用centerName)
* deptName - 所属部门名称
* personName - 员工姓名
* weekdayOtHours - 平时加班工时(最晚打卡-排班下班,0.5h取整)
* weekendOtHours - 周末加班工时(最晚-最早,0.5h取整)
* totalOtHours - 加班工时合计
* _sortDept - 内部排序字段(部门)
* _sortName - 内部排序字段(姓名)
*
* 核心数据结构说明:
* personMap : Map 间接人员基础信息
* punchMap : Map>> 当月全员打卡,按人+日分组
* offDutyMap : Map> 当月全员排班下班时间
* dayKey : 日期字符串 yyyy-MM-dd,作为按天计算的键
*/
public class IndirectPersonnelOvertimeReportHandler extends ListHandler {
private static Logger logger = Logger.getLogger(IndirectPersonnelOvertimeReportHandler.class);
Context ctx = SHRContext.getInstance().getContext();
/**
* 间接人员类别:person.CFRylb=2
*/
private static final int INDIRECT_RYLB = 2;
/**
* 周末最早打卡早于13:15时扣除的午休时长(小时)
*/
private static final double LUNCH_DEDUCT_HOURS = 1.5D;
/**
* 午休扣除阈值:13:15(分钟数)
*/
private static final int AFTERNOON_THRESHOLD_MINUTES = 13 * 60 + 15;
/**
* 中心组织层级(T_ORG_Admin.FLevel)。
* TODO(待业务确认): 当前按2级作为中心,若组织架构调整需同步校验。
*/
private static final int CENTER_ORG_LEVEL = 2;
/**
* 列表查询入口:按日期范围/组织/人员筛选间接人员,计算加班工时并追加合计行。
*/
@Override
protected GridDataEntity getGridRequestData(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws ShrWebBizException {
logger.error("IndirectPersonnelOvertimeReportHandler getGridRequestData------------");
GridDataEntity gridDataEntity = new GridDataEntity();
try {
// 快筛: 行政组织adminOrg + 人员person + 日期month
String filterItem = ReportFilterUtil.getFilterItems(request);
JSONObject fastFilterItemsJson = ReportFilterUtil.parseFastFilterJson(request);
logger.error("filterItem: " + filterItem);
logger.error("fastFilterItemsJson: " + fastFilterItemsJson);
Map paramMap = ReportFilterUtil.parseAdminOrgParams(fastFilterItemsJson, logger);
String adminOrg = paramMap.get("adminOrg");
List personIds = ReportFilterUtil.parseF7IdList(fastFilterItemsJson, "person");
// dateRange: 开始/结束日期,优先快筛字段(name=month),未传则默认当月
ReportFilterUtil.DateRange dateRange = ReportFilterUtil.resolveQueryDateRange(filterItem, fastFilterItemsJson, "month", logger);
logger.error("查询日期: " + dateRange.getStartDate() + " ~ " + dateRange.getEndDate() + ", 组织: " + adminOrg + ", 人员: " + personIds);
// personMap: key=人员FID, value=人员基础信息(工号/姓名/部门/中心)
Map personMap = loadIndirectPersons(adminOrg, personIds);
// dataList: 最终返回给前端的报表行列表
List