# ItticketCommentServiceImpl.java

    package cloud.wconnect.it.service.itrequest.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.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.util.*;
    import cloud.wconnect.it.cons.S3BucketFunctionCons;
    import cloud.wconnect.it.entity.itrequest.ItticketComment;
    import cloud.wconnect.it.mapper.itrequest.ItticketCommentMapper;
    import cloud.wconnect.it.pojo.dto.itrequest.ExpansionDTO;
    import cloud.wconnect.it.pojo.dto.itrequest.ItticketCommentDTO;
    import cloud.wconnect.it.service.itrequest.IItticketCommentService;
    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.databind.ObjectMapper;
    import com.google.common.collect.Lists;
    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.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;
    import java.util.stream.Collectors;

    /**
     * <p>
     *  服务实现类
     * </p>
     *
     * @author yyt
     * @since 2023-03-25
     */
    @DS("it_manage")
    @Service
    public class ItticketCommentServiceImpl extends ServiceImpl<ItticketCommentMapper, ItticketComment> implements IItticketCommentService {

        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private ObjectMapper objectMapper;

        @Value("${aws-s3.region}")
        private String region;
        @Value("#{${aws-s3.function-bucket}}")
        private Map<String, Map<String, Object>> bucketMap;

        /**
         * 添加 itticket 附件
         *
         * @param propertyId  资产
         * @param id          itticket id
         * @param attachments 附件
         * @param userId      操作人
         * @author yyt
         * @date 2023/3/25
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void saveItticketAttachment(int propertyId, Integer id, List<String> attachments, Integer userId) {
            if (CollectionUtils.isEmpty(attachments)) {
                return;
            }

            saveBatch(attachments.stream().map(item -> new ItticketComment().setPropertyId(propertyId).setItticketId(id)
                            .setContent(item).setCommentType(ItticketComment.TYPE_ITTICKET_ATTACHMENT)
                            .setCreateId(userId).setCreateTime(DateTimeUtils.nowTimestamp()))
                    .collect(Collectors.toList()));
        }

        /**
         * 清除 itticket 附件
         *
         * @param id itticket id
         * @author yyt
         * @date 2023/3/25
         */
        @Override
        public void clearItticketAttachment(Integer id) {
            remove(new QueryWrapper<ItticketComment>().lambda().eq(ItticketComment::getItticketId, id)
                    .eq(ItticketComment::getCommentType, ItticketComment.TYPE_ITTICKET_ATTACHMENT));
        }

        /**
         * 获取 itticket 附件
         *
         * @param id itticket id
         * @return itticket 附件
         * @author yyt
         * @date 2023/3/27
         */
        @Override
        public List<ItticketComment> getItticketAttachment(Integer id) {
            return baseMapper.selectList(new QueryWrapper<ItticketComment>().lambda().eq(ItticketComment::getItticketId, id)
                    .eq(ItticketComment::getCommentType, ItticketComment.TYPE_ITTICKET_ATTACHMENT));
        }

        /**
         * 获取 itticket 备注
         *
         * @param id itticket id
         * @return itticket 备注
         * @author yyt
         * @date 2023/3/27
         */
        @Override
        public List<ItticketComment> listItticketComment(Integer id) {
            return baseMapper.selectList(new QueryWrapper<ItticketComment>().lambda().eq(ItticketComment::getItticketId, id)
                    .ne(ItticketComment::getCommentType, ItticketComment.TYPE_ITTICKET_ATTACHMENT)
                    .orderByDesc(ItticketComment::getId));
        }

        /**
         * 新增备注
         *
         * @param id                 itticket id
         * @param propertyId         资产 id
         * @param itticketCommentDTO 备注信息
         * @param userId             操作人
         * @return 新增的备注
         * @author yyt
         * @date 2023/3/27
         */
        @Override
        public ItticketComment saveComment(int id, int propertyId, ItticketCommentDTO itticketCommentDTO, Integer userId) {
            ItticketComment itticketComment = beanMapper.map(itticketCommentDTO, ItticketComment.class);
            itticketComment.setItticketId(id).setPropertyId(propertyId).setCreateId(userId)
                    .setCreateTime(DateTimeUtils.nowTimestamp());
            save(itticketComment);

            return itticketComment;
        }

        /**
         * 校验备注存在
         *
         * @param itId it id
         * @param id   备注 id
         * @return 备注
         * @author yyt
         * @date 2023/3/28
         */
        @Override
        public ItticketComment checkExist(int itId, int id) {
            ItticketComment comment = getOne(new QueryWrapper<ItticketComment>().lambda().eq(ItticketComment::getItticketId, itId)
                    .eq(ItticketComment::getId, id));
            if (Objects.isNull(comment)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "the itticketComment is not found;id:" + id);
            }
            return comment;
        }

        /**
         * 获取最后一次备注
         *
         * @param itId it id
         * @return 最后一次备注
         * @author yyt
         * @date 2024/4/15
         **/
        @Override
        public ItticketComment getLastComment(Integer itId) {
            return getOne(new QueryWrapper<ItticketComment>().lambda().eq(ItticketComment::getItticketId, itId)
                    .in(ItticketComment::getCommentType, Lists.newArrayList(ItticketComment.TYPE_TEXT, ItticketComment.TYPE_ATTACHMENT))
                    .orderByDesc(ItticketComment::getId).last("limit 1"));
        }

        /**
         * 获取 ticket 备注
         *
         * @param tenantId 租户 id
         * @param ticketId ticket id
         * @return 备注
         * @author yyt
         * @date 2026/1/19
         **/
        @Override
        public List<ItticketCommentDTO> listTicketCommentDTO(Integer tenantId, int ticketId) {
            List<ItticketComment> comments = listItticketComment(ticketId);
            if (CollectionUtils.isEmpty(comments)) {
                return Collections.emptyList();
            }

            List<Integer> userIds = comments.stream().map(ItticketComment::getCreateId).distinct().collect(Collectors.toList());
            userIds.addAll(comments.stream().filter(item -> StringUtils.isNotEmpty(item.getExpansionJson()))
                    .map(item -> JsonUtils.convertStringToObject(objectMapper, item.getExpansionJson(), ExpansionDTO.class).getAcceptBy())
                    .toList());

            Map<Integer, UserDTO> userById = userInternalService.getUsers(tenantId, userIds)
                    .stream().collect(Collectors.toMap(UserDTO::getId, v -> v));
            return beanMapper.mapList(comments, ItticketCommentDTO.class,
                    (entity, item) -> {
                        UserDTO userDTO = userById.get(item.getCreateId());
                        item.setCreateName(userDTO.getName());
                        item.setAvatar(userDTO.getAvatar());

                        String expansionJson = entity.getExpansionJson();
                        if (StringUtils.isNotEmpty(expansionJson)) {
                            ExpansionDTO expansionDTO = JsonUtils.convertStringToObject(objectMapper, expansionJson, ExpansionDTO.class);
                            expansionDTO.setAcceptName(userById.get(expansionDTO.getAcceptBy()).getName());
                            item.setExpansion(expansionDTO);
                        }
                    });
        }

        /**
         * 删除 ticket 备注
         *
         * @param comment 备注
         * @author yyt
         * @date 2026/1/19
         **/
        @Override
        public void delete(ItticketComment comment) {
            boolean result = removeById(comment.getId());
            if (result && comment.getCommentType() == ItticketComment.TYPE_ATTACHMENT) {
                //删除附件
                List<String> delS3Keys = AttachmentUtil.getKeysByAttachments(Lists.newArrayList(comment.getContent()), objectMapper);
                S3Utils.batchDeleteFile(region, bucketMap.get(S3BucketFunctionCons.IT_REQUEST), delS3Keys);
            }
        }

    }