|
|
@@ -54,9 +54,13 @@ import javax.servlet.http.HttpServletRequest;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Date;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.HashSet;
|
|
|
import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
import java.util.Objects;
|
|
|
import java.util.Optional;
|
|
|
+import java.util.Set;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -196,36 +200,89 @@ public class CmsGroupRelationController {
|
|
|
SearchResult<GroupsRelationRechargeView> search = beanSearcher.search(GroupsRelationRechargeView.class, builder
|
|
|
.field(GroupsRelationRechargeView::getStatus, List.of(GroupsRelation.Status.validity.name(), GroupsRelation.Status.outside.name())).op(Operator.InList)
|
|
|
.build());
|
|
|
- search.getDataList().forEach(data -> {
|
|
|
- // Ticket-slot ownership is authoritative for multi-quantity orders. Resolve it
|
|
|
- // before the legacy relation_id lookup, otherwise an old/generated relation order
|
|
|
- // can mask the real multi-quantity parent order.
|
|
|
- OrderDon orderDon = null;
|
|
|
- OrderDonTicketRecord ticketRecord = orderDonTicketRecordMapper.selectOne(
|
|
|
- Wrappers.lambdaQuery(OrderDonTicketRecord.class)
|
|
|
- .eq(OrderDonTicketRecord::getRelationId, data.getRelationId())
|
|
|
- .eq(OrderDonTicketRecord::getStatus, OrderDonTicketRecord.Status.success)
|
|
|
- .orderByDesc(OrderDonTicketRecord::getId)
|
|
|
- .last("limit 1"));
|
|
|
- if (ticketRecord != null) {
|
|
|
- OrderDon slotOrder = orderDonMapper.selectById(ticketRecord.getOrderId());
|
|
|
- if (slotOrder != null && !Constant.noOrderAllStatus.contains(slotOrder.getStatus())) {
|
|
|
- orderDon = slotOrder;
|
|
|
- }
|
|
|
+ fillRechargeOrderNos(search.getDataList());
|
|
|
+ return GatewayResponse.SUCCESS.newBuilder().toResult(search);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Fill order numbers in batches. The old implementation issued up to three SQL statements
|
|
|
+ * for every row on the page, which made a ten-row page perform 20-30 database round trips.
|
|
|
+ */
|
|
|
+ private void fillRechargeOrderNos(List<GroupsRelationRechargeView> dataList) {
|
|
|
+ if (CollUtil.isEmpty(dataList)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Long> relationIds = dataList.stream()
|
|
|
+ .map(GroupsRelationRechargeView::getRelationId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (relationIds.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Ticket-slot ownership is authoritative. Keep only the latest successful slot per relation,
|
|
|
+ // matching the previous "order by id desc limit 1" behavior.
|
|
|
+ Map<Long, OrderDonTicketRecord> latestTicketByRelation = new HashMap<>();
|
|
|
+ orderDonTicketRecordMapper.selectList(Wrappers.lambdaQuery(OrderDonTicketRecord.class)
|
|
|
+ .select(OrderDonTicketRecord::getId, OrderDonTicketRecord::getRelationId,
|
|
|
+ OrderDonTicketRecord::getOrderId)
|
|
|
+ .in(OrderDonTicketRecord::getRelationId, relationIds)
|
|
|
+ .eq(OrderDonTicketRecord::getStatus, OrderDonTicketRecord.Status.success)
|
|
|
+ .orderByDesc(OrderDonTicketRecord::getId))
|
|
|
+ .forEach(record -> latestTicketByRelation.putIfAbsent(record.getRelationId(), record));
|
|
|
+
|
|
|
+ Set<Long> ticketOrderIds = latestTicketByRelation.values().stream()
|
|
|
+ .map(OrderDonTicketRecord::getOrderId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+ Map<Long, OrderDon> ticketOrderById = ticketOrderIds.isEmpty()
|
|
|
+ ? new HashMap<>()
|
|
|
+ : orderDonMapper.selectBatchIds(ticketOrderIds).stream()
|
|
|
+ .collect(Collectors.toMap(OrderDon::getId, order -> order, (left, right) -> left));
|
|
|
+
|
|
|
+ Set<Long> resolvedRelationIds = new HashSet<>();
|
|
|
+ dataList.forEach(data -> {
|
|
|
+ OrderDonTicketRecord ticket = latestTicketByRelation.get(data.getRelationId());
|
|
|
+ OrderDon order = ticket == null ? null : ticketOrderById.get(ticket.getOrderId());
|
|
|
+ if (order != null && !Constant.noOrderAllStatus.contains(order.getStatus())) {
|
|
|
+ data.setOrderNo(order.getOrderNo());
|
|
|
+ resolvedRelationIds.add(data.getRelationId());
|
|
|
}
|
|
|
- if (orderDon == null) {
|
|
|
- orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
|
|
|
- .eq(OrderDon::getUserId, data.getUserId())
|
|
|
- .eq(OrderDon::getRelationId, data.getRelationId())
|
|
|
+ });
|
|
|
+
|
|
|
+ List<GroupsRelationRechargeView> unresolved = dataList.stream()
|
|
|
+ .filter(data -> data.getRelationId() != null && !resolvedRelationIds.contains(data.getRelationId()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (unresolved.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Long> unresolvedRelationIds = unresolved.stream()
|
|
|
+ .map(GroupsRelationRechargeView::getRelationId).distinct().collect(Collectors.toList());
|
|
|
+ List<Long> userIds = unresolved.stream()
|
|
|
+ .map(GroupsRelationRechargeView::getUserId).filter(Objects::nonNull)
|
|
|
+ .distinct().collect(Collectors.toList());
|
|
|
+ if (userIds.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, OrderDon> latestLegacyOrder = new HashMap<>();
|
|
|
+ orderDonMapper.selectList(Wrappers.lambdaQuery(OrderDon.class)
|
|
|
+ .in(OrderDon::getRelationId, unresolvedRelationIds)
|
|
|
+ .in(OrderDon::getUserId, userIds)
|
|
|
.notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
|
|
|
- .orderByDesc(OrderDon::getId)
|
|
|
- .last("limit 1"));
|
|
|
- }
|
|
|
- if (orderDon != null) {
|
|
|
- data.setOrderNo(orderDon.getOrderNo());
|
|
|
+ .orderByDesc(OrderDon::getId))
|
|
|
+ .forEach(order -> latestLegacyOrder.putIfAbsent(
|
|
|
+ order.getRelationId() + ":" + order.getUserId(), order));
|
|
|
+
|
|
|
+ unresolved.forEach(data -> {
|
|
|
+ OrderDon order = latestLegacyOrder.get(data.getRelationId() + ":" + data.getUserId());
|
|
|
+ if (order != null) {
|
|
|
+ data.setOrderNo(order.getOrderNo());
|
|
|
}
|
|
|
});
|
|
|
- return GatewayResponse.SUCCESS.newBuilder().toResult(search);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -360,7 +417,9 @@ public class CmsGroupRelationController {
|
|
|
}
|
|
|
//扣除次数
|
|
|
Integer rechargeRemainNum = relation.getRechargeRemainNum();
|
|
|
- if (isYoutubeIndividualMember && (rechargeRemainNum == null || rechargeRemainNum < subRechargeNum)) {
|
|
|
+ // Historical tickets did not track recharge counts. A null value means quota
|
|
|
+ // management is not enabled for this ticket, so keep the legacy shipping behavior.
|
|
|
+ if (isYoutubeIndividualMember && rechargeRemainNum != null && rechargeRemainNum < subRechargeNum) {
|
|
|
throw BusinessRuntimeException.getInstance("YouTube个人会员剩余代充次数不足");
|
|
|
}
|
|
|
if (rechargeRemainNum != null && rechargeRemainNum > 0) {
|