# SpecialEventServiceImpl.java

    package cloud.wconnect.workperformance.service.sva.setting.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.workperformance.entity.sva.setting.SpecialEvent;
    import cloud.wconnect.workperformance.mapper.sva.setting.SpecialEventMapper;
    import cloud.wconnect.workperformance.pojo.dto.sva.specialevent.DepDateSpecialEventTargetHourDTO;
    import cloud.wconnect.workperformance.pojo.dto.sva.specialevent.SpecialEventDTO;
    import cloud.wconnect.workperformance.pojo.query.sva.specialevent.SpecialEventQuery;
    import cloud.wconnect.workperformance.service.sva.setting.ISpecialEventService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.Lists;
    import jakarta.annotation.Resource;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.stereotype.Service;

    import java.math.BigDecimal;
    import java.text.MessageFormat;
    import java.util.*;

    /**
     * <p>
     * 服务实现类：特殊事件
     * </p>
     *
     * @author zc
     * @since 2023-03-14
     */
    @Service
    @DS("work_performance")
    public class SpecialEventServiceImpl extends ServiceImpl<SpecialEventMapper, SpecialEvent> implements ISpecialEventService {
        @Resource
        private BeanMapper beanMapper;
        @Resource
        private ObjectMapper objectMapper;

        /**
         * 新增 Special Event
         *
         * @param propertyId      资产 id
         * @param operatorId      操作人 id
         * @param specialEventDTO Special Event 数据
         * @return Special Event id
         * @author zc
         * @date 2023/3/14
         */
        @Override
        public int insert(int propertyId, int operatorId, SpecialEventDTO specialEventDTO) {
            SpecialEvent specialEvent = beanMapper.map(specialEventDTO, SpecialEvent.class);
            specialEvent.setPropertyId(propertyId);
            specialEvent.setCreatedBy(operatorId);
            specialEvent.setCreatedTime(DateTimeUtils.nowTimestamp());
            save(specialEvent);
            return specialEvent.getId();
        }

        /**
         * 编辑 Special Event
         *
         * @param operatorId      操作人 id
         * @param specialEventDTO Special Event 数据
         * @author zc
         * @date 2023/3/14
         */
        @Override
        public void update(int operatorId, SpecialEventDTO specialEventDTO) {
            SpecialEvent specialEvent = beanMapper.map(specialEventDTO, SpecialEvent.class);
            specialEvent.setLastUpdatedBy(operatorId);
            specialEvent.setLastUpdatedTime(DateTimeUtils.nowTimestamp());
            updateById(specialEvent);
        }

        /**
         * 获取指定日期范围内的 Special Event 集合
         *
         * @param propertyId 资产 id
         * @param query      查询条件
         * @return Special Event 集合
         * @author zc
         * @date 2023/3/14
         */
        @Override
        public List<SpecialEventDTO> list(int propertyId, SpecialEventQuery query) {
            List<SpecialEvent> specialEventList = list(new QueryWrapper<SpecialEvent>().lambda()
                    .eq(SpecialEvent::getPropertyId, propertyId)
                    .between(SpecialEvent::getTheDate, query.getStartDate(), query.getEndDate()));
            if (CollectionUtils.isEmpty(specialEventList)) {
                return Collections.emptyList();
            }
            return beanMapper.mapList(specialEventList, SpecialEventDTO.class);
        }

        /**
         * 获取指定日期范围内特殊活动设置的工时
         *
         * @param propertyId 资产 id
         * @param fromDate   开始日期
         * @param toDate     结束日期
         * @return SpecialEvent 集合
         * @author zc
         * @date 2023/6/28
         */
        @Override
        public List<SpecialEvent> listByDate(int propertyId, long fromDate, long toDate) {
            return list(new QueryWrapper<SpecialEvent>().lambda()
                    .eq(SpecialEvent::getPropertyId, propertyId)
                    .between(SpecialEvent::getTheDate, fromDate, toDate));
        }

        /**
         * 校验数据归属
         *
         * @param propertyId   资产 id
         * @param specialEvent SpecialEvent 数据
         * @author zc
         * @date 2025/7/31
         */
        @Override
        public void checkBelong(int propertyId, SpecialEvent specialEvent) {
            if (!specialEvent.getPropertyId().equals(propertyId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The requested does not belong to this property; propertyId:{0}; requestedPropertyId:{1}",
                                propertyId, specialEvent.getPropertyId()));
            }
        }

        /**
         * 获取部门指定日期范围内的特殊活动设置的工时
         *
         * @param propertyId 资产 id
         * @param fromDate   开始日期，时间戳
         * @param toDate     结束日期，时间戳
         * @return DepDateSpecialEventTargetHourDTO 集合
         * @author lichen
         * @date 2026/3/6
         */
        @Override
        public List<DepDateSpecialEventTargetHourDTO> listDepDateRange(int propertyId, long fromDate, long toDate) {
            List<SpecialEvent> specialEvents = listByDate(propertyId, fromDate, toDate);
            return convertSpecialEvent(specialEvents);
        }

        /**
         * 转换事件
         *
         * @param specialEvents 事件
         * @return java.util.List<cloud.wconnect.workperformance.pojo.dto.sva.specialevent.DepDateSpecialEventTargetHourDTO>
         * @author lichen
         * @date 2026/3/6
         */
        private List<DepDateSpecialEventTargetHourDTO> convertSpecialEvent(List<SpecialEvent> specialEvents) {
            if (CollectionUtils.isEmpty(specialEvents)) return Collections.emptyList();

            ArrayList<DepDateSpecialEventTargetHourDTO> resultList = Lists.newArrayList();
            for (SpecialEvent specialEvent : specialEvents) {
                Map<String, BigDecimal> departmentCode2Hours = JsonUtils.convertStringByTypeReference(objectMapper,
                        specialEvent.getCategoryRecomHours(), new TypeReference<>() {
                        });
                departmentCode2Hours.forEach((departmentCode, hours) -> {
                    if (Objects.nonNull(hours)) {
                        resultList.add(new DepDateSpecialEventTargetHourDTO(specialEvent.getTheDate(), departmentCode, specialEvent.getEventTitle(), hours));
                    }
                });
            }
            return resultList;
        }

    }