# GmwrStrDataNoteServiceImpl.java

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

    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.gmwr.GmwrStrDataNote;
    import cloud.wconnect.workperformance.mapper.gmwr.GmwrStrDataNoteMapper;
    import cloud.wconnect.workperformance.pojo.dto.gmwr.strdata.note.GmwrStrDataNoteDateDTO;
    import cloud.wconnect.workperformance.service.gmwr.IGmwrStrDataNoteService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.google.common.collect.Lists;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.stereotype.Service;

    import java.util.*;
    import java.util.function.Function;
    import java.util.stream.Collectors;

    /**
     * <p>
     * Weekly GM Report - STR Data Note 服务实现类
     * </p>
     *
     * @author zc
     * @since 2025-02-28
     */
    @Service
    @DS("work_performance")
    public class GmwrStrDataNoteServiceImpl extends ServiceImpl<GmwrStrDataNoteMapper, GmwrStrDataNote> implements IGmwrStrDataNoteService {

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

        /**
         * 保存备注数据
         *
         * @param propertyId  属性 id
         * @param reportId    报告 id
         * @param noteDTOList 备注数据
         * @param operatorId  操作人 id
         * @author zc
         * @date 2025/3/2
         */
        @Override
        public void save(int propertyId, int reportId, List<GmwrStrDataNoteDateDTO> noteDTOList, int operatorId) {
            if (CollectionUtils.isEmpty(noteDTOList)) {
                return;
            }
            Map<Integer, Map<Integer, GmwrStrDataNote>> category2NoteByDateCategory = listByReportId(reportId).stream()
                    .collect(Collectors.groupingBy(GmwrStrDataNote::getDateCategory,
                            Collectors.toMap(GmwrStrDataNote::getCategory, Function.identity())));

            long nowTimestamp = DateTimeUtils.nowTimestamp();
            List<GmwrStrDataNote> noteList = Lists.newArrayList();
            noteDTOList.forEach(item -> {
                Map<Integer, GmwrStrDataNote> category2Note = category2NoteByDateCategory.getOrDefault(item.getCategory(), Collections.emptyMap());
                item.getList().forEach(note -> {
                    GmwrStrDataNote 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 GmwrStrDataNote().setPropertyId(propertyId)
                                .setReportId(reportId).setDateCategory(item.getCategory()).setCategory(note.getCategory())
                                .setContent(note.getContent()).setUpdatedBy(operatorId).setUpdatedTime(nowTimestamp));
                    }
                });
            });
            if (CollectionUtils.isEmpty(noteList)) {
                return;
            }
            // 按唯一索引字段排序，避免死锁
            noteList.sort(Comparator.comparing(GmwrStrDataNote::getReportId)
                    .thenComparing(GmwrStrDataNote::getDateCategory)
                    .thenComparing(GmwrStrDataNote::getCategory));

            baseMapper.insertOrUpdateBatchByUnique(noteList);
        }

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