|
@@ -19,6 +19,7 @@ import com.ruoyi.common.utils.StringUtils;
|
|
|
import com.ruoyi.system.domain.InfoUser;
|
|
import com.ruoyi.system.domain.InfoUser;
|
|
|
import com.ruoyi.system.domain.flash.*;
|
|
import com.ruoyi.system.domain.flash.*;
|
|
|
import com.ruoyi.system.mapper.InfoUserMapper;
|
|
import com.ruoyi.system.mapper.InfoUserMapper;
|
|
|
|
|
+import com.ruoyi.system.service.PaymentMethodGateService;
|
|
|
import com.ruoyi.system.mapper.flash.*;
|
|
import com.ruoyi.system.mapper.flash.*;
|
|
|
import org.springframework.dao.DataIntegrityViolationException;
|
|
import org.springframework.dao.DataIntegrityViolationException;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
@@ -70,6 +71,8 @@ public class FlashDeliveryApplicationService {
|
|
|
private final FlashDeliveryPricingCalculator pricingCalculator;
|
|
private final FlashDeliveryPricingCalculator pricingCalculator;
|
|
|
private final RiderDeliveryLockService riderDeliveryLockService;
|
|
private final RiderDeliveryLockService riderDeliveryLockService;
|
|
|
private final RiderDeliveryExclusivityService riderDeliveryExclusivityService;
|
|
private final RiderDeliveryExclusivityService riderDeliveryExclusivityService;
|
|
|
|
|
+ /** 支付方式闸门(031):闪送下单校验与抢单过滤的唯一判定来源。 */
|
|
|
|
|
+ private final PaymentMethodGateService paymentMethodGateService;
|
|
|
|
|
|
|
|
public FlashDeliveryApplicationService(FlashDeliveryOrderMapper orderMapper,
|
|
public FlashDeliveryApplicationService(FlashDeliveryOrderMapper orderMapper,
|
|
|
FlashDeliveryPricingMapper pricingMapper,
|
|
FlashDeliveryPricingMapper pricingMapper,
|
|
@@ -79,7 +82,8 @@ public class FlashDeliveryApplicationService {
|
|
|
FlashDeliveryRouteService routeService,
|
|
FlashDeliveryRouteService routeService,
|
|
|
FlashDeliveryPricingCalculator pricingCalculator,
|
|
FlashDeliveryPricingCalculator pricingCalculator,
|
|
|
RiderDeliveryLockService riderDeliveryLockService,
|
|
RiderDeliveryLockService riderDeliveryLockService,
|
|
|
- RiderDeliveryExclusivityService riderDeliveryExclusivityService) {
|
|
|
|
|
|
|
+ RiderDeliveryExclusivityService riderDeliveryExclusivityService,
|
|
|
|
|
+ PaymentMethodGateService paymentMethodGateService) {
|
|
|
this.orderMapper = orderMapper;
|
|
this.orderMapper = orderMapper;
|
|
|
this.pricingMapper = pricingMapper;
|
|
this.pricingMapper = pricingMapper;
|
|
|
this.imageMapper = imageMapper;
|
|
this.imageMapper = imageMapper;
|
|
@@ -89,6 +93,7 @@ public class FlashDeliveryApplicationService {
|
|
|
this.pricingCalculator = pricingCalculator;
|
|
this.pricingCalculator = pricingCalculator;
|
|
|
this.riderDeliveryLockService = riderDeliveryLockService;
|
|
this.riderDeliveryLockService = riderDeliveryLockService;
|
|
|
this.riderDeliveryExclusivityService = riderDeliveryExclusivityService;
|
|
this.riderDeliveryExclusivityService = riderDeliveryExclusivityService;
|
|
|
|
|
+ this.paymentMethodGateService = paymentMethodGateService;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 闪送首页:返回开放的业务场景、配送等级,以及当前时段各服务的公开运价摘要。 */
|
|
/** 闪送首页:返回开放的业务场景、配送等级,以及当前时段各服务的公开运价摘要。 */
|
|
@@ -99,6 +104,9 @@ public class FlashDeliveryApplicationService {
|
|
|
FlashDeliveryPricing pricing = findPricingAtOrNull(pricingTargetTime(new Date()));
|
|
FlashDeliveryPricing pricing = findPricingAtOrNull(pricingTargetTime(new Date()));
|
|
|
view.setServices(pricing == null ? List.of() : SERVICE_TYPES.stream()
|
|
view.setServices(pricing == null ? List.of() : SERVICE_TYPES.stream()
|
|
|
.map(serviceType -> serviceView(pricing, serviceType)).toList());
|
|
.map(serviceType -> serviceView(pricing, serviceType)).toList());
|
|
|
|
|
+ // 031:首页返回闪送维度可选支付方式(平台开关开放集合),App 下单渲染用
|
|
|
|
|
+ view.setPayMethods(paymentMethodGateService.listAvailable(
|
|
|
|
|
+ PaymentMethodGateService.GateScope.RIDER_FLASH, null, null));
|
|
|
return view;
|
|
return view;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -132,6 +140,9 @@ public class FlashDeliveryApplicationService {
|
|
|
applyBreakdown(view, context.breakdown());
|
|
applyBreakdown(view, context.breakdown());
|
|
|
view.setCurrency("TWD");
|
|
view.setCurrency("TWD");
|
|
|
view.setPricingVersion(context.pricing().getConfigVersion());
|
|
view.setPricingVersion(context.pricing().getConfigVersion());
|
|
|
|
|
+ // 031:报价响应同样携带可选支付方式,与首页同源
|
|
|
|
|
+ view.setPayMethods(paymentMethodGateService.listAvailable(
|
|
|
|
|
+ PaymentMethodGateService.GateScope.RIDER_FLASH, null, null));
|
|
|
return view;
|
|
return view;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -406,6 +417,8 @@ public class FlashDeliveryApplicationService {
|
|
|
public FlashDeliveryRiderOrderPageView riderOrders(Long riderId, int pageNum, int pageSize,
|
|
public FlashDeliveryRiderOrderPageView riderOrders(Long riderId, int pageNum, int pageSize,
|
|
|
String tab, BigDecimal longitude, BigDecimal latitude) {
|
|
String tab, BigDecimal longitude, BigDecimal latitude) {
|
|
|
InfoUser rider = requireRider(riderId);
|
|
InfoUser rider = requireRider(riderId);
|
|
|
|
|
+ // 031:骑手接受的支付方式集合(未设置=平台开放全部),newTask 页签按此过滤
|
|
|
|
|
+ Set<String> acceptedPayTypes = acceptedRiderPayTypes(rider);
|
|
|
if (!hasText(tab)) throw fail("flash.delivery.tab.invalid");
|
|
if (!hasText(tab)) throw fail("flash.delivery.tab.invalid");
|
|
|
String selectedTab = tab.trim();
|
|
String selectedTab = tab.trim();
|
|
|
// lambda 无法捕获被重新赋值的参数,统一改用仅 newTask 携带坐标的有效变量。
|
|
// lambda 无法捕获被重新赋值的参数,统一改用仅 newTask 携带坐标的有效变量。
|
|
@@ -417,7 +430,7 @@ public class FlashDeliveryApplicationService {
|
|
|
validateRiderCoordinates(effectiveLongitude, effectiveLatitude);
|
|
validateRiderCoordinates(effectiveLongitude, effectiveLatitude);
|
|
|
}
|
|
}
|
|
|
QueryWrapper<FlashDeliveryOrder> query = riderOrdersQuery(riderId, selectedTab,
|
|
QueryWrapper<FlashDeliveryOrder> query = riderOrdersQuery(riderId, selectedTab,
|
|
|
- effectiveLongitude, effectiveLatitude, true);
|
|
|
|
|
|
|
+ effectiveLongitude, effectiveLatitude, true, acceptedPayTypes);
|
|
|
IPage<FlashDeliveryOrder> orders = orderMapper.selectPage(page(pageNum, pageSize), query);
|
|
IPage<FlashDeliveryOrder> orders = orderMapper.selectPage(page(pageNum, pageSize), query);
|
|
|
FlashDeliveryRiderOrderPageView result = new FlashDeliveryRiderOrderPageView();
|
|
FlashDeliveryRiderOrderPageView result = new FlashDeliveryRiderOrderPageView();
|
|
|
result.setRecords(orders.getRecords().stream()
|
|
result.setRecords(orders.getRecords().stream()
|
|
@@ -428,7 +441,7 @@ public class FlashDeliveryApplicationService {
|
|
|
if ("newTask".equals(selectedTab)) {
|
|
if ("newTask".equals(selectedTab)) {
|
|
|
result.setNearbyTaskCount(orders.getTotal());
|
|
result.setNearbyTaskCount(orders.getTotal());
|
|
|
QueryWrapper<FlashDeliveryOrder> maximumQuery = riderOrdersQuery(riderId, selectedTab,
|
|
QueryWrapper<FlashDeliveryOrder> maximumQuery = riderOrdersQuery(riderId, selectedTab,
|
|
|
- effectiveLongitude, effectiveLatitude, false)
|
|
|
|
|
|
|
+ effectiveLongitude, effectiveLatitude, false, acceptedPayTypes)
|
|
|
.select("MAX(amount)");
|
|
.select("MAX(amount)");
|
|
|
result.setHighestOrderAmount(firstLong(orderMapper.selectObjs(maximumQuery)));
|
|
result.setHighestOrderAmount(firstLong(orderMapper.selectObjs(maximumQuery)));
|
|
|
}
|
|
}
|
|
@@ -1107,13 +1120,15 @@ public class FlashDeliveryApplicationService {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /** 支付方式与主订单系统同域(4=现金、6=线下转账);闪送款项直达骑手,仅允许线下方式,缺省现金,下单后锁定。 */
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 支付方式经 031 闸门校验(闪送维度仅平台开关层——抢单前无收款方),
|
|
|
|
|
+ * 缺省现金 4;取代原先注释掉的白名单硬编码,改由平台配置管控(spec FR-004)。
|
|
|
|
|
+ */
|
|
|
private String normalizePayType(String payType) {
|
|
private String normalizePayType(String payType) {
|
|
|
- if (!hasText(payType)) return PAY_TYPE_CASH;
|
|
|
|
|
- String trimmed = payType.trim();
|
|
|
|
|
- return trimmed;
|
|
|
|
|
-// if (PAY_TYPE_CASH.equals(trimmed) || PAY_TYPE_TRANSFER.equals(trimmed)) return trimmed;
|
|
|
|
|
-// throw fail("flash.delivery.pay.type.invalid");
|
|
|
|
|
|
|
+ String value = hasText(payType) ? payType.trim() : PAY_TYPE_CASH;
|
|
|
|
|
+ paymentMethodGateService.assertUsable(value,
|
|
|
|
|
+ PaymentMethodGateService.GateScope.RIDER_FLASH, null, null);
|
|
|
|
|
+ return value;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 将时间转为台北时区 HH:mm,用于命中运价时段。 */
|
|
/** 将时间转为台北时区 HH:mm,用于命中运价时段。 */
|
|
@@ -1156,7 +1171,8 @@ public class FlashDeliveryApplicationService {
|
|
|
/** 按页签构建骑手任务查询:newTask 限定可抢状态与时间窗,可选距离过滤和就近排序。 */
|
|
/** 按页签构建骑手任务查询:newTask 限定可抢状态与时间窗,可选距离过滤和就近排序。 */
|
|
|
private QueryWrapper<FlashDeliveryOrder> riderOrdersQuery(Long riderId, String tab,
|
|
private QueryWrapper<FlashDeliveryOrder> riderOrdersQuery(Long riderId, String tab,
|
|
|
BigDecimal longitude, BigDecimal latitude,
|
|
BigDecimal longitude, BigDecimal latitude,
|
|
|
- boolean orderResults) {
|
|
|
|
|
|
|
+ boolean orderResults,
|
|
|
|
|
+ Set<String> acceptedPayTypes) {
|
|
|
QueryWrapper<FlashDeliveryOrder> query = new QueryWrapper<>();
|
|
QueryWrapper<FlashDeliveryOrder> query = new QueryWrapper<>();
|
|
|
Date now = new Date();
|
|
Date now = new Date();
|
|
|
switch (tab) {
|
|
switch (tab) {
|
|
@@ -1164,6 +1180,12 @@ public class FlashDeliveryApplicationService {
|
|
|
query.eq("status", WAITING_ACCEPTANCE).isNull("rider_id")
|
|
query.eq("status", WAITING_ACCEPTANCE).isNull("rider_id")
|
|
|
.and(item -> item.eq("delivery_mode", "NOW")
|
|
.and(item -> item.eq("delivery_mode", "NOW")
|
|
|
.or().le("scheduled_pickup_start_at", now));
|
|
.or().le("scheduled_pickup_start_at", now));
|
|
|
|
|
+ // 031:只展示骑手接受其支付方式的订单(现金单恒可见,见 acceptedRiderPayTypes)
|
|
|
|
|
+ if (acceptedPayTypes.isEmpty()) {
|
|
|
|
|
+ query.apply("1 = 0");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ query.in("pay_type", acceptedPayTypes);
|
|
|
|
|
+ }
|
|
|
if (longitude != null) {
|
|
if (longitude != null) {
|
|
|
Integer limitKm = newTaskDistanceLimit();
|
|
Integer limitKm = newTaskDistanceLimit();
|
|
|
if (limitKm != null) {
|
|
if (limitKm != null) {
|
|
@@ -1200,6 +1222,32 @@ public class FlashDeliveryApplicationService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 校验骑手坐标:经纬度必须成对出现且在合法范围。 */
|
|
/** 校验骑手坐标:经纬度必须成对出现且在合法范围。 */
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 骑手接受的支付方式展开为 payType 集合。
|
|
|
|
|
+ * 未设置(NULL)=平台闪送维度开放的全部组;现金 4 不纳入管控但闪送现金单恒可见,
|
|
|
|
|
+ * 因此始终并入集合(与闸门对现金直接放行的口径一致)。
|
|
|
|
|
+ */
|
|
|
|
|
+ private Set<String> acceptedRiderPayTypes(InfoUser rider) {
|
|
|
|
|
+ String csv = rider.getFlashPayMethods();
|
|
|
|
|
+ List<String> groups = new ArrayList<>();
|
|
|
|
|
+ if (csv == null || csv.trim().isEmpty()) {
|
|
|
|
|
+ for (PaymentMethodGateService.PayMethodOption option : paymentMethodGateService.listAvailable(
|
|
|
|
|
+ PaymentMethodGateService.GateScope.RIDER_FLASH, null, null)) {
|
|
|
|
|
+ if (!groups.contains(option.getMethodCode())) groups.add(option.getMethodCode());
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for (String part : csv.split(",")) {
|
|
|
|
|
+ if (!part.trim().isEmpty()) groups.add(part.trim());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ Set<String> payTypes = new LinkedHashSet<>();
|
|
|
|
|
+ payTypes.add(PAY_TYPE_CASH);
|
|
|
|
|
+ for (String group : groups) {
|
|
|
|
|
+ payTypes.addAll(PaymentMethodGateService.payTypesOf(group));
|
|
|
|
|
+ }
|
|
|
|
|
+ return payTypes;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private void validateRiderCoordinates(BigDecimal longitude, BigDecimal latitude) {
|
|
private void validateRiderCoordinates(BigDecimal longitude, BigDecimal latitude) {
|
|
|
if ((longitude == null) != (latitude == null)
|
|
if ((longitude == null) != (latitude == null)
|
|
|
|| longitude != null && (longitude.compareTo(BigDecimal.valueOf(-180)) < 0
|
|
|| longitude != null && (longitude.compareTo(BigDecimal.valueOf(-180)) < 0
|