# GmwrMonthlyOtbPaceNoteServiceImpl.java

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

    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.gmwr.GmwrMonthlyOtbPaceNote;
    import cloud.wconnect.workperformance.mapper.gmwr.GmwrMonthlyOtbPaceNoteMapper;
    import cloud.wconnect.workperformance.pojo.dto.gmwr.monthlyotbpace.note.GmwrMonthlyOtbPaceNoteDateDTO;
    import cloud.wconnect.workperformance.service.gmwr.IGmwrMonthlyOtbPaceNoteService;
    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 - Monthly OTB Pace Note 服务实现类
     * </p>
     *
     * @author zc
     * @since 2025-02-28
     */
    @Service
    @DS("work_performance")
    public class GmwrMonthlyOtbPaceNoteServiceImpl extends ServiceImpl<GmwrMonthlyOtbPaceNoteMapper, GmwrMonthlyOtbPaceNote> implements IGmwrMonthlyOtbPaceNoteService {

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

        /**
         * 保存备注
         *
         * @param propertyId  资产 id
         * @param reportId    报告 id
         * @param noteDTOList 备注列表
         * @param operatorId  操作人 id
         * @author zc
         * @date 2025/3/1
         */
        @Override
        public void save(int propertyId, int reportId, List<GmwrMonthlyOtbPaceNoteDateDTO> noteDTOList, int operatorId) {
            if (CollectionUtils.isEmpty(noteDTOList)) {
                return;
            }
            Map<Long, Map<Integer, GmwrMonthlyOtbPaceNote>> category2NoteByMonth = listByReportId(reportId).stream()
                    .collect(Collectors.groupingBy(GmwrMonthlyOtbPaceNote::getMonth,
                            Collectors.toMap(GmwrMonthlyOtbPaceNote::getCategory, Function.identity())));

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

            baseMapper.insertOrUpdateBatchByUnique(noteList);
        }

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