# CbCaseNotifyUserLogServiceImpl.java

    package cloud.wconnect.finance.service.chargeback.impl;

    import cloud.wconnect.commonlib.cons.ApproveStatusEnum;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.finance.cons.chargeback.CaseErrorCons;
    import cloud.wconnect.finance.entity.chargeback.CbCase;
    import cloud.wconnect.finance.entity.chargeback.CbCaseApproveLevelUser;
    import cloud.wconnect.finance.entity.chargeback.CbCaseNotifyUserLog;
    import cloud.wconnect.finance.mapper.chargeback.CbCaseNotifyUserLogMapper;
    import cloud.wconnect.finance.service.chargeback.*;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.google.common.collect.Lists;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.util.List;
    import java.util.Objects;
    import java.util.Set;
    import java.util.stream.Collectors;

    /**
     * <p>
     * 通知用户记录表 服务实现类
     * </p>
     *
     * @author yyt
     * @since 2023-08-22
     */
    @Service
    @DS("finance")
    public class CbCaseNotifyUserLogServiceImpl extends ServiceImpl<CbCaseNotifyUserLogMapper, CbCaseNotifyUserLog> implements ICbCaseNotifyUserLogService {

        @Autowired
        private ICbCaseApproveLevelService cbCaseApproveLevelService;
        @Autowired
        private ICbCaseApproveLevelUserService cbCaseApproveLevelUserService;
        @Autowired
        private ICbCaseApproveLogService cbCaseApproveLogService;
        @Autowired
        private ICbCaseNotifyService cbCaseNotifyService;
        @Autowired
        private ICbCaseEmailConfigService cbCaseEmailConfigService;
         @Autowired
         private I18nMessageUtils i18nMessageUtils;

        /**
         * 提醒处理
         *
         * @param cs           case
         * @param propertyDTO   资产
         * @param targetUserId 处理人，为 0 时表示需要通知阶段处理人
         * @author yyt
         * @date 2023/9/1
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void notifyHandle(CbCase cs, PropertyDTO propertyDTO, int targetUserId) {
            Integer propertyId = cs.getPropertyId();
            if (!cbCaseEmailConfigService.checkNotify(cs.getPropertyId(), cbCaseEmailConfigService.getTypeForStage(cs.getStage()))) {
                throw new BadRequestException(CaseErrorCons.CB_STAGE_IS_CLOSED,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The current stage of the approval configuration is off. Please enable it before performing the operation.");
            }

            Long caseId = cs.getId();
            Integer stage = cs.getStage();
            Long batchId = cs.getBatchId();
            Long levelId = cs.getLevelId();
            Integer approveStatus = cs.getApproveStatus();
            long dateNow = DateTimeUtils.dateNowTimestamp(propertyDTO.getTimezone());
            if (targetUserId == BaseConstant.ZERO) {
                // 校验 审批状态：待送审 / 审批拒绝时，可以通知 阶段处理人
                if (!Lists.newArrayList(ApproveStatusEnum.PENDING.getStatus(), ApproveStatusEnum.REJECTED.getStatus())
                        .contains(approveStatus)) {
                    throw new BadRequestException(CommonErrorI18nConstant.STATUS_MUST_BE,
                            i18nMessageUtils.getErrorParamMapNeedTranslate(Lists.newArrayList(ApproveStatusEnum.PENDING.getDesc(), ApproveStatusEnum.REJECTED.getStatus())),
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The approvalStatus is not supported.");
                }

                // 当前阶段的 处理人
                Set<Integer> allHandleUserIds = cbCaseApproveLevelUserService.listApproveUser(propertyId, stage, levelId)
                        .stream().map(CbCaseApproveLevelUser::getUserId).collect(Collectors.toSet());
                if (CollectionUtils.isEmpty(allHandleUserIds)) {
                    throw new BadRequestException(CaseErrorCons.CB_NOTIFY_STAGE_HANDLER_FAIL,
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                            "Please configure the handler first before proceeding with the notification operation");
                }

                // 过滤出 当日未发送过的人员进行通知
                Set<Integer> alreadyNotifyUserIds = list(new QueryWrapper<CbCaseNotifyUserLog>().lambda()
                        .eq(CbCaseNotifyUserLog::getCaseId, caseId).eq(CbCaseNotifyUserLog::getStage, stage)
                        .eq(CbCaseNotifyUserLog::getBatchId, batchId).eq(CbCaseNotifyUserLog::getLevelId, levelId)
                        .eq(CbCaseNotifyUserLog::getCreatedDate, dateNow))
                        .stream().map(CbCaseNotifyUserLog::getUserId).collect(Collectors.toSet());
                if (alreadyNotifyUserIds.containsAll(allHandleUserIds)) {
                    // 一天只能通知一次
                    throw new BadRequestException(CaseErrorCons.CB_NOTIFY_REPEAT,
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                            "The same day has been notified once, do not repeat the operation");
                }

                List<Integer> notifyUserIds = allHandleUserIds.stream().filter(item -> !alreadyNotifyUserIds.contains(item))
                        .collect(Collectors.toList());
                cbCaseNotifyService.notifyHandle(cs, notifyUserIds);

                // 插入通知记录
                long nowTime = DateTimeUtils.nowTimestamp();
                saveBatch(notifyUserIds.stream().map(item -> new CbCaseNotifyUserLog().setPropertyId(propertyId)
                                .setCaseId(caseId).setStage(stage).setBatchId(batchId).setLevelId(levelId).setUserId(item)
                                .setCreatedDate(dateNow).setCreatedTime(nowTime))
                        .collect(Collectors.toList()));
            } else {
                // 校验 审批状态：审批中时，可以通知
                if (ApproveStatusEnum.APPROVEING.getStatus() != approveStatus) {
                    throw new BadRequestException(CommonErrorI18nConstant.STATUS_MUST_BE,
                             i18nMessageUtils.getErrorParamMapNeedTranslate(Lists.newArrayList(ApproveStatusEnum.APPROVEING.getDesc())),
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The approvalStatus is not supported.");
                }
                // 校验通知人 是当前阶段的审批人
                if (Objects.isNull(cbCaseApproveLevelService.getUserApproveLevel(propertyId, stage, targetUserId))) {
                    throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The notifier is not the approver");
                }
                // 校验当前用户是否已经审批过
                if (CollectionUtils.isNotEmpty(cbCaseApproveLogService.listCaseIdByCaseAndTargetUser(Lists.newArrayList(cs), targetUserId))) {
                    throw new BadRequestException(CaseErrorCons.CB_ALREADY_APPROVED,
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The notifier has already approved it. No notice required");
                }

                CbCaseNotifyUserLog notifyLog = getOne(new QueryWrapper<CbCaseNotifyUserLog>().lambda()
                        .eq(CbCaseNotifyUserLog::getCaseId, caseId).eq(CbCaseNotifyUserLog::getStage, stage)
                        .eq(CbCaseNotifyUserLog::getBatchId, batchId).eq(CbCaseNotifyUserLog::getLevelId, levelId)
                        .eq(CbCaseNotifyUserLog::getUserId, targetUserId)
                        .eq(CbCaseNotifyUserLog::getCreatedDate, dateNow));
                if (Objects.nonNull(notifyLog)) {
                    // 一天只能通知一次
                    throw new BadRequestException(CaseErrorCons.CB_NOTIFY_REPEAT,
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The same day has been notified once, do not repeat the operation");
                }

                cbCaseNotifyService.notifyHandle(cs, Lists.newArrayList(targetUserId));

                // 插入通知记录
                long nowTime = DateTimeUtils.nowTimestamp();
                save(new CbCaseNotifyUserLog().setPropertyId(propertyId).setCaseId(caseId).setStage(stage).setBatchId(batchId)
                        .setLevelId(levelId).setUserId(targetUserId).setCreatedDate(dateNow).setCreatedTime(nowTime));
            }
        }

    }