|
|
@@ -3,10 +3,14 @@ package com.ruoyi.app.flashdelivery.service;
|
|
|
import com.ruoyi.app.order.dto.OrderPushBodyDto;
|
|
|
import com.ruoyi.app.utils.PayPush;
|
|
|
import com.ruoyi.app.utils.event.PushEventService;
|
|
|
+import com.ruoyi.common.core.domain.entity.SysDictData;
|
|
|
+import com.ruoyi.common.utils.DictUtils;
|
|
|
import com.ruoyi.framework.manager.AsyncManager;
|
|
|
import com.ruoyi.system.domain.InfoUser;
|
|
|
+import com.ruoyi.system.domain.RiderPosition;
|
|
|
import com.ruoyi.system.domain.flash.FlashDeliveryOrder;
|
|
|
import com.ruoyi.system.mapper.InfoUserMapper;
|
|
|
+import com.ruoyi.system.mapper.RiderPositionMapper;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
@@ -14,15 +18,17 @@ import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.support.TransactionSynchronization;
|
|
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
|
|
|
|
|
+import java.util.List;
|
|
|
import java.util.TimerTask;
|
|
|
|
|
|
import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.ACCEPTED;
|
|
|
import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.CANCELLED;
|
|
|
import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.DELIVERED;
|
|
|
import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.PICKED_UP;
|
|
|
+import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.WAITING_ACCEPTANCE;
|
|
|
|
|
|
/**
|
|
|
- * 闪送订单状态变更后的消息推送:履约事件(接单、取件、送达)推寄件用户,取消事件推接单骑手。
|
|
|
+ * 闪送订单消息推送:可抢新单推符合条件的骑手,履约事件推寄件用户,取消事件推接单骑手。
|
|
|
* 推送统一在事务提交后异步执行,失败仅记日志,不影响订单状态流转本身。
|
|
|
*/
|
|
|
@Service
|
|
|
@@ -34,18 +40,27 @@ public class FlashDeliveryNotificationService {
|
|
|
private static final String CONTENT_PICKED_UP = "no.message.push.delivery.personnel.qspsz.order";
|
|
|
private static final String CONTENT_DELIVERED = "no.message.push.delivery.personnel.qsysd.order";
|
|
|
private static final String CONTENT_CANCELLED = "no.message.push.order.cancelled";
|
|
|
+ private static final String CONTENT_AVAILABLE = "no.message.push.new.flash.order";
|
|
|
+ private static final int RIDER_NOTIFICATION_LIMIT = 20;
|
|
|
/** 推送 payload 的业务类型:1=外卖、2=充值,3=闪送。 */
|
|
|
private static final int PUSH_TYPE_FLASH = 3;
|
|
|
- /** -1 表示非语音提醒(0 仅用于外卖骑手新单语音)。 */
|
|
|
+ /** -1 表示非语音提醒;0 表示骑手新单提醒。 */
|
|
|
private static final int PUSH_PAYLOAD_TYPE_NONE = -1;
|
|
|
|
|
|
private final InfoUserMapper userMapper;
|
|
|
private final PushEventService pushEventService;
|
|
|
+ private final RiderPositionMapper riderPositionMapper;
|
|
|
|
|
|
- @Autowired
|
|
|
public FlashDeliveryNotificationService(InfoUserMapper userMapper, PushEventService pushEventService) {
|
|
|
+ this(userMapper, pushEventService, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ public FlashDeliveryNotificationService(InfoUserMapper userMapper, PushEventService pushEventService,
|
|
|
+ RiderPositionMapper riderPositionMapper) {
|
|
|
this.userMapper = userMapper;
|
|
|
this.pushEventService = pushEventService;
|
|
|
+ this.riderPositionMapper = riderPositionMapper;
|
|
|
}
|
|
|
|
|
|
/** 按订单取寄件用户;订单或用户缺失时静默跳过。 */
|
|
|
@@ -80,9 +95,14 @@ public class FlashDeliveryNotificationService {
|
|
|
|
|
|
/** 向接单骑手推送指定状态文案;与用户端一致,失败仅记日志。 */
|
|
|
void sendToRider(InfoUser recipient, FlashDeliveryOrder order, String status, String contentKey) {
|
|
|
+ sendToRider(recipient, order, status, contentKey, PUSH_PAYLOAD_TYPE_NONE);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void sendToRider(InfoUser recipient, FlashDeliveryOrder order, String status,
|
|
|
+ String contentKey, int payloadType) {
|
|
|
if (recipient == null || recipient.getUserId() == null) return;
|
|
|
String orderNo = order.getOrderNo();
|
|
|
- String body = OrderPushBodyDto.getJson(orderNo, status, PUSH_PAYLOAD_TYPE_NONE, PUSH_TYPE_FLASH);
|
|
|
+ String body = OrderPushBodyDto.getJson(orderNo, status, payloadType, PUSH_TYPE_FLASH);
|
|
|
AsyncManager.me().execute(new TimerTask() {
|
|
|
@Override
|
|
|
public void run() {
|
|
|
@@ -96,6 +116,33 @@ public class FlashDeliveryNotificationService {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ /** 向一名可接单骑手发送闪送新单提醒;type=0 保留骑手端新单语音语义。 */
|
|
|
+ void sendAvailableOrderToRider(RiderPosition rider, FlashDeliveryOrder order) {
|
|
|
+ if (rider == null || rider.getRiderId() == null) return;
|
|
|
+ InfoUser recipient = new InfoUser();
|
|
|
+ recipient.setUserId(rider.getRiderId());
|
|
|
+ recipient.setCid(rider.getCid());
|
|
|
+ sendToRider(recipient, order, WAITING_ACCEPTANCE, CONTENT_AVAILABLE, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 订单已向骑手开放后,通知附近最多 20 名符合闪送接单条件的骑手。 */
|
|
|
+ public void notifyAvailable(FlashDeliveryOrder order) {
|
|
|
+ if (order == null || riderPositionMapper == null || !WAITING_ACCEPTANCE.equals(order.getStatus())
|
|
|
+ || !Boolean.TRUE.equals(order.getIsDisplay()) || order.getRiderId() != null
|
|
|
+ || order.getPickupLongitude() == null || order.getPickupLatitude() == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ runAfterCommit(() -> {
|
|
|
+ int vehicleType = Integer.valueOf(2).equals(order.getVehicleType()) ? 2 : 1;
|
|
|
+ List<RiderPosition> riders = riderPositionMapper.getFlashRiderNotificationList(
|
|
|
+ order.getPickupLongitude(), order.getPickupLatitude(), vehicleType,
|
|
|
+ order.getDeliveryType(), newTaskDistanceLimit(), RIDER_NOTIFICATION_LIMIT);
|
|
|
+ if (riders != null) {
|
|
|
+ riders.forEach(rider -> sendAvailableOrderToRider(rider, order));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
/** 骑手抢单成功后通知寄件用户;未解析到寄件用户时跳过。 */
|
|
|
public void notifyAccepted(FlashDeliveryOrder order) {
|
|
|
runAfterCommit(() -> {
|
|
|
@@ -141,4 +188,17 @@ public class FlashDeliveryNotificationService {
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
+
|
|
|
+ private Integer newTaskDistanceLimit() {
|
|
|
+ try {
|
|
|
+ List<SysDictData> values = DictUtils.getDictCache("sys_qs_newtask_distance");
|
|
|
+ if (values != null && !values.isEmpty()) {
|
|
|
+ int limit = Integer.parseInt(values.get(0).getDictValue());
|
|
|
+ return limit > 0 ? limit : null;
|
|
|
+ }
|
|
|
+ } catch (Exception ignored) {
|
|
|
+ // 与骑手新任务列表保持一致:缺失或非法配置时不限制距离。
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
}
|