liujie
2026-08-21 ad5db85e540947e82c7a4d5612879b3b3ecdf459
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package com.tourguide.modules.user.service;
 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tourguide.common.api.PageResponse;
import com.tourguide.common.exception.BusinessException;
import com.tourguide.modules.user.dto.GuideApplicationResponse;
import com.tourguide.modules.user.entity.GuideApplication;
import com.tourguide.modules.user.mapper.GuideApplicationMapper;
import com.tourguide.modules.system.service.GuideNotificationService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.stream.Collectors;
 
/** 管理导游入驻申请查询和一次性审核状态流转。 */
@Service
public class GuideApplicationService {
    private static final int PENDING = 0;
    private static final int APPROVED = 1;
    private static final int REJECTED = 2;
    private final GuideApplicationMapper applicationMapper;
    private final GuideUserService guideUserService;
    private final GuideNotificationService notificationService;
    private final GuideAuditSmsService auditSmsService;
 
    public GuideApplicationService(GuideApplicationMapper applicationMapper, GuideUserService guideUserService,
                                   GuideNotificationService notificationService,
                                   GuideAuditSmsService auditSmsService) {
        this.applicationMapper = applicationMapper;
        this.guideUserService = guideUserService;
        this.notificationService = notificationService;
        this.auditSmsService = auditSmsService;
    }
 
    public PageResponse<GuideApplicationResponse> page(long page, long size, String keyword, Integer auditStatus,
                                                       LocalDate startDate, LocalDate endDate) {
        LambdaQueryWrapper<GuideApplication> query = new LambdaQueryWrapper<GuideApplication>();
        if (StringUtils.hasText(keyword)) {
            String searchKeyword = keyword.trim();
            query.and(wrapper -> wrapper.like(GuideApplication::getApplicationNo, searchKeyword)
                    .or().like(GuideApplication::getRealName, searchKeyword)
                    .or().like(GuideApplication::getMobile, searchKeyword));
        }
        query.eq(auditStatus != null, GuideApplication::getAuditStatus, auditStatus)
                .ge(startDate != null, GuideApplication::getCreatedAt, startDate == null ? null : startDate.atStartOfDay())
                .lt(endDate != null, GuideApplication::getCreatedAt, endDate == null ? null : endDate.plusDays(1).atStartOfDay())
                .orderByDesc(GuideApplication::getCreatedAt);
        Page<GuideApplication> result = applicationMapper.selectPage(new Page<GuideApplication>(page, size), query);
        return new PageResponse<GuideApplicationResponse>(
                result.getRecords().stream().map(GuideApplicationResponse::from).collect(Collectors.toList()),
                result.getTotal(), result.getCurrent(), result.getSize());
    }
 
    public GuideApplicationResponse detail(Long id) {
        GuideApplication application = applicationMapper.selectById(id);
        if (application == null) { throw new BusinessException(404, "导游申请不存在"); }
        return GuideApplicationResponse.from(application);
    }
 
    @Transactional
    public GuideApplicationResponse audit(Long id, Integer auditStatus, String auditRemark, String auditor) {
        validateAudit(auditStatus, auditRemark);
        GuideApplication application = applicationMapper.selectOne(new LambdaQueryWrapper<GuideApplication>()
                .eq(GuideApplication::getId, id)
                .last("FOR UPDATE"));
        if (application == null) { throw new BusinessException(404, "导游申请不存在"); }
        if (application.getAuditStatus() == null || application.getAuditStatus() != PENDING) {
            throw new BusinessException(409, "该申请已审核,请勿重复操作");
        }
        if (auditStatus == APPROVED) guideUserService.createFromApprovedApplication(application);
        LambdaUpdateWrapper<GuideApplication> update = new LambdaUpdateWrapper<GuideApplication>()
                .eq(GuideApplication::getId, id)
                .eq(GuideApplication::getAuditStatus, PENDING)
                .set(GuideApplication::getAuditStatus, auditStatus)
                .set(GuideApplication::getAuditRemark, normalizeRemark(auditRemark))
                .set(GuideApplication::getAuditor, auditor)
                .set(GuideApplication::getAuditedAt, LocalDateTime.now());
        if (applicationMapper.update(null, update) != 1) {
            throw new BusinessException(409, "该申请已被其他管理员处理");
        }
        com.tourguide.modules.user.entity.GuideUser guide = guideUserService.findByPhone(application.getMobile());
        if (guide != null) notificationService.notifyAuditResult(guide.getId(), auditStatus == APPROVED);
        auditSmsService.send(application.getMobile(), application.getRealName(), auditStatus == APPROVED);
        return detail(id);
    }
 
    private void validateAudit(Integer auditStatus, String auditRemark) {
        if (auditStatus == null || (auditStatus != APPROVED && auditStatus != REJECTED)) {
            throw new BusinessException(400, "审核结果仅支持通过或驳回");
        }
        if (auditStatus == REJECTED && !StringUtils.hasText(auditRemark)) {
            throw new BusinessException(400, "驳回时必须填写审核备注");
        }
    }
 
    private String normalizeRemark(String auditRemark) {
        return StringUtils.hasText(auditRemark) ? auditRemark.trim() : null;
    }
}