# GmwrSelloutEfficiencyNoteServiceImpl.java

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

    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.gmwr.GmwrSelloutEfficiencyNote;
    import cloud.wconnect.workperformance.mapper.gmwr.GmwrSelloutEfficiencyNoteMapper;
    import cloud.wconnect.workperformance.pojo.dto.gmwr.selloutefficiency.GmwrSelloutEfficiencyNoteDTO;
    import cloud.wconnect.workperformance.service.gmwr.IGmwrSelloutEfficiencyNoteService;
    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.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 - Sellout Efficiency Note 服务实现类
     * </p>
     *
     * @author zc
     * @since 2025-02-28
     */
    @Service
    @DS("work_performance")
    public class GmwrSelloutEfficiencyNoteServiceImpl extends ServiceImpl<GmwrSelloutEfficiencyNoteMapper, GmwrSelloutEfficiencyNote> implements IGmwrSelloutEfficiencyNoteService {

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

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

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

            baseMapper.insertOrUpdateBatchByUnique(noteList);
        }

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