liujie
2026-06-09 c96fbe6b0aeb413a17c429133ee6d81d138144b9
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
@@ -6,6 +6,7 @@
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -46,6 +47,7 @@
import com.xiaopeng.operation.utils.XpPricingUtil;
import com.xiaopeng.operation.utils.holiday.HolidayUtil;
import com.xiaopeng.operation.utils.map.FastDistanceCalculator;
import com.xiaopeng.operation.vo.PricingInfoVo;
import com.xiaopeng.operation.vo.PricingPageListVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -346,6 +348,7 @@
        fareVo.setOriginalFare(xpPricingCardVo.getTotalPrice());
        if (userCouponVo != null) {
            fareVo.setDiscountAmount(userCouponVo.getMoney());
            fareVo.setCouponType(userCouponVo.getCouponType());
            fareVo.setFinalFare(fareVo.getOriginalFare() - fareVo.getDiscountAmount());
            fareVo.setCouponId(userCouponVo.getId());
        } else {
@@ -495,7 +498,7 @@
//        xpOrder.setStartMileage(Double.valueOf(startMileage));
        xpOrder.setAppUserId(Long.valueOf(uid));
        xpOrder.setOrderNumber("XP" + System.currentTimeMillis());
        xpOrder.setOrderNumber(getOrderNumber());
        xpOrder.setPlacementLon(dto.getPlacementLon());
        xpOrder.setPlacementLat(dto.getPlacementLat());
        xpOrder.setPlacementAddress(dto.getPlacementAddress());
@@ -519,7 +522,8 @@
        xpOrder.setEndPointId(dto.getEndPointId());
        xpOrder.setStartPointName(xpPoint.getPointName());
        xpOrder.setEndPointName(endXpPoint.getPointName());
        xpOrder.setXpuTaskId(snowflake.nextId() + "");
        xpOrder.setXpuStartTaskId(snowflake.nextId() + "");
        xpOrder.setXpuEndTaskId(snowflake.nextId() + "");
        // 当前时段
        String currentTimeSlot = DateUtils.getCurrentTimeSlot();
@@ -638,6 +642,11 @@
    }
    private String getOrderNumber(){
        int random = Double.valueOf(Math.random() * 1000).intValue();
        return "XP" + random + System.currentTimeMillis();
    }
    private Boolean isInOperationTime(String operationStrategy) {
        JSONArray jsonArray = JSONArray.parseArray(operationStrategy);
@@ -825,4 +834,80 @@
        this.updateById(update);
    }
    @Override
    public void savePrice(PricingInfoVo dto, XpOfficialPartner officialPartner) {
        XpOpenCity openCity = xpOpenCityMapper.selectOne(new QueryWrapper<XpOpenCity>().eq("city_code", dto.getCityCode()));
        if (openCity == null) {
            throw new ServiceException("城市未开通");
        }
        XpPricing pricing = this.lambdaQuery()
                .eq(XpPricing::getVehicleModel, dto.getVehicleModel())
                .eq(XpPricing::getChannel, officialPartner.getBrandName())
                .eq(XpPricing::getCityId, openCity.getId().intValue())
                .eq(XpPricing::getOfficialPartnerId, officialPartner.getId())
                .one();
        if(null == pricing){
            pricing = new XpPricing();
            pricing.setOfficialPartnerId(officialPartner.getId());
            pricing.setVehicleModel(dto.getVehicleModel());
            pricing.setChannel(officialPartner.getBrandName());
            pricing.setCityId(openCity.getId());
            pricing.setRemark(dto.getRemark());
            pricing.setPricingType(dto.getPricingType());
            pricing.setBasicPricingJson("{}");
            pricing.setStartingFareJson("[]");
            pricing.setDynamicPricingJson("{}");
            pricing.setIsDynamicPrice(0);
            this.save(pricing);
        }
        try {
            if (StringUtils.isNotBlank(dto.getBasicPricingJson())) {
                JSONObject.parseObject(dto.getBasicPricingJson());
            }
            if (StringUtils.isNotBlank(dto.getStartingFareJson())) {
                JSONArray.parseArray(dto.getStartingFareJson());
            }
            if (StringUtils.isNotBlank(dto.getDynamicPricingJson())) {
                JSONObject.parseObject(dto.getDynamicPricingJson());
            }
        } catch (Exception e) {
            throw new ServiceException("价格配置JSON格式不正确", I18nKeyConstant.PRICING_JSON_INVALID);
        }
        XpPricing update = new XpPricing();
        update.setId(pricing.getId());
        update.setBasicPricingJson(dto.getBasicPricingJson());
        update.setStartingFareJson(StringUtils.isNotBlank(dto.getStartingFareJson()) ? dto.getStartingFareJson() : null);
        update.setDynamicPricingJson(dto.getDynamicPricingJson());
        update.setIsDynamicPrice(dto.getIsDynamicPrice());
        update.setPriceRule(dto.getPriceRule());
        this.updateById(update);
        // 动态调价 Quartz 任务调度
        String jobName = DynamicPricingCheckJob.JOB_PREFIX + pricing.getId();
        if (Integer.valueOf(1).equals(dto.getIsDynamicPrice())
                && StringUtils.isNotBlank(dto.getDynamicPricingJson())) {
            JSONObject dynamicJson = JSONObject.parseObject(dto.getDynamicPricingJson());
            Integer periodMinutes = dynamicJson.getInteger("num1");
            if (periodMinutes != null && periodMinutes > 0) {
                // 先移除可能存在的旧任务,再注册新任务(num1 分钟后首次执行)
                QuartzManager.removeJob(jobName, TimeJobType.DYNAMIC_PRICING_CHECK);
                Date triggerTime = new Date(System.currentTimeMillis() + periodMinutes * 60_000L);
                Map<String, Object> jobData = new HashMap<>();
                jobData.put("pricingId", pricing.getId());
                QuartzManager.addJob(DynamicPricingCheckJob.class, jobName,
                        TimeJobType.DYNAMIC_PRICING_CHECK, triggerTime, jobData);
                log.info("动态调价任务已注册 pricingId={}, 供需计算周期={}分钟", pricing.getId(), periodMinutes);
            }
        } else {
            // 关闭动态调价时,移除已存在的任务
            QuartzManager.removeJob(jobName, TimeJobType.DYNAMIC_PRICING_CHECK);
            log.info("动态调价任务已移除 pricingId={}", pricing.getId());
        }
    }
}