# GmwrMonthEndNoteServiceImpl.java

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

    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.gmwr.GmwrMonthEndNote;
    import cloud.wconnect.workperformance.mapper.gmwr.GmwrMonthEndNoteMapper;
    import cloud.wconnect.workperformance.pojo.dto.gmwr.monthend.GmwrMonthEndNoteDTO;
    import cloud.wconnect.workperformance.service.gmwr.IGmwrMonthEndNoteService;
    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 - Month End Note 服务实现类
     * </p>
     *
     * @author zc
     * @since 2025-02-28
     */
    @Service
    @DS("work_performance")
    public class GmwrMonthEndNoteServiceImpl extends ServiceImpl<GmwrMonthEndNoteMapper, GmwrMonthEndNote> implements IGmwrMonthEndNoteService {

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

        /**
         * 保存备注
         *
         * @param propertyId  资产 id
         * @param reportId    报告 id
         * @param noteDTOList 备注集合
         * @param operatorId  操作人 id
         * @author zc
         * @date 2025/2/28
         */
        @Override
        public void save(int propertyId, int reportId, List<GmwrMonthEndNoteDTO> noteDTOList, int operatorId) {
            if (CollectionUtils.isEmpty(noteDTOList)) {
                return;
            }
            Map<Integer, GmwrMonthEndNote> category2Note = listByReportId(reportId).stream()
                    .collect(Collectors.toMap(GmwrMonthEndNote::getCategory, Function.identity()));

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

            baseMapper.insertOrUpdateBatchByUnique(noteList);
        }

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