|
@@ -12,25 +12,16 @@ import com.ylx.common.core.domain.R;
|
|
|
import com.ylx.common.core.domain.entity.SysDictData;
|
|
import com.ylx.common.core.domain.entity.SysDictData;
|
|
|
import com.ylx.common.core.domain.model.WxLoginUser;
|
|
import com.ylx.common.core.domain.model.WxLoginUser;
|
|
|
import com.ylx.common.exception.ServiceException;
|
|
import com.ylx.common.exception.ServiceException;
|
|
|
-import com.ylx.common.utils.DateUtils;
|
|
|
|
|
-import com.ylx.common.utils.DictUtils;
|
|
|
|
|
-import com.ylx.common.utils.SecurityUtils;
|
|
|
|
|
-import com.ylx.common.utils.StringUtils;
|
|
|
|
|
|
|
+import com.ylx.common.utils.*;
|
|
|
import com.ylx.common.weixinPay.enums.WxPayTypeEnum;
|
|
import com.ylx.common.weixinPay.enums.WxPayTypeEnum;
|
|
|
import com.ylx.common.weixinPay.service.WxPayV3Service;
|
|
import com.ylx.common.weixinPay.service.WxPayV3Service;
|
|
|
-import com.ylx.massage.domain.MaProject;
|
|
|
|
|
-import com.ylx.massage.domain.MaTechnician;
|
|
|
|
|
-import com.ylx.massage.domain.TAddress;
|
|
|
|
|
-import com.ylx.massage.domain.TWxUser;
|
|
|
|
|
|
|
+import com.ylx.massage.domain.*;
|
|
|
import com.ylx.massage.domain.vo.HomeBlock;
|
|
import com.ylx.massage.domain.vo.HomeBlock;
|
|
|
import com.ylx.massage.domain.vo.OrderVerificationVo;
|
|
import com.ylx.massage.domain.vo.OrderVerificationVo;
|
|
|
import com.ylx.massage.domain.vo.TechnicianAvailabilityVo;
|
|
import com.ylx.massage.domain.vo.TechnicianAvailabilityVo;
|
|
|
import com.ylx.massage.mapper.MaProjectMapper;
|
|
import com.ylx.massage.mapper.MaProjectMapper;
|
|
|
import com.ylx.massage.mapper.MaTechnicianMapper;
|
|
import com.ylx.massage.mapper.MaTechnicianMapper;
|
|
|
-import com.ylx.massage.service.CouponService;
|
|
|
|
|
-import com.ylx.massage.service.IMaTechnicianService;
|
|
|
|
|
-import com.ylx.massage.service.TAddressService;
|
|
|
|
|
-import com.ylx.massage.service.TWxUserService;
|
|
|
|
|
|
|
+import com.ylx.massage.service.*;
|
|
|
import com.ylx.massage.utils.OrderNumberGenerator;
|
|
import com.ylx.massage.utils.OrderNumberGenerator;
|
|
|
import com.ylx.message.enums.TriggerEventEnum;
|
|
import com.ylx.message.enums.TriggerEventEnum;
|
|
|
import com.ylx.message.service.IMessageService;
|
|
import com.ylx.message.service.IMessageService;
|
|
@@ -120,6 +111,8 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
|
|
|
private IMessageService messageService;
|
|
private IMessageService messageService;
|
|
|
|
|
|
|
|
private static final int NOT_DELETE = 0;
|
|
private static final int NOT_DELETE = 0;
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private TGeoFenceService geoFenceService;
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public TOrder addOrder(TOrder order) {
|
|
public TOrder addOrder(TOrder order) {
|
|
@@ -554,16 +547,16 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
|
|
|
order.setPaymentMethod(dto.getPaymentMethod());
|
|
order.setPaymentMethod(dto.getPaymentMethod());
|
|
|
|
|
|
|
|
// 经纬度安全赋值
|
|
// 经纬度安全赋值
|
|
|
- order.setUserLatitude(new BigDecimal(address.getLatitude()));
|
|
|
|
|
- order.setUserLongitude(new BigDecimal(address.getLongitude()));
|
|
|
|
|
|
|
+ order.setUserLatitude(address.getLatitude());
|
|
|
|
|
+ order.setUserLongitude(address.getLongitude());
|
|
|
|
|
|
|
|
merchantAddressList.stream().filter(a -> a.getType() == 1).findFirst().ifPresent(addr -> {
|
|
merchantAddressList.stream().filter(a -> a.getType() == 1).findFirst().ifPresent(addr -> {
|
|
|
- order.setMerchantLongitude(new BigDecimal(addr.getLongitude()));
|
|
|
|
|
- order.setMerchantLatitude(new BigDecimal(addr.getLatitude()));
|
|
|
|
|
|
|
+ order.setMerchantLongitude(addr.getLongitude());
|
|
|
|
|
+ order.setMerchantLatitude(addr.getLatitude());
|
|
|
});
|
|
});
|
|
|
merchantAddressList.stream().filter(a -> a.getType() == 2).findFirst().ifPresent(addr -> {
|
|
merchantAddressList.stream().filter(a -> a.getType() == 2).findFirst().ifPresent(addr -> {
|
|
|
- order.setVirtualLongitude(new BigDecimal(addr.getLongitude()));
|
|
|
|
|
- order.setVirtualLatitude(new BigDecimal(addr.getLatitude()));
|
|
|
|
|
|
|
+ order.setVirtualLongitude(addr.getLongitude());
|
|
|
|
|
+ order.setVirtualLatitude(addr.getLatitude());
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// 设置支付状态
|
|
// 设置支付状态
|
|
@@ -905,19 +898,88 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
|
|
|
.eq(TAddress::getIsDefault, 1)
|
|
.eq(TAddress::getIsDefault, 1)
|
|
|
.eq(TAddress::getIsDelete, NOT_DELETE));
|
|
.eq(TAddress::getIsDelete, NOT_DELETE));
|
|
|
if (CollUtil.isEmpty(merchantAddressList)) {
|
|
if (CollUtil.isEmpty(merchantAddressList)) {
|
|
|
- throw new ServiceException("商户地址不存在");
|
|
|
|
|
|
|
+ throw new ServiceException("商户地址不存在,请先完善商户地址");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- TAddress address = CollUtil.getFirst(merchantAddressList);
|
|
|
|
|
- dto.setLongitude(address.getLongitude());
|
|
|
|
|
- dto.setLatitude(address.getLatitude());
|
|
|
|
|
|
|
+ TAddress merchantAddress = CollUtil.getFirst(merchantAddressList);
|
|
|
|
|
+ BigDecimal merchantLat = merchantAddress.getLatitude();
|
|
|
|
|
+ BigDecimal merchantLon = merchantAddress.getLongitude();
|
|
|
|
|
+
|
|
|
|
|
+ // 商户坐标为空拦截
|
|
|
|
|
+ if (ObjectUtil.hasNull(merchantLat, merchantLon)) {
|
|
|
|
|
+ log.warn("商户id:{} 默认地址经纬度为空,无法计算围栏距离", userId);
|
|
|
|
|
+ dto.setLatitude(null);
|
|
|
|
|
+ dto.setLongitude(null);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dto.setLatitude(merchantLat);
|
|
|
|
|
+ dto.setLongitude(merchantLon);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
page = this.baseMapper.queryMerchantOrderList(page, dto);
|
|
page = this.baseMapper.queryMerchantOrderList(page, dto);
|
|
|
|
|
+ List<OrderPageVO> records = page.getRecords();
|
|
|
|
|
+ if (CollUtil.isEmpty(records)) {
|
|
|
|
|
+ return page;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 获取所有有效的地理围栏
|
|
|
|
|
+ List<TGeoFence> validFenceList = geoFenceService.selectValidFences(dto.getCityCode());
|
|
|
|
|
+ if (CollUtil.isEmpty(validFenceList)) {
|
|
|
|
|
+ log.info("城市编码{}无有效地理围栏,全部订单非高风险", dto.getCityCode());
|
|
|
|
|
+ for (OrderPageVO vo : records) {
|
|
|
|
|
+ vo.setIsHighRiskArea(false);
|
|
|
|
|
+ }
|
|
|
|
|
+ return page;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 遍历订单,在内存中进行空间计算
|
|
|
|
|
+ for (OrderPageVO orderVO : records) {
|
|
|
|
|
+ BigDecimal userLat = orderVO.getUserLatitude();
|
|
|
|
|
+ BigDecimal userLon = orderVO.getUserLongitude();
|
|
|
|
|
+ // 用户坐标为空,跳过计算
|
|
|
|
|
+ if (ObjectUtil.hasNull(userLat, userLon)) {
|
|
|
|
|
+ orderVO.setIsHighRiskArea(false);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (ObjectUtil.isNotNull(page) && CollUtil.isNotEmpty(page.getRecords())) {
|
|
|
|
|
- List<OrderPageVO> records = page.getRecords();
|
|
|
|
|
- for (OrderPageVO record : records) {
|
|
|
|
|
- this.fillCurrentAfterSaleInfo(record, record.getId());
|
|
|
|
|
|
|
+ // 存储最小距离、对应围栏、是否命中风险圈
|
|
|
|
|
+ BigDecimal minDistanceKm = null;
|
|
|
|
|
+ TGeoFence nearestFence = null;
|
|
|
|
|
+
|
|
|
|
|
+ for (TGeoFence fence : validFenceList) {
|
|
|
|
|
+ BigDecimal fenceLat = fence.getLatitude();
|
|
|
|
|
+ BigDecimal fenceLon = fence.getLongitude();
|
|
|
|
|
+ BigDecimal radiusKm = fence.getRadiusKm();
|
|
|
|
|
+ // 围栏坐标/半径非法则跳过当前围栏
|
|
|
|
|
+ if (ObjectUtil.hasNull(fenceLat, fenceLon, radiusKm)
|
|
|
|
|
+ || radiusKm.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 【修复】传参顺序:用户纬度、用户经度,围栏纬度、围栏经度
|
|
|
|
|
+ BigDecimal distKm = DistanceUtil.formatDistanceInKilometers(userLat, userLon, fenceLat, fenceLon);
|
|
|
|
|
+ // 距离非法跳过
|
|
|
|
|
+ if (ObjectUtil.isNull(distKm)) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 更新全局最小距离围栏
|
|
|
|
|
+ if (ObjectUtil.isNull(minDistanceKm) || distKm.compareTo(minDistanceKm) < 0) {
|
|
|
|
|
+ minDistanceKm = distKm;
|
|
|
|
|
+ nearestFence = fence;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 赋值VO
|
|
|
|
|
+ if (ObjectUtil.isNull(minDistanceKm) || ObjectUtil.isNull(nearestFence)) {
|
|
|
|
|
+ orderVO.setIsHighRiskArea(false);
|
|
|
|
|
+ orderVO.setDistanceKm(null);
|
|
|
|
|
+ orderVO.setFenceIntro(null);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ orderVO.setDistanceKm(minDistanceKm);
|
|
|
|
|
+ // 判断是否在围栏半径内
|
|
|
|
|
+ int compare = minDistanceKm.compareTo(nearestFence.getRadiusKm());
|
|
|
|
|
+ orderVO.setIsHighRiskArea(compare <= 0);
|
|
|
|
|
+ orderVO.setFenceIntro(nearestFence.getFenceIntro());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|