| | |
| | | import com.tourguide.modules.user.dto.GuideRegistrationTokenResponse; |
| | | import com.tourguide.modules.user.dto.SmsCodeResponse; |
| | | import com.tourguide.modules.user.entity.GuideApplication; |
| | | import com.tourguide.modules.user.entity.GuideTeam; |
| | | import com.tourguide.modules.user.mapper.GuideApplicationMapper; |
| | | import com.tourguide.modules.user.mapper.GuideTeamMapper; |
| | | import org.springframework.data.redis.core.StringRedisTemplate; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | public class GuideRegistrationService { |
| | | private static final int PENDING = 0; |
| | | private static final int APPROVED = 1; |
| | | private static final String REGISTRATION_SCENE = "registration"; |
| | | private static final Duration TOKEN_TTL = Duration.ofMinutes(30); |
| | | private static final String TOKEN_KEY_PREFIX = "tourguide:guide-registration:token:"; |
| | | private static final DateTimeFormatter APPLICATION_NO_TIME = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); |
| | |
| | | private final GuideApplicationMapper applicationMapper; |
| | | private final GuideUserService guideUserService; |
| | | private final OperationCityMapper cityMapper; |
| | | private final GuideTeamMapper teamMapper; |
| | | |
| | | public GuideRegistrationService(GuideVerificationCodeService verificationCodeService, |
| | | StringRedisTemplate redisTemplate, |
| | | GuideApplicationMapper applicationMapper, |
| | | GuideUserService guideUserService, |
| | | OperationCityMapper cityMapper) { |
| | | OperationCityMapper cityMapper, |
| | | GuideTeamMapper teamMapper) { |
| | | this.verificationCodeService = verificationCodeService; |
| | | this.redisTemplate = redisTemplate; |
| | | this.applicationMapper = applicationMapper; |
| | | this.guideUserService = guideUserService; |
| | | this.cityMapper = cityMapper; |
| | | this.teamMapper = teamMapper; |
| | | } |
| | | |
| | | public GuideRegistrationTokenResponse verifyPhone(String phone, String code) { |
| | | ensurePhoneCanRegister(phone); |
| | | verificationCodeService.verifyAndConsume(phone, code); |
| | | verificationCodeService.verifyAndConsume(phone, code, REGISTRATION_SCENE); |
| | | String token = UUID.randomUUID().toString().replace("-", ""); |
| | | redisTemplate.opsForValue().set(tokenKey(token), phone, TOKEN_TTL); |
| | | return new GuideRegistrationTokenResponse(token, TOKEN_TTL.getSeconds()); |
| | |
| | | |
| | | public SmsCodeResponse sendCode(String phone) { |
| | | ensurePhoneCanRegister(phone); |
| | | return verificationCodeService.send(phone); |
| | | return verificationCodeService.send(phone, REGISTRATION_SCENE); |
| | | } |
| | | |
| | | public String requireVerifiedPhone(String registrationToken) { |
| | |
| | | } |
| | | if (applicationMapper.selectCount(new LambdaQueryWrapper<GuideApplication>() |
| | | .eq(GuideApplication::getIdCardNo, idCardNo) |
| | | .ne(GuideApplication::getMobile, phone) |
| | | .in(GuideApplication::getAuditStatus, PENDING, APPROVED)) > 0) { |
| | | throw new BusinessException(409, "该身份证号已提交过导游申请"); |
| | | } |
| | | OperationCity city = cityMapper.selectById(request.getBankCityId()); |
| | | if (city == null || city.getStatus() == null || city.getStatus() != 1) { |
| | | throw new BusinessException(400, "开户城市未开放或已停用"); |
| | | } |
| | | OperationCity city = findEnabledBankCity(request.getBankCityId()); |
| | | GuideTeam team = findEnabledGuideTeam(request.getGuideType(), request.getTeamId()); |
| | | |
| | | GuideApplication application = new GuideApplication(); |
| | | application.setApplicationNo(buildApplicationNo()); |
| | |
| | | application.setAgeRange(normalizeOptional(request.getAgeRange())); |
| | | application.setWorkYearRange(normalizeOptional(request.getWorkYearRange())); |
| | | application.setGuideType(request.getGuideType()); |
| | | application.setTeamId(team == null ? null : team.getId()); |
| | | application.setIdCardNo(idCardNo); |
| | | application.setIdCardFrontUrl(request.getIdCardFrontUrl()); |
| | | application.setIdCardBackUrl(request.getIdCardBackUrl()); |
| | | application.setCertificateUrl(request.getGuideCertificateUrl()); |
| | | application.setQualificationCertificateUrl(normalizeOptional(request.getQualificationCertificateUrl())); |
| | | application.setCertificateValidUntil(request.getCertificateValidUntil()); |
| | | application.setBankCardNo(request.getBankCardNo()); |
| | | application.setBankCityId(city.getId()); |
| | | application.setBankCityName(city.getCityName()); |
| | | application.setBankCardNo(normalizeOptional(request.getBankCardNo())); |
| | | if (city != null) { |
| | | application.setBankCityId(city.getId()); |
| | | application.setBankCityName(city.getCityName()); |
| | | } |
| | | application.setAuditStatus(PENDING); |
| | | application.setDeleted(0); |
| | | applicationMapper.insert(application); |
| | |
| | | |
| | | private void ensurePhoneCanRegister(String phone) { |
| | | com.tourguide.modules.user.entity.GuideUser guide = guideUserService.findByPhone(phone); |
| | | if (guide != null && (guide.getStatus() == null || guide.getStatus() != 2)) { |
| | | if (guide != null && (guide.getStatus() == null |
| | | || (guide.getStatus() != GuideUserService.STATUS_PENDING |
| | | && guide.getStatus() != GuideUserService.STATUS_CANCELLED))) { |
| | | throw new BusinessException(409, "该手机号已注册为导游"); |
| | | } |
| | | if (applicationMapper.selectCount(new LambdaQueryWrapper<GuideApplication>() |
| | |
| | | return StringUtils.hasText(value) ? value.trim() : null; |
| | | } |
| | | |
| | | private OperationCity findEnabledBankCity(Long bankCityId) { |
| | | if (bankCityId == null) { |
| | | return null; |
| | | } |
| | | OperationCity city = cityMapper.selectById(bankCityId); |
| | | if (city == null || city.getStatus() == null || city.getStatus() != 1) { |
| | | throw new BusinessException(400, "开户城市未开放或已停用"); |
| | | } |
| | | return city; |
| | | } |
| | | |
| | | private GuideTeam findEnabledGuideTeam(String guideType, Long teamId) { |
| | | if ("personal".equals(guideType)) { |
| | | return null; |
| | | } |
| | | if (teamId == null) { |
| | | throw new BusinessException(400, "请选择讲解队"); |
| | | } |
| | | GuideTeam team = teamMapper.selectById(teamId); |
| | | if (team == null || team.getStatus() == null || team.getStatus() != 1) { |
| | | throw new BusinessException(400, "讲解队不存在或已停用"); |
| | | } |
| | | return team; |
| | | } |
| | | |
| | | private String tokenKey(String token) { return TOKEN_KEY_PREFIX + token; } |
| | | } |