# GmwrHotelKpiNoteServiceImpl.java

    package cloud.wconnect.workperformance.service.gmwr.impl;

    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.gmwr.GmwrHotelKpiNote;
    import cloud.wconnect.workperformance.mapper.gmwr.GmwrHotelKpiNoteMapper;
    import cloud.wconnect.workperformance.pojo.dto.gmwr.hotelkpi.note.GmwrHotelKpiNoteDTO;
    import cloud.wconnect.workperformance.service.gmwr.IGmwrHotelKpiNoteService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.compress.utils.Lists;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.stereotype.Service;

    import java.util.Comparator;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;
    import java.util.function.Function;
    import java.util.stream.Collectors;

    /**
     * <p>
     * Weekly GM Report - Hotel KPI Note 服务实现类
     * </p>
     *
     * @author zc
     * @since 2025-02-28
     */
    @Service
    @DS("work_performance")
    public class GmwrHotelKpiNoteServiceImpl extends ServiceImpl<GmwrHotelKpiNoteMapper, GmwrHotelKpiNote> implements IGmwrHotelKpiNoteService {

        /**
         * 根据报告id获取备注数据
         *
         * @param reportId 报告 id
         * @return GmwrHotelKpiNote
         * @author zc
         * @date 2025/3/2
         */
        @Override
        public List<GmwrHotelKpiNote> listByReportId(int reportId) {
            return list(new LambdaQueryWrapper<GmwrHotelKpiNote>()
                    .eq(GmwrHotelKpiNote::getReportId, reportId));
        }

        /**
         * 保存备注
         *
         * @param propertyId  资产 id
         * @param reportId    报告 id
         * @param saveNoteDTO 备注数据
         * @param operatorId  操作人 id
         * @author zc
         * @date 2025/3/2
         */
        @Override
        public void save(int propertyId, int reportId, GmwrHotelKpiNoteDTO saveNoteDTO, int operatorId) {
            if (CollectionUtils.isEmpty(saveNoteDTO.getList())) {
                return;
            }
            Map<Integer, GmwrHotelKpiNote> category2Note = listByReportId(reportId).stream()
                    .collect(Collectors.toMap(GmwrHotelKpiNote::getCategory, Function.identity()));

            long nowTimestamp = DateTimeUtils.nowTimestamp();
            List<GmwrHotelKpiNote> noteList = Lists.newArrayList();
            saveNoteDTO.getList().forEach(note -> {
                GmwrHotelKpiNote originNote = category2Note.get(note.getCategory());
                if (Objects.nonNull(originNote)) {
                    editNote(originNote, note.getContent(), operatorId, nowTimestamp);
                    noteList.add(originNote);
                } else {
                    if (StringUtils.isBlank(note.getContent())) {
                        return;
                    }
                    noteList.add(new GmwrHotelKpiNote().setPropertyId(propertyId)
                            .setReportId(reportId).setCategory(note.getCategory())
                            .setContent(note.getContent()).setUpdatedBy(operatorId)
                            .setUpdatedTime(nowTimestamp));
                }
            });
            if (CollectionUtils.isEmpty(noteList)) {
                return;
            }
            // 按唯一索引字段排序，避免死锁
            noteList.sort(Comparator.comparing(GmwrHotelKpiNote::getReportId)
                    .thenComparing(GmwrHotelKpiNote::getCategory));

            baseMapper.insertOrUpdateBatchByUnique(noteList);
        }

        /**
         * 编辑备注
         *
         * @param originNote   原始备注
         * @param content      内容
         * @param operatorId   操作人 id
         * @param nowTimestamp 当前时间戳
         * @author zc
         * @date 2025/4/30
         */
        private void editNote(GmwrHotelKpiNote originNote, String content, int operatorId, long nowTimestamp) {
            if (Objects.equals(originNote.getContent(), content)) {
                return;
            }
            originNote.setContent(content);
            originNote.setUpdatedBy(operatorId);
            originNote.setUpdatedTime(nowTimestamp);
        }
    }