# SvaCommentServiceImpl.java

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

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.sva.SvaComment;
    import cloud.wconnect.workperformance.mapper.sva.SvaCommentMapper;
    import cloud.wconnect.workperformance.pojo.dto.sva.schedulevsactual.SvaCommentDTO;
    import cloud.wconnect.workperformance.pojo.dto.sva.schedulevsactual.SvaCommentListDTO;
    import cloud.wconnect.workperformance.pojo.query.sva.schedulevsactual.SvaCommentQuery;
    import cloud.wconnect.workperformance.service.sva.scheduleactual.ISvaCommentService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import jakarta.annotation.Resource;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.stereotype.Service;

    import java.text.MessageFormat;
    import java.util.*;
    import java.util.stream.Collectors;

    /**
     * <p>
     * Schedule vs Actual Hours 评论表 服务实现类
     * </p>
     *
     * @author zc
     * @since 2023-06-26
     */
    @Service
    @DS("work_performance")
    public class SvaCommentServiceImpl extends ServiceImpl<SvaCommentMapper, SvaComment> implements ISvaCommentService {
        @Resource
        private UserInternalService userInternalService;
        @Resource
        private BeanMapper beanMapper;

        /**
         * 根据 position id 获取指定日期范围的评论数据
         *
         * @param propertyId 资产 id
         * @param fromDate   开始日期时间戳
         * @param toDate     结束日期时间戳
         * @return 评论数据集合
         * @author zc
         * @date 2025/4/23
         */
        @Override
        public List<SvaComment> listByDateRange(int propertyId, long fromDate, long toDate) {
            return list(new QueryWrapper<SvaComment>().lambda()
                    .eq(SvaComment::getPropertyId, propertyId)
                    .between(SvaComment::getTheDate, fromDate, toDate));
        }

        /**
         * 获取评论数据
         *
         * @param tenantId   租户 id
         * @param propertyId 资产 id
         * @param query      查询条件
         * @return 评论集合
         * @author zc
         * @date 2025/2/7
         */
        @Override
        public List<SvaCommentListDTO> listComment(int tenantId, int propertyId, SvaCommentQuery query) {
            List<SvaComment> commentList = list(new QueryWrapper<SvaComment>().lambda()
                    .eq(SvaComment::getPropertyId, propertyId)
                    .eq(SvaComment::getPositionId, query.getPositionId())
                    .eq(SvaComment::getDeptCategoryId, query.getDepartmentCategoryId())
                    .eq(SvaComment::getTheDate, query.getTheDate())
                    .orderByDesc(SvaComment::getCreatedTime));
            if (CollectionUtils.isEmpty(commentList)) {
                return Collections.emptyList();
            }

            // 获取创建人信息
            Set<Integer> userIds = commentList.stream().map(SvaComment::getCreatedBy).collect(Collectors.toSet());
            Map<Integer, UserDTO> userId2UserDTO = userInternalService.getUserMapByIds(tenantId, userIds);
            return beanMapper.mapList(commentList, SvaCommentListDTO.class, item -> {
                UserDTO userDTO = userId2UserDTO.getOrDefault(item.getCreatedBy(), new UserDTO());
                item.setCreatedName(userDTO.getName());
                item.setAvatar(userDTO.getAvatar());
            });
        }

        /**
         * 校验数据存在
         *
         * @param id 评论 id
         * @return SvaComment
         * @author zc
         * @date 2025/12/18
         */
        @Override
        public SvaComment checkExist(int id) {
            SvaComment comment = getById(id);
            if (Objects.isNull(comment)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The comment is not found; id:" + id);
            }
            return comment;
        }

        /**
         * 校验数据归属
         *
         * @param propertyId 资产 id
         * @param operatorId 操作人 id
         * @param comment    评论数据
         * @author zc
         * @date 2025/12/18
         */
        @Override
        public void checkBelong(int propertyId, int operatorId, SvaComment comment) {
            if (!comment.getPropertyId().equals(propertyId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The importLog does not belong to this property; propertyId:{0}; commentPropertyId:{1}",
                                propertyId, comment.getPropertyId()));
            }
            if (!Objects.equals(comment.getCreatedBy(), operatorId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The comment does not belong to the user; origin: {0}, current: {1}",
                                comment.getCreatedBy(), operatorId));
            }
        }

        /**
         * 保存评论数据
         *
         * @param propertyId 资产 id
         * @param commentDTO 评论 DTO
         * @param operatorId 操作人 id
         * @return 评论 id
         * @author zc
         * @date 2025/12/18
         */
        @Override
        public int save(int propertyId, SvaCommentDTO commentDTO, int operatorId) {
            SvaComment comment = new SvaComment();
            comment.setPropertyId(propertyId);
            comment.setPositionId(commentDTO.getPositionId());
            comment.setDeptCategoryId(commentDTO.getDepartmentCategoryId());
            comment.setTheDate(commentDTO.getTheDate());
            comment.setComment(commentDTO.getComment());
            comment.setCreatedBy(operatorId);
            comment.setCreatedTime(DateTimeUtils.nowTimestamp());

            save(comment);

            return comment.getId();
        }
    }