# ServiceRequestCenterServiceImpl.java

    package cloud.wconnect.it.service.servicerequestcenter.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.pojo.dto.*;
    import cloud.wconnect.commonlib.pojo.query.UserQuery;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.InternationalizationUtils;
    import cloud.wconnect.commonlib.util.PaginationUtil;
    import cloud.wconnect.it.cons.servicerequestcenter.*;
    import cloud.wconnect.it.entity.servicerequestcenter.ServiceRequestCenter;
    import cloud.wconnect.it.entity.servicerequestcenter.ServiceRequestCenterComment;
    import cloud.wconnect.it.mapper.servicerequestcenter.ServiceRequestCenterMapper;
    import cloud.wconnect.it.pojo.dto.servicerequestcenter.AllocateToOneSelfDTO;
    import cloud.wconnect.it.pojo.dto.servicerequestcenter.ServiceRequestCenterDTO;
    import cloud.wconnect.it.pojo.dto.servicerequestcenter.ServiceRequestCenterStatisticsDTO;
    import cloud.wconnect.it.pojo.dto.servicerequestcenter.StatisticsCurrentDepartmentDTO;
    import cloud.wconnect.it.pojo.query.servicerequestcenter.*;
    import cloud.wconnect.it.service.servicerequestcenter.IServiceRequestCenterCommentService;
    import cloud.wconnect.it.service.servicerequestcenter.IServiceRequestCenterPropertyService;
    import cloud.wconnect.it.service.servicerequestcenter.IServiceRequestCenterService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.google.common.collect.Lists;
    import com.google.common.collect.Maps;
    import com.google.common.collect.Sets;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.stereotype.Service;

    import java.math.BigDecimal;
    import java.math.RoundingMode;
    import java.time.ZonedDateTime;
    import java.util.*;
    import java.util.stream.Collectors;

    /**
     * <p>
     *  服务实现类
     * </p>
     *
     * @author yyt
     * @since 2025-12-16
     */
    @Service
    @DS("it_manage")
    public class ServiceRequestCenterServiceImpl extends ServiceImpl<ServiceRequestCenterMapper, ServiceRequestCenter> implements IServiceRequestCenterService {

        @Autowired
        private BeanMapper beanMapper;
        @Lazy
        @Autowired
        private IServiceRequestCenterCommentService serviceRequestCenterCommentService;
        @Autowired
        private IServiceRequestCenterPropertyService serviceRequestCenterPropertyService;
        @Autowired
        private UserInternalService userInternalService;

        @Value("${default.timezone}")
        private String defaultTimeZone;

        /**
         * my request 列表
         *
         * @param tenantId    租户id
         * @param propertyIds 资产id
         * @param query       查询条件
         * @param userId      操作人
         * @return my request 列表
         * @author yyt
         * @date 2025/12/17
         */
        @Override
        public ListPagedDTO<ServiceRequestCenterDTO> myRequest(int tenantId, List<Integer> propertyIds, ServiceRequestCenterQuery query, int userId) {
            formatQueryParam(query);
            Page<ServiceRequestCenter> page;
            Integer pageNumber = query.getPage();
            Integer size = query.getSize();
            // 创建人设置自己
            query.setCreatorList(Lists.newArrayList(userId));
            // 当未指定类型时，查询所有类型的单据
            String type = query.getType();
            if (StringUtils.isEmpty(type)) {
                query.setPropertyIdList(propertyIds);
                page = baseMapper.pageMyRequest(new Page<>(pageNumber, size), tenantId, query);
            } else {
                // 查询指定类型
                List<Integer> typeList = query.getTypeList();
                if (typeList.contains(ServiceRequestCenterTypeEnum.ACCOUNT.getCode())
                        && (typeList.contains(ServiceRequestCenterTypeEnum.IT.getCode()) || typeList.contains(ServiceRequestCenterTypeEnum.PRODUCT.getCode()))) {
                    typeList = typeList.stream().filter(item -> item != ServiceRequestCenterTypeEnum.ACCOUNT.getCode()).toList();
                    query.setTypeList(typeList);
                    query.setPropertyIdList(propertyIds);
                    page = baseMapper.pageMyRequest(new Page<>(pageNumber, size), tenantId, query);
                } else {
                    // 如果只查询财务
                    if (typeList.contains(ServiceRequestCenterTypeEnum.ACCOUNT.getCode())) {
                        page = baseMapper.pageMyRequestForAccount(new Page<>(pageNumber, size), tenantId, query);
                    } else {
                        // 如果只查询产品、it
                        page = baseMapper.pageMyRequestForItAndProduct(new Page<>(pageNumber, size), tenantId, propertyIds, query);
                    }
                }
            }

            return packageListPagedDTO(tenantId, page);
        }

        /**
         * 格式化查询参数
         *
         * @param query 查询条件
         * @author yyt
         * @date 2026/4/2
         **/
        private void formatQueryParam(ServiceRequestCenterQuery query) {
            String propertyIds = query.getPropertyIds();
            if (StringUtils.isNotEmpty(propertyIds)) {
                query.setPropertyIdList(Arrays.stream(propertyIds.split(",")).map(Integer::parseInt).collect(Collectors.toList()));
            }
            String status = query.getStatus();
            if (StringUtils.isNotEmpty(status)) {
                query.setStatusList(Arrays.stream(status.split(",")).map(Integer::parseInt).collect(Collectors.toList()));
            }
            String type = query.getType();
            if (StringUtils.isNotEmpty(type)) {
                query.setTypeList(Arrays.stream(type.split(",")).map(Integer::parseInt).collect(Collectors.toList()));
            }
            String creator = query.getCreator();
            if(StringUtils.isNotEmpty(creator)){
                query.setCreatorList(Arrays.stream(creator.split(",")).map(Integer::parseInt).collect(Collectors.toList()));
            }
            String priority = query.getPriority();
            if (StringUtils.isNotEmpty(priority)) {
                query.setPriorityList(Arrays.stream(priority.split(",")).map(Integer::parseInt).collect(Collectors.toList()));
            }
        }

        /**
         * 统计资产下，分配给指定用户的 request 数量
         *
         * @param tenantId    租户id
         * @param propertyIds 资产id
         * @param userId      用户id
         * @return 统计结果
         * @author yyt
         * @date 2025/12/17
         */
        @Override
        public AllocateToOneSelfDTO countAllocateToOneSelf(int tenantId, List<Integer> propertyIds, int userId) {
            // 根据用户所属部门，统计当前部门下的 request
            Integer departmentType = getUserDepartmentType(tenantId, userId);
            List<ServiceRequestCenter> requestList = list(tenantId, propertyIds, departmentType, userId);

            List<Integer> completedStatus = Arrays.asList(ServiceRequestCenterStatusEnum.RESOLVED.getCode(), ServiceRequestCenterStatusEnum.CLOSED.getCode());
            Map<Boolean, Integer> countByIsCompleted = requestList.stream().collect(Collectors.partitioningBy(item -> completedStatus.contains(item.getStatus()),
                    Collectors.collectingAndThen(Collectors.toList(), List::size)));

            return new AllocateToOneSelfDTO(countByIsCompleted.getOrDefault(false, BaseConstant.ZERO),
                    countByIsCompleted.getOrDefault(true, BaseConstant.ZERO));
        }

        /**
         * 查询指定条件的 request
         *
         * @param tenantId    租户 id
         * @param propertyIds 资产id
         * @param type        1.account 2.it 3.product
         * @param userId      用户id
         * @return request list
         * @author yyt
         * @date 2025/12/17
         */
        private List<ServiceRequestCenter> list(int tenantId, List<Integer> propertyIds, Integer type, int userId) {
            // 财务类型：查询当前租户，责任人是自己的单据
            if (type == ServiceRequestCenterTypeEnum.ACCOUNT.getCode()) {
                return list(new QueryWrapper<ServiceRequestCenter>().lambda()
                        .in(ServiceRequestCenter::getTenantId, tenantId)
                        .eq(ServiceRequestCenter::getType, type)
                        .eq(ServiceRequestCenter::getDutyUser, userId));
            } else {
                //非财务类型：查询当前租户，当前登陆用户有权限的资产，责任人是自己的单据
                return baseMapper.listForAssignToMe(tenantId, propertyIds, type, userId);
            }
        }

        /**
         * 查询指定条件的 request
         *
         * @param tenantId 租户 id
         * @param userIds  用户id
         * @return request list
         * @author yyt
         * @date 2025/12/17
         */
        private List<ServiceRequestCenter> list(int tenantId, List<Integer> userIds) {
            return list(new QueryWrapper<ServiceRequestCenter>().lambda()
                    .in(ServiceRequestCenter::getTenantId, tenantId)
                    .eq(ServiceRequestCenter::getType, ServiceRequestCenterTypeEnum.ACCOUNT.getCode())
                    .in(ServiceRequestCenter::getDutyUser, userIds));
        }

        /**
         * 获取用户部门类型
         *
         * @param tenantId 租户id
         * @param userId   用户id
         * @return 部门类型
         * @author yyt
         * @date 2025/12/17
         */
        private Integer getUserDepartmentType(int tenantId, int userId) {
            UserDTO user = userInternalService.getOne(tenantId, userId);
            ServiceRequestCenterDepartmentEnum department = ServiceRequestCenterDepartmentEnum.getDepartment(user.getDepartment());
            return department.getCode();
        }

        /**
         * 获取用户部门
         *
         * @param tenantId 租户id
         * @param userId   用户id
         * @return 部门类型
         * @author yyt
         * @date 2025/12/17
         */
        private ServiceRequestCenterDepartmentEnum getUserDepartment(int tenantId, int userId) {
            UserDTO user = userInternalService.getOne(tenantId, userId);
            return ServiceRequestCenterDepartmentEnum.getDepartment(user.getDepartment());
        }

        /**
         * 获取分配给自己的 request 列表（其中管理员额外获取待分配的 request）
         *
         * @param tenantId    租户id
         * @param propertyIds 资产id
         * @param userId      操作人
         * @param query       查询条件
         * @param identity    身份（1.员工，2.管理员）
         * @return request 列表
         * @author yyt
         * @date 2025/12/18
         **/
        @Override
        public ListPagedDTO<ServiceRequestCenterDTO> allocateToOneSelf(int tenantId, List<Integer> propertyIds, int userId, AllocateToOneSelfQuery query, int identity) {
            // 获取用户所属部门
            Integer departmentType = getUserDepartmentType(tenantId, userId);

            Integer pageNum = query.getPage();
            Integer size = query.getSize();
            Page<ServiceRequestCenter> page;
            List<Integer> status = query.getStatus();
            // 财务类型：查询当前租户，责任人是自己的单据（若登陆用户是管理员，则额外查询待分配的单据）
            if (departmentType == ServiceRequestCenterTypeEnum.ACCOUNT.getCode()) {
                LambdaQueryWrapper<ServiceRequestCenter> queryWrapper = new QueryWrapper<ServiceRequestCenter>().lambda()
                        .eq(ServiceRequestCenter::getTenantId, tenantId)
                        .eq(ServiceRequestCenter::getType, departmentType)
                        .in(ServiceRequestCenter::getStatus, status);

                // 若是管理员，且 status 查询的是待处理，则额外查询待分配的 request + 分配给自己的 request
                if (identity == ServiceRequestCenterIdentityCons.MANAGER && status.contains(ServiceRequestCenterStatusEnum.OPEN.getCode())) {
                    queryWrapper.nested(queryWrapper1 ->
                            queryWrapper1.eq(ServiceRequestCenter::getDutyUser, BaseConstant.ZERO)
                                    .or()
                                    .eq(ServiceRequestCenter::getDutyUser, userId));
                } else {
                    // 否则，只查询分配给自己的 request
                    queryWrapper.eq(ServiceRequestCenter::getDutyUser, userId);
                }
                queryWrapper.orderByAsc(ServiceRequestCenter::getStatus)
                        .orderByDesc(ServiceRequestCenter::getId);
                page = page(new Page<>(pageNum, size), queryWrapper);
            } else {
                //非财务类型：查询当前租户，当前登陆用户有权限的资产，责任是自己的单据（若登陆用户是管理员，则额外查询待分配的单据
                page = baseMapper.pageForAssignToMe(new Page<>(pageNum, size), tenantId, propertyIds, departmentType, status, userId, identity);
            }
            return packageListPagedDTO(tenantId, page);
        }

        /**
         * 查询当日最大 service number
         *
         * @param tenantId 租户 id
         * @param date     日期
         * @return service number
         * @author yyt
         * @date 2025/12/16
         */
        @Override
        public String selectMaxServiceNumber(int tenantId, String date) {
            return baseMapper.selectMaxServiceNumber(tenantId, date);
        }

        /**
         * 查询可分配的人员列表
         *
         * @param tenantId    租户 id
         * @param userId      操作人
         * @param query       查询条件
         * @param request     request
         * @return 可分配的人员列表
         * @author yyt
         * @date 2025/12/18
         **/
        @Override
        public ListPagedDTO<UserBasicInfoDTO> assignablePersonnel(int tenantId, int userId, AssignablePersonnelQuery query, ServiceRequestCenter request) {
            // 查询当前部门下未离职的 员工 + 管理员
            // request 有责任人时，返回用户中需要排除掉责任人，没有责任人时，全部返回
            List<UserDTO> users = listCurrentDepartmentUser(tenantId, request.getType(), serviceRequestCenterPropertyService.listPropertyIds(request.getId()),
                    request.getDutyUser() == BaseConstant.ZERO ? null : request.getDutyUser());
            if (CollectionUtils.isEmpty(users)) {
                return new ListPagedDTO<>();
            }

            List<UserDTO> pageUsers = PaginationUtil.getPage(users, query.getPage(), query.getSize());
            return new ListPagedDTO<>(users.size(), beanMapper.mapList(pageUsers, UserBasicInfoDTO.class));
        }

        /**
         * 获取当前部门下的员工+管理员
         *
         * @param tenantId      租户 id
         * @param type          类型
         * @param propertyIds   指定资产
         * @param excludeUserId 需要排除的用户
         * @return 当前部门下的员工+管理员
         * @author yyt
         * @date 2025/12/19
         **/
        private List<UserDTO> listCurrentDepartmentUser(int tenantId, int type, List<Integer> propertyIds, Integer excludeUserId) {
            // 财务类型：查询当前租户下，财务部门下的员工+管理员
            // 非财务类型：查询当前租户下，当前 request 绑定资产，当前部门下的员工+管理员
            UserQuery userQuery = new UserQuery();
            userQuery.setTenantId(tenantId);
            if (type != ServiceRequestCenterTypeEnum.ACCOUNT.getCode()) {
                userQuery.setPropertyIds(propertyIds);
            }

            Map<String, List<String>> positionsByDepartment = Maps.newHashMap();
            List<ServiceRequestCenterDepartmentEnum> departments = ServiceRequestCenterDepartmentEnum.listDepartments(type);
            for (ServiceRequestCenterDepartmentEnum departmentEnum : departments) {
                List<String> allPositions = Lists.newArrayList(departmentEnum.getManagerPositions());
                allPositions.addAll(departmentEnum.getStaffPositions());
                positionsByDepartment.put(departmentEnum.getDepartment(), allPositions);
            }
            userQuery.setPositionsByDepartment(positionsByDepartment);

            List<UserDTO> users = userInternalService.getUsers(userQuery);
            if (CollectionUtils.isEmpty(users)) {
                return Collections.emptyList();
            }

            // 过来掉需要排除的用户
            if (excludeUserId != null) {
                users = users.stream().filter(user -> !user.getId().equals(excludeUserId)).toList();
            }

            // 排除掉离职的，并排序（id 倒序），然后手动分页返回数据
            return users.stream().filter(UserDTO::getStatus).sorted(Comparator.comparing(UserDTO::getId).reversed()).toList();
        }

        /**
         * all request 列表
         *
         * @param tenantId    租户 id
         * @param propertyIds 登陆用户有权限的资产 id
         * @param query       查询条件
         * @param userId      登录人
         * @return all request 列表
         * @author yyt
         * @date 2025/12/18
         **/
        @Override
        public ListPagedDTO<ServiceRequestCenterDTO> allRequest(int tenantId, List<Integer> propertyIds, ServiceRequestCenterQuery query, int userId) {
            formatQueryParam(query);

            // 当选择资产，同时也选择财务类型，则不查询数据，因为财务不属于任何资产，只有非财务类型才属于资产
            List<Integer> propertyIdList = query.getPropertyIdList();
            List<Integer> typeList = query.getTypeList();
            if (CollectionUtils.isNotEmpty(propertyIdList) && CollectionUtils.isNotEmpty(typeList) && typeList.contains(ServiceRequestCenterTypeEnum.ACCOUNT.getCode())) {
                return new ListPagedDTO<>();
            }

            Page<ServiceRequestCenter> page;
            Integer pageNumber = query.getPage();
            Integer size = query.getSize();

            // 未选择资产、类型，查询所有单据
            if(CollectionUtils.isEmpty(propertyIdList) && CollectionUtils.isEmpty(typeList)){
                // 查询有权限的资产
                query.setPropertyIdList(propertyIds);
                page = baseMapper.pageAllRequest(new Page<>(pageNumber, size), tenantId, query);
            } else {
                if(CollectionUtils.isNotEmpty(propertyIdList) && CollectionUtils.isNotEmpty(typeList)){
                    // 都选择，此时只查询非财务类型的单据（因为上面已经判断了，此时不会有财务类型）
                    page = baseMapper.pageAllRequestForItAndProduct(new Page<>(pageNumber, size), tenantId, query);
                } else {
                    // 只查询资产
                    if(CollectionUtils.isNotEmpty(propertyIdList)){
                        page = baseMapper.pageAllRequestForItAndProduct(new Page<>(pageNumber, size), tenantId, query);
                    } else {
                        // 查询有权限的资产
                        query.setPropertyIdList(propertyIds);
                        // 财务和非财务都查询
                        if(typeList.contains(ServiceRequestCenterTypeEnum.ACCOUNT.getCode()) &&
                                (typeList.contains(ServiceRequestCenterTypeEnum.IT.getCode())  || typeList.contains(ServiceRequestCenterTypeEnum.PRODUCT.getCode()))){
                            typeList = typeList.stream().filter(type -> type != ServiceRequestCenterTypeEnum.ACCOUNT.getCode()).toList();
                            query.setTypeList(typeList);
                            page = baseMapper.pageAllRequest(new Page<>(pageNumber, size), tenantId, query);
                        } else {
                            // 只查财务类型
                            if(typeList.contains(ServiceRequestCenterTypeEnum.ACCOUNT.getCode())){
                                page = baseMapper.pageAllRequestForAccount(new Page<>(pageNumber, size), tenantId, query);
                            } else {
                                // 只查询非财务类型
                                page = baseMapper.pageAllRequestForItAndProduct(new Page<>(pageNumber, size), tenantId, query);
                            }
                        }
                    }
                }
            }

            return packageListPagedDTO(tenantId, page);
        }

        /**
         * 封装 request 列表
         *
         * @param tenantId 租户 id
         * @param page     分页数据
         * @return request 列表
         * @author yyt
         * @date 2025/12/18
         **/
        private ListPagedDTO<ServiceRequestCenterDTO> packageListPagedDTO(int tenantId, Page<ServiceRequestCenter> page) {
            List<ServiceRequestCenter> requests = page.getRecords();
            if (CollectionUtils.isEmpty(requests)) {
                return new ListPagedDTO<>();
            }

            Map<Integer, Integer> commentCountByRequestId = serviceRequestCenterCommentService.listByRequestIds(requests.stream().map(ServiceRequestCenter::getId).toList())
                    .stream().collect(Collectors.groupingBy(ServiceRequestCenterComment::getRequestId,
                            Collectors.collectingAndThen(Collectors.toList(), List::size)));
            Set<Integer> userIds = Sets.newHashSetWithExpectedSize(requests.size());
            for (ServiceRequestCenter request : requests) {
                userIds.add(request.getCreatedBy());
                if (request.getDutyUser() > BaseConstant.ZERO) {
                    userIds.add(request.getDutyUser());
                }
            }
            Map<Integer, UserDTO> userByUserId = userInternalService.getUserMapByIds(tenantId, userIds);

            return new ListPagedDTO<>(page.getTotal(), beanMapper.mapList(requests, ServiceRequestCenterDTO.class,
                    (request, requestDTO) -> {
                        requestDTO.setCommentCount(commentCountByRequestId.getOrDefault(request.getId(), BaseConstant.ZERO));
                        requestDTO.setCreatedName(userByUserId.getOrDefault(request.getCreatedBy(), new UserDTO()).getName());

                        UserDTO dutyUser = userByUserId.getOrDefault(request.getDutyUser(), new UserDTO());
                        requestDTO.setDutyUserName(dutyUser.getName());
                        requestDTO.setDutyUserPosition(dutyUser.getPosition());
                    }));
        }

        /**
         * 获取创建人列表
         *
         * @param tenantId    租户 id
         * @param propertyIds 资产 id
         * @param query       查询条件
         * @return 创建人列表
         * @author yyt
         * @date 2025/12/18
         **/
        @Override
        public ListPagedDTO<UserNameDTO> listCreator(int tenantId, List<Integer> propertyIds, ListCreatorQuery query) {
            // 查询多资产下 request 创建人列表
            Page<ServiceRequestCenter> page = baseMapper.pageCreator(new Page<>(query.getPage(), query.getSize()), tenantId, query);
            List<ServiceRequestCenter> requests = page.getRecords();
            if (CollectionUtils.isEmpty(requests)) return new ListPagedDTO<>();

            Set<Integer> userIds = requests.stream().map(ServiceRequestCenter::getCreatedBy).collect(Collectors.toSet());
            Map<Integer, String> userNameByUserId = userInternalService.getNameMapByIds(tenantId, userIds);

            return new ListPagedDTO<>(page.getTotal(), beanMapper.mapList(userIds, UserNameDTO.class,
                    (userId, userNameDTO) -> {
                        userNameDTO.setId(userId);
                        userNameDTO.setName(userNameByUserId.get(userId));
                    }
            ));
        }

        /**
         * statistics 信息
         *
         * @param tenantId    租户 id
         * @param propertyIds 登陆用户有权限的资产 id
         * @param userId      操作人
         * @param query       查询条件
         * @return statistics 信息
         * @author yyt
         * @date 2025/12/18
         **/
        @Override
        public ServiceRequestCenterStatisticsDTO statistics(int tenantId, List<Integer> propertyIds, int userId, ServiceRequestCenterStatisticsQuery query) {
            Integer type = getUserDepartmentType(tenantId, userId);
            Integer dateInteger = null;
            String dateStr = query.getDate();
            if (StringUtils.isNotBlank(dateStr)) {
                dateInteger = Integer.parseInt(dateStr);
            }

            // 登陆用户是财务部门：查询当前租户下，财务部门下的单据
            List<ServiceRequestCenter> requests;
            if (type == ServiceRequestCenterTypeEnum.ACCOUNT.getCode()) {
                requests = list(new QueryWrapper<ServiceRequestCenter>().lambda()
                        .eq(ServiceRequestCenter::getTenantId, tenantId)
                        .eq(ServiceRequestCenter::getType, type)
                        .le(Objects.nonNull(dateInteger), ServiceRequestCenter::getCreatedDate, dateInteger));
            } else {
                // 登陆用户非财务部门（产品/it）：当前租户下，当前登录用户拥有权限的资产下，当前部门下的单据
                // 未指定资产时查询有权限的所有资产
                if(CollectionUtils.isEmpty(query.getPropertyIdList())){
                    query.setPropertyIdList(propertyIds);
                }
                requests = baseMapper.listForStatistics(tenantId, type, query.getPropertyIdList(), dateInteger, null);
            }

            if (CollectionUtils.isEmpty(requests)) {
                return new ServiceRequestCenterStatisticsDTO();
            }

            int openCount = 0;
            int inProgressCount = 0;
            int resolvedCount = 0;
            int completedCount = 0;
            int lowCount = 0;
            int mediumCount = 0;
            int highCount = 0;
            int urgentCount = 0;
            List<Integer> completedStatusList =  Lists.newArrayList(ServiceRequestCenterStatusEnum.RESOLVED.getCode(), ServiceRequestCenterStatusEnum.CLOSED.getCode());

            for (ServiceRequestCenter request : requests) {
                Integer status = request.getStatus();
                if (status == ServiceRequestCenterStatusEnum.OPEN.getCode()) {
                    openCount++;
                } else if (status == ServiceRequestCenterStatusEnum.IN_PROGRESS.getCode()) {
                    inProgressCount++;
                } else if (status == ServiceRequestCenterStatusEnum.RESOLVED.getCode()) {
                    resolvedCount++;
                }

                if (completedStatusList.contains(status)) {
                    completedCount++;
                }

                Integer priority = request.getPriority();
                if (priority == ServiceRequestCenterPriorityEnum.LOW.getCode()) {
                    lowCount++;
                } else if (priority == ServiceRequestCenterPriorityEnum.MEDIUM.getCode()) {
                    mediumCount++;
                } else if (priority == ServiceRequestCenterPriorityEnum.HIGH.getCode()) {
                    highCount++;
                } else if (priority == ServiceRequestCenterPriorityEnum.URGENT.getCode()) {
                    urgentCount++;
                }
            }

            ServiceRequestCenterStatisticsDTO statisticsDTO = new ServiceRequestCenterStatisticsDTO();
            statisticsDTO.setTotalCount(requests.size());
            statisticsDTO.setOpenCount(openCount);
            statisticsDTO.setInProgressCount(inProgressCount);
            statisticsDTO.setResolvedCount(resolvedCount);
            statisticsDTO.setCompletedCount(completedCount);
            statisticsDTO.setLowCount(lowCount);
            statisticsDTO.setMediumCount(mediumCount);
            statisticsDTO.setHighCount(highCount);
            statisticsDTO.setUrgentCount(urgentCount);

            // avg response time
            statisticsDTO.setResponseAvgTime(calculateAvgResponseTime(requests));

            // 计算 avg resolution time
            statisticsDTO.setResolutionAvgTime(calculateAvgResolutionTime(requests));

            return statisticsDTO;
        }

        /**
         * 计算平均响应时间
         *
         * @param requests 请求列表
         * @return 平均响应时间
         * @author yyt
         * @date 2025/12/18
         **/
        private BigDecimal calculateAvgResponseTime(List<ServiceRequestCenter> requests) {
            // 第一次处理时间 - 创建时间
            List<ServiceRequestCenter> needCalculateRequests = requests.stream()
                    .peek(ServiceRequestCenter::calculateResponseMinutes)
                    .filter(item -> Objects.nonNull(item.getResponseMinutes()))
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(needCalculateRequests)) return null;

            // 默认使用四舍五入
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode("half");

            // 每个 request 的分钟数累加 / 数量 / 60
            Long totalMinutes = needCalculateRequests.stream().map(ServiceRequestCenter::getResponseMinutes).reduce(BaseConstant.LONG_ZERO, Long::sum);
            return BigDecimal.valueOf(totalMinutes)
                    .divide(new BigDecimal(needCalculateRequests.size()), BaseConstant.DATA_PRECISION, roundingMode)
                    .divide(BigDecimal.valueOf(60), BaseConstant.DATA_PRECISION, roundingMode);
        }

        /**
         * 计算平均解决时间
         *
         * @param requests 请求列表
         * @return 平均解决时间
         * @author yyt
         * @date 2025/12/18
         **/
        private BigDecimal calculateAvgResolutionTime(List<ServiceRequestCenter> requests) {
            List<ServiceRequestCenter> needCalculateRequests = requests.stream()
                    .peek(ServiceRequestCenter::calculateResolutionMinutes)
                    .filter(item -> Objects.nonNull(item.getResolutionMinutes()))
                    .toList();
            if (CollectionUtils.isEmpty(needCalculateRequests)) return null;

            // 默认使用四舍五入
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode("half");

            // 每个 request 的分钟数累加 / 数量 / 60
            Long totalMinutes = needCalculateRequests.stream().map(ServiceRequestCenter::getResolutionMinutes).reduce(BaseConstant.LONG_ZERO, Long::sum);
            return BigDecimal.valueOf(totalMinutes)
                    .divide(new BigDecimal(needCalculateRequests.size()), BaseConstant.DATA_PRECISION, roundingMode)
                    .divide(BigDecimal.valueOf(60), BaseConstant.DATA_PRECISION, roundingMode);
        }

        /**
         * 当前部门下人员 statistics 信息
         *
         * @param tenantId    租户 id
         * @param propertyIds 登陆用户有权限的资产 id
         * @param userId      操作人
         * @param query       查询条件
         * @return statistics 信息
         * @author yyt
         * @date 2025/12/19
         **/
        @Override
        public ListPagedDTO<StatisticsCurrentDepartmentDTO> departmentStatistics(int tenantId, List<Integer> propertyIds, int userId, StatisticsCurrentDepartmentQuery query) {
            // 分页获取当前部门下的员工+管理员
            ServiceRequestCenterDepartmentEnum department = getUserDepartment(tenantId, userId);
            int type = department.getCode();
            List<UserDTO> users = listCurrentDepartmentUser(tenantId, type,
                    CollectionUtils.isEmpty(query.getPropertyIdList()) ? propertyIds : query.getPropertyIdList(), null);
            if (CollectionUtils.isEmpty(users)) return new ListPagedDTO<>();

            List<UserDTO> pageUser = PaginationUtil.getPage(users, query.getPage(), query.getSize());
            if (CollectionUtils.isEmpty(pageUser)) return new ListPagedDTO<>();

            // 查询分配给当前部门下的 request
            List<Integer> userIds = pageUser.stream().map(UserDTO::getId).toList();
            List<ServiceRequestCenter> allRequests;
            if (type == ServiceRequestCenterTypeEnum.ACCOUNT.getCode()) {
                allRequests = list(tenantId, userIds);
            } else {
                allRequests = baseMapper.listForStatistics(tenantId, type,
                        CollectionUtils.isEmpty(query.getPropertyIdList()) ? propertyIds : query.getPropertyIdList(), null, userIds);
            }

            // 统计每个人 未完成状态 (open、inProgress) 的 request
            List<Integer> unfinishedStatus = Lists.newArrayList(ServiceRequestCenterStatusEnum.OPEN.getCode(), ServiceRequestCenterStatusEnum.IN_PROGRESS.getCode());
            Map<Integer, Integer> unfinishedCountByUserId = allRequests.stream().collect(Collectors.groupingBy(ServiceRequestCenter::getDutyUser,
                    Collectors.collectingAndThen(Collectors.toList(),
                            item ->
                                    item.stream()
                                            .filter(request -> unfinishedStatus.contains(request.getStatus()))
                                            .toList()
                                            .size())));

            // 筛选日期之前的 request（默认全部）
            List<ServiceRequestCenter> requestForDate = allRequests;
            String date = query.getDate();
            if (StringUtils.isNotEmpty(date)) {
                // 筛选日期之前的 request
                Integer dateInteger = Integer.parseInt(date);
                requestForDate = allRequests.stream()
                        .filter(item -> item.getCreatedDate() <= dateInteger)
                        .toList();
            }

            Map<Integer, List<ServiceRequestCenter>> requestsByUserId = requestForDate.stream()
                    .peek(ServiceRequestCenter::calculateResolutionMinutes)
                    .collect(Collectors.groupingBy(ServiceRequestCenter::getDutyUser));

            List<StatisticsCurrentDepartmentDTO> statisticsDTOList = Lists.newArrayListWithExpectedSize(pageUser.size());
            for (UserDTO userDTO : pageUser) {
                StatisticsCurrentDepartmentDTO statisticsDTO = new StatisticsCurrentDepartmentDTO();
                Integer currentUserId = userDTO.getId();
                statisticsDTO.setId(currentUserId);
                statisticsDTO.setName(userDTO.getName());

                List<ServiceRequestCenter> currentUserRequestsForDate = requestsByUserId.getOrDefault(currentUserId, Collections.emptyList());
                statisticsDTO.setAssigned(currentUserRequestsForDate.size());
                statisticsDTO.setResolutionAvgTime(calculateAvgResolutionTime(currentUserRequestsForDate));

                statisticsDTO.setPendingWorkload(unfinishedCountByUserId.getOrDefault(currentUserId, BaseConstant.ZERO));
                statisticsDTOList.add(statisticsDTO);
            }

            return new ListPagedDTO<>(users.size(), statisticsDTOList);
        }

        /**
         * 获取待分配的 ticket
         *
         * @param tenantId     租户 id
         * @param propertyDTOs 资产
         * @return 待分配的 ticket
         * @author yyt
         * @date 2025/12/19
         **/
        @Override
        public List<ServiceRequestCenter> listPendingAllocationTicket(int tenantId, List<PropertyDTO> propertyDTOs) {
            // 过去24小时内未分配的 request
            Map<String, List<Integer>> propertyIdsByTimeZone = propertyDTOs.stream()
                    .collect(Collectors.groupingBy(PropertyDTO::getTimezone,
                            Collectors.mapping(PropertyDTO::getId, Collectors.toList())));
            List<ServiceRequestCenter> requests = Lists.newArrayList();
            propertyIdsByTimeZone.forEach((timezone, propertyIds) -> {
                ZonedDateTime endDate = DateTimeUtils.dateTimeNow(timezone);
                ZonedDateTime startDate = endDate.minusHours(23);
                requests.addAll(baseMapper.listPendingAllocationTicket(tenantId, propertyIds, startDate.toEpochSecond(), endDate.toEpochSecond()));
            });
            return requests;
        }

        /**
         * 查询超过7天未close的 request
         *
         * @param tenantId 租户 id
         * @return 超过7天未close的 request
         * @author yyt
         * @date 2025/12/19
         **/
        @Override
        public List<ServiceRequestCenter> listUnclosedRequests(Integer tenantId) {
            long targetDateTime = DateTimeUtils.dateNow(defaultTimeZone).minusDays(6).toEpochSecond();
            return list(new QueryWrapper<ServiceRequestCenter>().lambda()
                    .eq(ServiceRequestCenter::getTenantId, tenantId)
                    .eq(ServiceRequestCenter::getStatus, ServiceRequestCenterStatusEnum.RESOLVED.getCode())
                    .lt(ServiceRequestCenter::getResolvedTime, targetDateTime));
        }

    }