# ServiceRequestCenterCommentServiceImpl.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.ListPagedDTO;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.pojo.query.PageSizeQuery;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.it.cons.servicerequestcenter.ServiceRequestCenterAddCommentCons;
    import cloud.wconnect.it.cons.servicerequestcenter.ServiceRequestCenterLogCons;
    import cloud.wconnect.it.cons.servicerequestcenter.ServiceRequestCenterStatusEnum;
    import cloud.wconnect.it.entity.servicerequestcenter.ServiceRequestCenter;
    import cloud.wconnect.it.entity.servicerequestcenter.ServiceRequestCenterComment;
    import cloud.wconnect.it.mapper.servicerequestcenter.ServiceRequestCenterCommentMapper;
    import cloud.wconnect.it.pojo.bo.servicerequestcenter.ServiceRequestCenterNotifyBodyBO;
    import cloud.wconnect.it.pojo.dto.servicerequestcenter.AssignBasicDTO;
    import cloud.wconnect.it.pojo.dto.servicerequestcenter.ChangeValueBasicDTO;
    import cloud.wconnect.it.pojo.dto.servicerequestcenter.SaveServiceRequestCenterCommentDTO;
    import cloud.wconnect.it.pojo.dto.servicerequestcenter.ServiceRequestCenterCommentDTO;
    import cloud.wconnect.it.service.servicerequestcenter.IServiceRequestCenterCommentService;
    import cloud.wconnect.it.service.servicerequestcenter.IServiceRequestCenterLogService;
    import cloud.wconnect.it.service.servicerequestcenter.IServiceRequestCenterService;
    import cloud.wconnect.it.service.servicerequestcenter.notify.IServiceRequestCenterNotifyService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    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.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

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

    /**
     * <p>
     *  服务实现类
     * </p>
     *
     * @author yyt
     * @since 2025-12-16
     */
    @Service
    @DS("it_manage")
    public class ServiceRequestCenterCommentServiceImpl extends ServiceImpl<ServiceRequestCenterCommentMapper, ServiceRequestCenterComment> implements IServiceRequestCenterCommentService {

        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private IServiceRequestCenterService serviceRequestCenterService;
        @Autowired
        private IServiceRequestCenterNotifyService serviceRequestCenterCommentOperation;
        @Autowired
        private IServiceRequestCenterLogService serviceRequestCenterLogService;

        /**
         * my request 页面填写备注
         *
         * @param tenantId       租户 id
         * @param request        request
         * @param saveCommentDTO 备注信息
         * @author yyt
         * @date 2025/12/17
         */
        @Override
        public void saveCommentForMyRequest(int tenantId, ServiceRequestCenter request, SaveServiceRequestCenterCommentDTO saveCommentDTO) {
            Integer requestId = request.getId();
            Integer userId = request.getCreatedBy();
            // 添加备注
            save(requestId, saveCommentDTO.getContent(), saveCommentDTO.getAttachments(), userId);

            // 若没责任人，则 return
            // 若有责任人，则给责任人发通知（若责任人是自己，则不通知）, 若责任人离职，则清空责任人、重置待分配通知时间（待分配通知时查询 request 使用），不发通知
            // 如果状态是 resolved、closed, 则置 request 状态为 open，清空完成时间、关闭人、关闭时间，并记录 reopen log
            Integer dutyUser = request.getDutyUser();
            if (dutyUser == BaseConstant.ZERO) return;

            Integer status = request.getStatus();
            List<Integer> completeStatus = Lists.newArrayList(ServiceRequestCenterStatusEnum.RESOLVED.getCode(), ServiceRequestCenterStatusEnum.CLOSED.getCode());

            UserDTO user = userInternalService.getOne(tenantId, dutyUser);
            if (!user.getStatus()) {
                // 责任人离职，清空责任人，重置待分配通知时间，不发通知
                serviceRequestCenterService.update(new UpdateWrapper<ServiceRequestCenter>().lambda()
                        .eq(ServiceRequestCenter::getId, requestId)
                        .set(ServiceRequestCenter::getDutyUser, BaseConstant.ZERO)
                        .set(ServiceRequestCenter::getPendingAllocationTime, DateTimeUtils.nowTimestamp()));
            } else {
                // 给责任人发送添加备注通知
                if (!Objects.equals(dutyUser, userId)) {
                    // 若状态是 resolve / closed，则发 reopen 通知
                    // 否则发添加备注通知
                    if (completeStatus.contains(status)) {
                        handleNotify(tenantId, request, saveCommentDTO, userId, ServiceRequestCenterAddCommentCons.USER_ADD_COMMENT_TO_REOPEN);
                    } else {
                        handleNotify(tenantId, request, saveCommentDTO, userId, ServiceRequestCenterAddCommentCons.USER_ADD_COMMENT);
                    }
                }
            }

            if (completeStatus.contains(status)) {
                // 置 open，清空完成时间、关闭人、关闭时间，并记录 reopen log
                serviceRequestCenterService.update(new UpdateWrapper<ServiceRequestCenter>().lambda()
                        .eq(ServiceRequestCenter::getId, requestId)
                        .set(ServiceRequestCenter::getStatus, ServiceRequestCenterStatusEnum.OPEN.getCode())
                        .set(ServiceRequestCenter::getResolvedTime, null)
                        .set(ServiceRequestCenter::getClosedBy, null)
                        .set(ServiceRequestCenter::getClosedTime, null));

                serviceRequestCenterLogService.save(requestId, ServiceRequestCenterLogCons.REOPEN,
                        JsonUtils.convertObjToString(objectMapper, new ChangeValueBasicDTO(status, ServiceRequestCenterStatusEnum.OPEN.getCode())),
                        userId);
            }
        }

        /**
         * 责任人填写备注
         *
         * @param tenantId       租户 id
         * @param request        request
         * @param saveCommentDTO 备注信息
         * @param userId         用户id
         * @author yyt
         * @date 2025/12/17
         */
        @Override
        public void saveCommentForDutyUser(int tenantId, ServiceRequestCenter request, SaveServiceRequestCenterCommentDTO saveCommentDTO, int userId) {
            // 保存备注，通知用户（若用户是自己，则不通知）
            save(request.getId(), saveCommentDTO.getContent(), saveCommentDTO.getAttachments(), userId);
            if (!Objects.equals(request.getCreatedBy(), userId)) {
                handleNotify(tenantId, request, saveCommentDTO, userId, ServiceRequestCenterAddCommentCons.DUTY_USER_ADD_COMMENT);
            }
        }

        /**
         * 管理员填写备注
         *
         * @param tenantId       租户 id
         * @param request        request
         * @param saveCommentDTO 备注信息
         * @param userId         用户id
         * @author yyt
         * @date 2025/12/17
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void saveCommentForManager(int tenantId, ServiceRequestCenter request, SaveServiceRequestCenterCommentDTO saveCommentDTO, int userId) {
            // 保存备注，通知用户（若用户是自己，则不通知）
            saveCommentForDutyUser(tenantId, request, saveCommentDTO, userId);

            Integer requestId = request.getId();
            // 自动分到自己名下，并添加操作log
            serviceRequestCenterService.update(new UpdateWrapper<ServiceRequestCenter>().lambda()
                    .eq(ServiceRequestCenter::getId, requestId)
                    .set(ServiceRequestCenter::getDutyUser, userId));

            String expand = JsonUtils.convertObjToString(objectMapper, new AssignBasicDTO(userId));
            serviceRequestCenterLogService.save(requestId, ServiceRequestCenterLogCons.ASSIGN, expand, userId);
        }

        /**
         * 发送添加备注通知
         *
         * @param tenantId       租户 id
         * @param request        request
         * @param saveCommentDTO 备注信息
         * @param userId         用户id
         * @param commentType    备注类型
         * @author yyt
         * @date 2025/12/17
         **/
        private void handleNotify(int tenantId, ServiceRequestCenter request, SaveServiceRequestCenterCommentDTO saveCommentDTO, Integer userId, int commentType) {
            ServiceRequestCenterComment comment = new ServiceRequestCenterComment();
            comment.setContent(saveCommentDTO.getContent());
            comment.setAttachments(saveCommentDTO.getAttachments());
            comment.setCreatedBy(userId);
            ServiceRequestCenterNotifyBodyBO notifyBodyBO = new ServiceRequestCenterNotifyBodyBO();
            notifyBodyBO.setTenantId(tenantId);
            notifyBodyBO.setRequestId(request.getId());
            notifyBodyBO.setComment(comment);
            notifyBodyBO.setCommentType(commentType);
            notifyBodyBO.setOperationId(userId);
            serviceRequestCenterCommentOperation.notify(notifyBodyBO);
        }

        /**
         * 根据 requestIds 批量查询
         *
         * @param requestIds requestIds
         * @return 批量查询结果
         * @author yyt
         * @date 2025/12/16
         */
        @Override
        public List<ServiceRequestCenterComment> listByRequestIds(List<Integer> requestIds) {
            return list(new QueryWrapper<ServiceRequestCenterComment>().lambda()
                    .in(ServiceRequestCenterComment::getRequestId, requestIds));
        }

        /**
         * 获取备注
         *
         * @param tenantId  租户 id
         * @param requestId request id
         * @param query     查询条件
         * @return 备注
         * @author yyt
         * @date 2025/12/17
         **/
        @Override
        public ListPagedDTO<ServiceRequestCenterCommentDTO> listComment(int tenantId, int requestId, PageSizeQuery query) {
            Page<ServiceRequestCenterComment> page = page(new Page<>(query.getPage(), query.getSize()),
                    new QueryWrapper<ServiceRequestCenterComment>().lambda()
                            .eq(ServiceRequestCenterComment::getRequestId, requestId)
                            .orderByDesc(ServiceRequestCenterComment::getId));
            List<ServiceRequestCenterComment> comments = page.getRecords();
            if (CollectionUtils.isEmpty(comments)) return new ListPagedDTO<>();

            Map<Integer, String> userNameById = userInternalService.getNameMapByIds(tenantId,
                    comments.stream().map(ServiceRequestCenterComment::getCreatedBy).collect(Collectors.toSet()));

            return new ListPagedDTO<>(page.getTotal(), beanMapper.mapList(comments, ServiceRequestCenterCommentDTO.class,
                    (comment, dto) -> {
                        dto.setCreatedName(userNameById.get(comment.getCreatedBy()));
                    }));
        }

        /**
         * 保存
         *
         * @param requestId   request id
         * @param content     内容
         * @param attachments 附件
         * @param createdBy   创建人
         * @author yyt
         * @date 2025/12/17
         **/
        @Override
        public void save(Integer requestId, String content, String attachments, Integer createdBy) {
            save(new ServiceRequestCenterComment()
                    .setRequestId(requestId)
                    .setContent(content)
                    .setAttachments(attachments)
                    .setCreatedBy(createdBy)
                    .setCreatedTime(DateTimeUtils.nowTimestamp()));
        }

    }