package com.cyksj.service.relation.impl; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.cyksj.common.constant.Constant; import com.cyksj.common.exception.BusinessRuntimeException; import com.cyksj.dto.RedisKey; import com.cyksj.mapper.GoodsDonSkuMapper; import com.cyksj.mapper.GroupsMapper; import com.cyksj.mapper.GroupsRelationMapper; import com.cyksj.mapper.OrderDonMapper; import com.cyksj.model.entity.*; import com.cyksj.redis.RedisService; import com.cyksj.service.groups.GroupsFuncService; import com.cyksj.service.order.OrderDonTicketRecordService; import com.cyksj.service.relation.GroupRelationClearService; import com.cyksj.service.relation.GroupsRelationChangeService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; /** * 项目名: yhlxj2 * 文件名: GroupsRelationChangeServiceImpl * 创建者: JavaZou * 创建时间:2024/10/28 14:15 */ @Service @RequiredArgsConstructor @Slf4j public class GroupsRelationChangeServiceImpl implements GroupsRelationChangeService { private final GroupsRelationMapper relationMapper; private final RedisService redisService; private final GroupsMapper groupsMapper; private final GroupsFuncService groupsFuncService; private final GoodsDonSkuMapper skuMapper; private final OrderDonMapper orderDonMapper; private final GroupRelationClearService relationClearService; private final OrderDonTicketRecordService orderDonTicketRecordService; @Override @Transactional(rollbackFor = Throwable.class) public GroupsRelation changeTicket(Long userId, Long oriRelationId, Long itemGroupsId, Long skuId) { validateSameSku(oriRelationId, skuId); GroupsRelation relation = getRelationThisTrips(userId, itemGroupsId, 1); if (relation == null) { return relation; } validateSameSku(relation.getId(), skuId); syncGroupsRelation(oriRelationId, relation); return relation; } @Override @Transactional(rollbackFor = Throwable.class) public GroupsRelation getEmptyGroupsRelation(Long userId, Long oriRelationId, Long skuId) { validateSameSku(oriRelationId, skuId); return getEmptyGroupsRelationIfRetry(userId, oriRelationId, skuId, 1); } public GroupsRelation getEmptyGroupsRelationIfRetry(Long userId, Long oriRelationId, Long skuId, Integer retryNum) { GroupsTrips groupsTrips = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class) .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting) .eq(GroupsTrips::getSkuId, skuId) .gt(GroupsTrips::getAvailableNum, 0) .orderByAsc(GroupsTrips::getAvailableNum) .last("limit 1")); GroupsRelation relation = null; if (groupsTrips != null) { relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class) .eq(GroupsRelation::getGroupsId, groupsTrips.getId()) .eq(GroupsRelation::getStatus, GroupsRelation.Status.none) .eq(GroupsRelation::getUserId, 0) .apply("not exists (select 1 from order_don_ticket_record ticket where ticket.active_relation_id = groups_relation.id)") .last("limit 1")); } if (relation == null) { //新增空车队 GoodsDonSku sku = skuMapper.selectById(skuId); relation = groupsFuncService.createNewGroupsTrips(sku); } if (!redisService.setNx(RedisKey.GROUPS_RELATION_NUM_KEY + relation.getId(), userId, 60 * 2L)) { retryNum++; if (retryNum >= 7) { return null; } return getEmptyGroupsRelationIfRetry(userId, oriRelationId, skuId, retryNum); } Long groupsId = relation.getGroupsId(); int count = groupsMapper.decrAvailableNum(groupsId); if (count == 0) { log.error("车位异常 groupId:{}", groupsId); groupsMapper.updateAvailableNum(groupsId); throw BusinessRuntimeException.getInstance("车位异常,请重试"); } syncGroupsRelation(oriRelationId, relation); return relation; } /** * 寻找该车队空余车位 */ public GroupsRelation getRelationThisTrips(Long userId, Long groupsId, Integer retryNum) { //寻找快满编车队进行占座 GroupsRelation relation = relationMapper.selectRandomOneRelationByGroupsId(groupsId); if (relation == null) { log.error("该车队人员已满,请选择另一车队"); return null; } Long relationId = relation.getId(); if (!redisService.setNx(RedisKey.GROUPS_RELATION_NUM_KEY + relationId, userId, 60 * 2L)) { if (retryNum == 7){ log.error("该车队人员已满,请选择另一车队"); return null; } retryNum++; return getRelationThisTrips(userId, groupsId, retryNum); } int count = groupsMapper.decrAvailableNum(relation.getGroupsId()); if (count == 0) { log.error("车位异常 groupId:{}", groupsId); groupsMapper.updateAvailableNum(groupsId); log.error("车位异常"); return null; } return relation; } public void syncGroupsRelation(Long oriRelationId, GroupsRelation newRelation) { OrderDonTicketRecord multiTicket = orderDonTicketRecordService.getActiveByRelationIdForUpdate(oriRelationId); if (multiTicket != null && multiTicket.getStatus() == OrderDonTicketRecord.Status.refunding) { throw BusinessRuntimeException.getInstance("订单退款处理中,暂不支持更换车票"); } GroupsRelation oriRelation = relationMapper.selectByIdForUpdate(oriRelationId); newRelation.setStartTime(oriRelation.getStartTime()); newRelation.setExpiryTime(oriRelation.getExpiryTime()); newRelation.setStatus(oriRelation.getStatus()); newRelation.setUserId(oriRelation.getUserId()); newRelation.setYhsId(oriRelation.getYhsId()); relationMapper.updateById(newRelation); oriRelation.setNewRelationId(newRelation.getId()); relationClearService.clearTicket(oriRelation, UserTicketClearedRecord.Source.change_ticket); if (multiTicket != null) { return; } OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class) .eq(OrderDon::getRelationId, oriRelationId) .eq(OrderDon::getUserId, newRelation.getUserId()) .notIn(OrderDon::getStatus, Constant.noOrderStatus) .orderByDesc(OrderDon::getId) .last("limit 1")); if (orderDon != null) { orderDon.setRelationId(newRelation.getId()); orderDonMapper.updateById(orderDon); } } private void validateSameSku(Long relationId, Long skuId) { Long relationSkuId = relationMapper.getGroupTripsSkuIdByRelationId(relationId); if (skuId == null || relationSkuId == null || !skuId.equals(relationSkuId)) { throw BusinessRuntimeException.getInstance("仅支持更换同规格车票"); } } }