|
|
@@ -1,11 +1,140 @@
|
|
|
package com.ylx.fareSetting.service.impl;
|
|
|
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.util.CoordinateUtil;
|
|
|
+import cn.hutool.core.util.NumberUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.ylx.common.exception.ServiceException;
|
|
|
import com.ylx.fareSetting.domian.MaProjectFareSetting;
|
|
|
+import com.ylx.fareSetting.domian.dto.FareCalculateDTO;
|
|
|
+import com.ylx.fareSetting.domian.vo.FareCalculateResultVO;
|
|
|
import com.ylx.fareSetting.mapper.MaProjectFareSettingMapper;
|
|
|
import com.ylx.fareSetting.service.IMaProjectFareSettingService;
|
|
|
+import com.ylx.massage.domain.TAddress;
|
|
|
+import com.ylx.massage.domain.vo.TFareSettingVo;
|
|
|
+import com.ylx.massage.service.TAddressService;
|
|
|
+import com.ylx.massage.service.TFareSettingService;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalTime;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Optional;
|
|
|
+
|
|
|
+
|
|
|
+@Slf4j
|
|
|
@Service
|
|
|
public class MaProjectFareSettingServiceImpl extends ServiceImpl<MaProjectFareSettingMapper, MaProjectFareSetting> implements IMaProjectFareSettingService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private TFareSettingService fareSettingService;
|
|
|
+ @Resource
|
|
|
+ private TAddressService addressService;
|
|
|
+
|
|
|
+ public FareCalculateResultVO calculateFare(FareCalculateDTO dto) {
|
|
|
+ FareCalculateResultVO result = new FareCalculateResultVO();
|
|
|
+
|
|
|
+ // 1.获取商户的默认地址
|
|
|
+ TAddress address = this.addressService.getOne(new LambdaQueryWrapper<TAddress>().eq(TAddress::getMerchantId, dto.getMerchantId()).eq(TAddress::getType, 1));
|
|
|
+ if (ObjectUtil.isNull(address)) {
|
|
|
+ throw new ServiceException("无法获取商户的默认地址");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 1. 获取商户车费配置
|
|
|
+ LambdaQueryWrapper<MaProjectFareSetting> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(MaProjectFareSetting::getMerchantId, dto.getMerchantId())
|
|
|
+ .eq(MaProjectFareSetting::getIsDelete, 0);
|
|
|
+ List<MaProjectFareSetting> list = this.baseMapper.selectList(wrapper);
|
|
|
+
|
|
|
+ MaProjectFareSetting finalConfig = null;
|
|
|
+
|
|
|
+ if (CollUtil.isNotEmpty(list)) {
|
|
|
+ if (list.size() == 1 && ObjectUtil.equals(1, list.get(0).getIsUnified())) {
|
|
|
+ // 【情况A】集合数量为1 -> 是统一配置
|
|
|
+ // 直接取唯一的一条作为最终配置
|
|
|
+ log.info("商户[{}]仅有一条配置,判定为统一设置模式", dto.getMerchantId());
|
|
|
+ finalConfig = list.get(0);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // 【情况B】集合数量大于1 -> 不是统一配置(独立项目配置)
|
|
|
+ // 需要根据传入的 projectId 从列表中筛选出对应的项目配置
|
|
|
+ log.info("商户[{}]存在多条配置,根据projectId[{}]进行匹配", dto.getMerchantId(), dto.getProjectId());
|
|
|
+
|
|
|
+ // 使用 Stream API 过滤出当前项目对应的配置
|
|
|
+ Optional<MaProjectFareSetting> projectConfigOpt = list.stream()
|
|
|
+ .filter(item -> item.getProjectId() != null && item.getProjectId().equals(dto.getProjectId()))
|
|
|
+ .findFirst();
|
|
|
+
|
|
|
+ if (projectConfigOpt.isPresent()) {
|
|
|
+ finalConfig = projectConfigOpt.get();
|
|
|
+ } else {
|
|
|
+ // 可选:如果没找到对应项目的配置,是否回退到第一条?或者报错?
|
|
|
+ // 这里假设必须精确匹配,否则抛异常或给默认值
|
|
|
+ throw new ServiceException("未找到该项目[" + dto.getProjectId() + "]的专属车费配置");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 【情况C】商户无配置 -> 获取后台城市车费设置
|
|
|
+ log.info("商户[{}]无配置,尝试获取城市[{}]的默认配置", dto.getMerchantId(), dto.getCityCode());
|
|
|
+ // TODO: 调用获取城市配置的 Service/Method
|
|
|
+ // finalConfig = cityFareService.getDefaultByCity(dto.getCityCode());
|
|
|
+ TFareSettingVo fareSetting = fareSettingService.getFareSetting("", dto.getCityCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 此时 finalConfig 应该已经有值了,继续后续的距离计算逻辑...
|
|
|
+ if (ObjectUtil.isNull(finalConfig)) {
|
|
|
+ throw new ServiceException("无法获取有效的车费计算规则");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 判断时间段 (白天 vs 夜间)
|
|
|
+ // 假设白天是 7:30 - 19:30,其余为夜间 (具体逻辑根据你的业务定)
|
|
|
+ LocalTime time = dto.getAppointmentStartTime().toLocalTime();
|
|
|
+ boolean isDayTime = !time.isBefore(LocalTime.of(7, 30)) && time.isBefore(LocalTime.of(19, 30));
|
|
|
+
|
|
|
+ BigDecimal freeKm = isDayTime ? finalConfig.getDayFreeKm() : finalConfig.getNightFreeKm();
|
|
|
+ result.setFreeDistanceKm(freeKm);
|
|
|
+
|
|
|
+
|
|
|
+ // 3. 计算实际距离 (调用地图API)
|
|
|
+//
|
|
|
+// // 参数顺序:纬度(lat), 经度(lon)
|
|
|
+//
|
|
|
+//// double distance = CoordinateUtil(37.870000, 112.550000, 37.880000, 112.560000);
|
|
|
+//
|
|
|
+//// 返回值单位是 米 (m),转换为公里
|
|
|
+// double distanceKm = NumberUtil.div(distance, 1000, 2); // 保留2位小数
|
|
|
+//
|
|
|
+// double distanceInMeters = this.baseMapper.calculateDistance(
|
|
|
+// dto.getLatitude(), dto.getLongitude(),
|
|
|
+// targetLat, targetLon
|
|
|
+// );
|
|
|
+//
|
|
|
+// BigDecimal actualKm = new BigDecimal(distanceInMeters).divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
|
|
|
+// result.setActualDistanceKm(actualKm);
|
|
|
+//
|
|
|
+// // 4. 计算费用
|
|
|
+// BigDecimal freeKm = result.getFreeDistanceKm();
|
|
|
+// BigDecimal exceedKm = actualKm.subtract(freeKm);
|
|
|
+//
|
|
|
+// // 如果小于0,说明在免费范围内
|
|
|
+// if (exceedKm.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+// result.setExceedDistanceKm(BigDecimal.ZERO);
|
|
|
+// result.setEstimatedFare(BigDecimal.ZERO);
|
|
|
+// result.setIsFree(true);
|
|
|
+// result.setMessage(String.format("距离 %.2f km,在 %.2f km 免费范围内", actualKm, freeKm));
|
|
|
+// } else {
|
|
|
+// result.setExceedDistanceKm(exceedKm);
|
|
|
+// // 费用 = 超出距离 * 单价
|
|
|
+// BigDecimal fare = exceedKm.multiply(UNIT_PRICE).setScale(2, RoundingMode.HALF_UP);
|
|
|
+// result.setEstimatedFare(fare);
|
|
|
+// result.setIsFree(false);
|
|
|
+// result.setMessage(String.format("超出免费里程 %.2f km,需支付车费", exceedKm));
|
|
|
+// }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
}
|