乐尚代驾八订单执行三

news2024/11/27 2:23:15
  • 司机到达代驾终点,代驾结束了。
  • 结束代驾之后,

– 获取额外费用(高速费、停车费等)

– 计算订单实际里程(实际与预估有偏差)

– 计算代驾实际费用

– 系统奖励

– 分账信息

– 生成最终账单

计算订单实际里程

  • 在MongoDB保存代驾过程中司机位置信息,把MongoDB存储司机位置信息获取出来,以时间排序,连接成一条线,这条线是实际距离

准备计算距离工具类
在这里插入图片描述
地图微服务接口

在这里插入图片描述

@Operation(summary = "代驾服务:计算订单实际里程")
@GetMapping("/calculateOrderRealDistance/{orderId}")
public Result<BigDecimal> calculateOrderRealDistance(@PathVariable Long orderId) {
    return Result.ok(locationService.calculateOrderRealDistance(orderId));
}





@Override
    public BigDecimal calculateOrderRealDistance(Long orderId) {
        //1 根据订单id获取代驾订单位置信息,根据创建时间排序(升序)
        //查询MongoDB
        //第一种方式
//        OrderServiceLocation orderServiceLocation = new OrderServiceLocation();
//        orderServiceLocation.setOrderId(orderId);
//        Example<OrderServiceLocation> example = Example.of(orderServiceLocation);
//        Sort sort = Sort.by(Sort.Direction.ASC, "createTime");
//        List<OrderServiceLocation> list = orderServiceLocationRepository.findAll(example, sort);
        //第二种方式
        //MongoRepository只需要 按照规则 在MongoRepository把查询方法创建出来就可以了
        // 总体规则:
        //1 查询方法名称 以 get  |  find  | read开头
        //2 后面查询字段名称,满足驼峰式命名,比如OrderId
        //3 字段查询条件添加关键字,比如Like  OrderBy   Asc
        // 具体编写 : 根据订单id获取代驾订单位置信息,根据创建时间排序(升序)
        List<OrderServiceLocation> list =
                orderServiceLocationRepository.findByOrderIdOrderByCreateTimeAsc(orderId);

        //2 第一步查询返回订单位置信息list集合
        //把list集合遍历,得到每个位置信息,计算两个位置距离
        //把计算所有距离相加操作
        double realDistance = 0;
        if(!CollectionUtils.isEmpty(list)) {
            for (int i = 0,size = list.size()-1; i < size; i++) {
                OrderServiceLocation location1 = list.get(i);
                OrderServiceLocation location2 = list.get(i + 1);

                //计算位置距离
                double distance = LocationUtil.getDistance(location1.getLatitude().doubleValue(),
                        location1.getLongitude().doubleValue(),
                        location2.getLatitude().doubleValue(),
                        location2.getLongitude().doubleValue());

                realDistance += distance;
            }
        }

        //3 返回最终计算实际距离
        return new BigDecimal(realDistance);
    }






/**
 * 代驾服务:计算订单实际里程
 * @param orderId
 * @return
 */
@GetMapping("/map/location/calculateOrderRealDistance/{orderId}")
Result<BigDecimal> calculateOrderRealDistance(@PathVariable Long orderId);

计算系统奖励

系统奖励
每天完成5单后 每单奖励2元
每天完成10单后 每单奖励5元
每天完成20单后 每单奖励10元

//package对应的不一定是真正的目录,可以任意写com.abc,同一个包下的drl文件可以相互访问
package  com.atguigu.daijia

import com.atguigu.daijia.model.form.rules.RewardRuleRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;

global com.atguigu.daijia.model.vo.rules.RewardRuleResponse rewardRuleResponse;

/**
系统奖励
    00:00:00-06:59:59  完成5单后 每单奖励5元
    07:00:00-23:59:59  完成10单后 每单奖励2元
*/
rule "00:00:00-06:59:59  完成5单后 每单奖励5元"
    salience 10          //指定优先级,数值越大优先级越高,不指定的情况下由上到下执行
    no-loop true         //防止陷入死循环
    when
        /*规则条件,到工作内存中查找FeeRuleRequest对象
        里面出来的结果只能是ture或者false
        $rule是绑定变量名,可以任意命名,官方推荐$符号,定义了绑定变量名,可以在then部分操作fact对象*/
        $rule:RewardRuleRequest(startTime >= "00:00:00" && startTime <= "06:59:59" && orderNum > 5)
    then
        rewardRuleResponse.setRewardAmount(new BigDecimal("5.0"));
        System.out.println("00:00:00-06:59:59 奖励:" + rewardRuleResponse.getRewardAmount() + "元");
end
rule "07:00:00-23:59:59  完成10单后 每单奖励2元"
    salience 10          //指定优先级,数值越大优先级越高,不指定的情况下由上到下执行
    no-loop true         //防止陷入死循环
    when
        /*规则条件,到工作内存中查找FeeRuleRequest对象
        里面出来的结果只能是ture或者false
        $rule是绑定变量名,可以任意命名,官方推荐$符号,定义了绑定变量名,可以在then部分操作fact对象*/
        $rule:RewardRuleRequest(startTime >= "07:00:00" && startTime <= "23:59:59" && orderNum > 10)
    then
        rewardRuleResponse.setRewardAmount(new BigDecimal("2.0"));
        System.out.println("00:00:00-06:59:59 奖励:" + rewardRuleResponse.getRewardAmount() + "元");
end










public class DroolsHelper {

    private static final String RULES_CUSTOMER_RULES_DRL = "rules/FeeRule.drl";

    public static KieSession loadForRule(String drlStr) {
        KieServices kieServices = KieServices.Factory.get();

        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        kieFileSystem.write(
                ResourceFactory.newClassPathResource(drlStr));

        KieBuilder kb = kieServices.newKieBuilder(kieFileSystem);
        kb.buildAll();

        KieModule kieModule = kb.getKieModule();
        KieContainer kieContainer = kieServices.newKieContainer(kieModule.getReleaseId());
        return kieContainer.newKieSession();
    }
}








@Operation(summary = "计算订单奖励费用")
@PostMapping("/calculateOrderRewardFee")
public Result<RewardRuleResponseVo>
        calculateOrderRewardFee(@RequestBody RewardRuleRequestForm rewardRuleRequestForm) {
    return Result.ok(rewardRuleService.calculateOrderRewardFee(rewardRuleRequestForm));
}








@Override
public RewardRuleResponseVo calculateOrderRewardFee(RewardRuleRequestForm rewardRuleRequestForm) {
    //封装传入参数对象
    RewardRuleRequest rewardRuleRequest = new RewardRuleRequest();
    rewardRuleRequest.setOrderNum(rewardRuleRequestForm.getOrderNum());

    //创建规则引擎对象
    KieSession kieSession = DroolsHelper.loadForRule(RULES_CUSTOMER_RULES_DRL);

    //封装返回对象
    RewardRuleResponse rewardRuleResponse = new RewardRuleResponse();
    kieSession.setGlobal("rewardRuleResponse",rewardRuleResponse);

    //设置对象,触发规则
    kieSession.insert(rewardRuleRequest);
    kieSession.fireAllRules();

    //终止会话
    kieSession.dispose();

    //封装RewardRuleResponseVo
    RewardRuleResponseVo rewardRuleResponseVo = new RewardRuleResponseVo();
    rewardRuleResponseVo.setRewardAmount(rewardRuleResponse.getRewardAmount());
    return rewardRuleResponseVo;
}










/**
 * 计算订单奖励费用
 * @param rewardRuleRequestForm
 * @return
 */
@PostMapping("/rules/reward/calculateOrderRewardFee")
Result<RewardRuleResponseVo> calculateOrderRewardFee(@RequestBody RewardRuleRequestForm rewardRuleRequestForm);

根据时间段获取订单数

  • 因为系统奖励的计算,白天和晚上是不一样的,所以会根据时间段来获取
@Operation(summary = "根据时间段获取订单数")
@GetMapping("/getOrderNumByTime/{startTime}/{endTime}")
public Result<Long> getOrderNumByTime(@PathVariable String startTime, @PathVariable String endTime) {
    return Result.ok(orderInfoService.getOrderNumByTime(startTime, endTime));
}




@Override
public Long getOrderNumByTime(String startTime, String endTime) {
   // 09 <= time < 10   <= time1  <    11
   // 这么写所有的订单都可以被查询到,且不会重复
    LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
    wrapper.ge(OrderInfo::getStartServiceTime,startTime);
    wrapper.lt(OrderInfo::getStartServiceTime,endTime);
    Long count = orderInfoMapper.selectCount(wrapper);
    return count;
}





/**
 *  根据时间段获取订单数
 * @param startTime
 * @param endTime
 * @return
 */
@GetMapping("/order/info/getOrderNumByTime/{startTime}/{endTime}")
Result<Long> getOrderNumByTime(@PathVariable("startTime") String startTime, @PathVariable("endTime") String endTime);

计算分账信息

  • 结束代驾之后,计算分账信息,平台按照一定规则抽成处理,将分账信息记录数据库表

支付微信平台费用
平台费率:0.6%
订单金额小于等于100
当天完成订单小于等于10单 平台抽成 20%
当天完成订单大于10单 平台抽成 18%
订单金额大于100
当天完成订单小于等于10单 平台抽成 18%
当天完成订单大于10单 平台抽成 16%

//package对应的不一定是真正的目录,可以任意写com.abc,同一个包下的drl文件可以相互访问
package  com.atguigu.daijia

import com.atguigu.daijia.model.form.rules.ProfitsharingRuleRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;

global com.atguigu.daijia.model.vo.rules.ProfitsharingRuleResponse profitsharingRuleResponse;
//支付微信平台费率:0.6%
//global BigDecimal paymentRate = new BigDecimal(0.006);
/**
支付微信平台费用
    平台费率:0.6%
*/
rule "支付微信平台费用 平台费率:0.6%"
    salience 10          //指定优先级,数值越大优先级越高,不指定的情况下由上到下执行
    no-loop true         //防止陷入死循环
    when
        /*规则条件,到工作内存中查找FeeRuleRequest对象
        里面出来的结果只能是ture或者false
        $rule是绑定变量名,可以任意命名,官方推荐$符号,定义了绑定变量名,可以在then部分操作fact对象*/
        $rule:ProfitsharingRuleRequest()
    then
        profitsharingRuleResponse.setOrderAmount($rule.getOrderAmount());
        profitsharingRuleResponse.setPaymentRate(new BigDecimal("0.006"));
        BigDecimal paymentFee = profitsharingRuleResponse.getOrderAmount().multiply(profitsharingRuleResponse.getPaymentRate()).setScale(2, RoundingMode.HALF_UP);
        profitsharingRuleResponse.setPaymentFee(paymentFee);
        System.out.println("支付微信平台费用:" + profitsharingRuleResponse.getPaymentFee() + "元");
end

/**
订单金额小于等于100
    当天完成订单小于等于10单 平台抽成 20%
    当天完成订单大于10单 平台抽成 18%
*/
rule "订单金额小于等于100 当天完成订单小于等于10单"
    salience 10          //指定优先级,数值越大优先级越高,不指定的情况下由上到下执行
    no-loop true         //防止陷入死循环
    when
        /*规则条件,到工作内存中查找FeeRuleRequest对象
        里面出来的结果只能是ture或者false
        $rule是绑定变量名,可以任意命名,官方推荐$符号,定义了绑定变量名,可以在then部分操作fact对象*/
        $rule:ProfitsharingRuleRequest(orderAmount <= 100.0 && orderNum <= 10)
    then
        BigDecimal totalAmount = profitsharingRuleResponse.getOrderAmount().subtract(profitsharingRuleResponse.getPaymentFee());
        BigDecimal platformIncome = totalAmount.multiply(new BigDecimal("0.2")).setScale(2, RoundingMode.HALF_UP);
        BigDecimal driverTotalIncome = totalAmount.subtract(platformIncome);
        //代驾司机个税,税率:10%
        BigDecimal driverTaxFee = driverTotalIncome.multiply(new BigDecimal("0.1")).setScale(2, RoundingMode.HALF_UP);
        BigDecimal driverIncome = driverTotalIncome.subtract(driverTaxFee);
        profitsharingRuleResponse.setPlatformIncome(platformIncome);
        profitsharingRuleResponse.setDriverIncome(driverIncome);
        profitsharingRuleResponse.setDriverTaxRate(new BigDecimal("0.1"));
        profitsharingRuleResponse.setDriverTaxFee(driverTaxFee);
        System.out.println("平台分账收入:" + platformIncome + "元" + ",司机分账收入:" + driverIncome + "元" + ",司机个税:" + driverTaxFee + "元");
end
rule "订单金额小于等于100 天完成订单大于10单"
    salience 10          //指定优先级,数值越大优先级越高,不指定的情况下由上到下执行
    no-loop true         //防止陷入死循环
    when
        /*规则条件,到工作内存中查找FeeRuleRequest对象
        里面出来的结果只能是ture或者false
        $rule是绑定变量名,可以任意命名,官方推荐$符号,定义了绑定变量名,可以在then部分操作fact对象*/
        $rule:ProfitsharingRuleRequest(orderAmount <= 100.0 && orderNum > 10)
    then
        BigDecimal totalAmount = profitsharingRuleResponse.getOrderAmount().subtract(profitsharingRuleResponse.getPaymentFee());
        BigDecimal platformIncome = totalAmount.multiply(new BigDecimal("0.18")).setScale(2, RoundingMode.HALF_UP);
        BigDecimal driverTotalIncome = totalAmount.subtract(platformIncome);
        //代驾司机个税,税率:10%
        BigDecimal driverTaxFee = driverTotalIncome.multiply(new BigDecimal("0.1")).setScale(2, RoundingMode.HALF_UP);
        BigDecimal driverIncome = driverTotalIncome.subtract(driverTaxFee);
        profitsharingRuleResponse.setPlatformIncome(platformIncome);
        profitsharingRuleResponse.setDriverIncome(driverIncome);
        profitsharingRuleResponse.setDriverTaxRate(new BigDecimal("0.1"));
        profitsharingRuleResponse.setDriverTaxFee(driverTaxFee);
        System.out.println("平台分账收入:" + platformIncome + "元" + ",司机分账收入:" + driverIncome + "元" + ",司机个税:" + driverTaxFee + "元");
end

/**
订单金额大于100
    当天完成订单小于等于10单 平台抽成 18%
    当天完成订单大于10单 平台抽成 16%
*/
rule "订单金额大于100 当天完成订单小于等于10单"
    salience 10          //指定优先级,数值越大优先级越高,不指定的情况下由上到下执行
    no-loop true         //防止陷入死循环
    when
        /*规则条件,到工作内存中查找FeeRuleRequest对象
        里面出来的结果只能是ture或者false
        $rule是绑定变量名,可以任意命名,官方推荐$符号,定义了绑定变量名,可以在then部分操作fact对象*/
        $rule:ProfitsharingRuleRequest(orderAmount > 100.0 && orderNum <= 10)
    then
        BigDecimal totalAmount = profitsharingRuleResponse.getOrderAmount().subtract(profitsharingRuleResponse.getPaymentFee());
        BigDecimal platformIncome = totalAmount.multiply(new BigDecimal("0.18")).setScale(2, RoundingMode.HALF_UP);
        BigDecimal driverTotalIncome = totalAmount.subtract(platformIncome);
        //代驾司机个税,税率:10%
        BigDecimal driverTaxFee = driverTotalIncome.multiply(new BigDecimal("0.1")).setScale(2, RoundingMode.HALF_UP);
        BigDecimal driverIncome = driverTotalIncome.subtract(driverTaxFee);
        profitsharingRuleResponse.setPlatformIncome(platformIncome);
        profitsharingRuleResponse.setDriverIncome(driverIncome);
        profitsharingRuleResponse.setDriverTaxRate(new BigDecimal("0.1"));
        profitsharingRuleResponse.setDriverTaxFee(driverTaxFee);
        System.out.println("平台分账收入:" + platformIncome + "元" + ",司机分账收入:" + driverIncome + "元" + ",司机个税:" + driverTaxFee + "元");
end
rule "订单金额大于100 天完成订单大于10单"
    salience 10          //指定优先级,数值越大优先级越高,不指定的情况下由上到下执行
    no-loop true         //防止陷入死循环
    when
        /*规则条件,到工作内存中查找FeeRuleRequest对象
        里面出来的结果只能是ture或者false
        $rule是绑定变量名,可以任意命名,官方推荐$符号,定义了绑定变量名,可以在then部分操作fact对象*/
        $rule:ProfitsharingRuleRequest(orderAmount > 100.0 && orderNum > 10)
    then
        BigDecimal totalAmount = profitsharingRuleResponse.getOrderAmount().subtract(profitsharingRuleResponse.getPaymentFee());
        BigDecimal platformIncome = totalAmount.multiply(new BigDecimal("0.18")).setScale(2, RoundingMode.HALF_UP);
        BigDecimal driverTotalIncome = totalAmount.subtract(platformIncome);
        //代驾司机个税,税率:10%
        BigDecimal driverTaxFee = driverTotalIncome.multiply(new BigDecimal("0.1")).setScale(2, RoundingMode.HALF_UP);
        BigDecimal driverIncome = driverTotalIncome.subtract(driverTaxFee);
        profitsharingRuleResponse.setPlatformIncome(platformIncome);
        profitsharingRuleResponse.setDriverIncome(driverIncome);
        profitsharingRuleResponse.setDriverTaxRate(new BigDecimal("0.1"));
        profitsharingRuleResponse.setDriverTaxFee(driverTaxFee);
        System.out.println("平台分账收入:" + platformIncome + "元" + ",司机分账收入:" + driverIncome + "元" + ",司机个税:" + driverTaxFee + "元");
end










@RestController
@RequestMapping("/rules/profitsharing")
@SuppressWarnings({"unchecked", "rawtypes"})
public class ProfitsharingRuleController {

    @Autowired
    private ProfitsharingRuleService profitsharingRuleService;

    @Operation(summary = "计算系统分账费用")
    @PostMapping("/calculateOrderProfitsharingFee")
    public Result<ProfitsharingRuleResponseVo> calculateOrderProfitsharingFee(@RequestBody ProfitsharingRuleRequestForm profitsharingRuleRequestForm) {
        return Result.ok(profitsharingRuleService.calculateOrderProfitsharingFee(profitsharingRuleRequestForm));
    }
}












private static final String RULES_CUSTOMER_RULES_DRL = "rules/ProfitsharingRule.drl";

@Override
public ProfitsharingRuleResponseVo calculateOrderProfitsharingFee(ProfitsharingRuleRequestForm profitsharingRuleRequestForm) {
    //传入参数对象封装
    ProfitsharingRuleRequest profitsharingRuleRequest = new ProfitsharingRuleRequest();
    profitsharingRuleRequest.setOrderAmount(profitsharingRuleRequestForm.getOrderAmount());
    profitsharingRuleRequest.setOrderNum(profitsharingRuleRequestForm.getOrderNum());
    
    //创建kieSession
    KieSession kieSession = DroolsHelper.loadForRule(RULES_CUSTOMER_RULES_DRL);
    
    //封装返回对象
    ProfitsharingRuleResponse profitsharingRuleResponse = new ProfitsharingRuleResponse();
    kieSession.setGlobal("profitsharingRuleResponse",profitsharingRuleResponse);
    
    //触发规则,返回vo对象
    kieSession.insert(profitsharingRuleRequest);
    kieSession.fireAllRules();
    kieSession.dispose();

    ProfitsharingRuleResponseVo profitsharingRuleResponseVo = new ProfitsharingRuleResponseVo();
    BeanUtils.copyProperties(profitsharingRuleResponse,profitsharingRuleResponseVo);
    
    return profitsharingRuleResponseVo;
}











/**
 * 计算订单分账数据
 * @param profitsharingRuleRequestForm
 * @return
 */
@PostMapping("/rules/profitsharing/calculateOrderProfitsharingFee")
Result<ProfitsharingRuleResponseVo> calculateOrderProfitsharingFee(@RequestBody ProfitsharingRuleRequestForm profitsharingRuleRequestForm);

结束代驾更新账单

  • 更新订单数据:订单状态、订单实际距离、订单实际金额等
  • 添加实际账单信息
  • 添加分账信息
@Operation(summary = "结束代驾服务更新订单账单")
@PostMapping("/endDrive")
public Result<Boolean> endDrive(@RequestBody UpdateOrderBillForm updateOrderBillForm) {
    return Result.ok(orderInfoService.endDrive(updateOrderBillForm));
}







@Override
public Boolean endDrive(UpdateOrderBillForm updateOrderBillForm) {
    //1 更新订单信息
    // update order_info set ..... where id=? and driver_id=?
    LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(OrderInfo::getId,updateOrderBillForm.getOrderId());
    wrapper.eq(OrderInfo::getDriverId,updateOrderBillForm.getDriverId());

    OrderInfo orderInfo = new OrderInfo();
    orderInfo.setStatus(OrderStatus.END_SERVICE.getStatus());
    orderInfo.setRealAmount(updateOrderBillForm.getTotalAmount());
    orderInfo.setFavourFee(updateOrderBillForm.getFavourFee());
    orderInfo.setRealDistance(updateOrderBillForm.getRealDistance());
    orderInfo.setEndServiceTime(new Date());

    int rows = orderInfoMapper.update(orderInfo, wrapper);

    if(rows == 1) {
        //添加账单数据
        OrderBill orderBill = new OrderBill();
        BeanUtils.copyProperties(updateOrderBillForm,orderBill);
        orderBill.setOrderId(updateOrderBillForm.getOrderId());
        orderBill.setPayAmount(updateOrderBillForm.getTotalAmount());
        orderBillMapper.insert(orderBill);

        //添加分账信息
        OrderProfitsharing orderProfitsharing = new OrderProfitsharing();
        BeanUtils.copyProperties(updateOrderBillForm, orderProfitsharing);
        orderProfitsharing.setOrderId(updateOrderBillForm.getOrderId());
        orderProfitsharing.setRuleId(updateOrderBillForm.getProfitsharingRuleId());
        orderProfitsharing.setStatus(1);
        orderProfitsharingMapper.insert(orderProfitsharing);

    } else {
        throw new GuiguException(ResultCodeEnum.UPDATE_ERROR);
    }
    return true;
}






/**
 * 结束代驾服务更新订单账单
 * @param updateOrderBillForm
 * @return
 */
@PostMapping("/order/info/endDrive")
Result<Boolean> endDrive(@RequestBody UpdateOrderBillForm updateOrderBillForm);

结束代驾

  • 调用以上的所有接口最终实现
@Operation(summary = "结束代驾服务更新订单账单")
@GuiguLogin
@PostMapping("/endDrive")
public Result<Boolean> endDrive(@RequestBody OrderFeeForm orderFeeForm) {
    Long driverId = AuthContextHolder.getUserId();
    orderFeeForm.setDriverId(driverId);
    return Result.ok(orderService.endDrive(orderFeeForm));
}






@Override
public Boolean endDrive(OrderFeeForm orderFeeForm) {
    //1 根据orderId获取订单信息,判断当前订单是否司机接单
    OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderFeeForm.getOrderId()).getData();
    if(orderInfo.getDriverId() != orderFeeForm.getDriverId()) {
        throw new GuiguException(ResultCodeEnum.ILLEGAL_REQUEST);
    }

    //2 计算订单实际里程
    BigDecimal realDistance =
            locationFeignClient.calculateOrderRealDistance(orderFeeForm.getOrderId()).getData();

    //3 计算代驾实际费用
    //远程调用,计算代驾费用
    //封装FeeRuleRequestForm
    FeeRuleRequestForm feeRuleRequestForm = new FeeRuleRequestForm();
    feeRuleRequestForm.setDistance(realDistance);
    feeRuleRequestForm.setStartTime(orderInfo.getStartServiceTime());

	
    //计算司机到达代驾开始位置时间
    //orderInfo.getArriveTime() - orderInfo.getAcceptTime()
    // 分钟 = 毫秒 / 1000 * 60
    Integer waitMinute =
            Math.abs((int)((orderInfo.getArriveTime().getTime()-orderInfo.getAcceptTime().getTime())/(1000 * 60)));
    feeRuleRequestForm.setWaitMinute(waitMinute);
    //远程调用 代驾费用
    FeeRuleResponseVo feeRuleResponseVo = feeRuleFeignClient.calculateOrderFee(feeRuleRequestForm).getData();
    //实际费用 = 代驾费用 + 其他费用(停车费)
    BigDecimal totalAmount =
            feeRuleResponseVo.getTotalAmount().add(orderFeeForm.getTollFee())
                    .add(orderFeeForm.getParkingFee())
                    .add(orderFeeForm.getOtherFee())
                    .add(orderInfo.getFavourFee());
    feeRuleResponseVo.setTotalAmount(totalAmount);

    //4 计算系统奖励
    String startTime = new DateTime(orderInfo.getStartServiceTime()).toString("yyyy-MM-dd") + " 00:00:00";
    String endTime = new DateTime(orderInfo.getStartServiceTime()).toString("yyyy-MM-dd") + " 24:00:00";
    Long orderNum = orderInfoFeignClient.getOrderNumByTime(startTime, endTime).getData();
    //4.2.封装参数
    RewardRuleRequestForm rewardRuleRequestForm = new RewardRuleRequestForm();
    rewardRuleRequestForm.setStartTime(orderInfo.getStartServiceTime());
    rewardRuleRequestForm.setOrderNum(orderNum);

    RewardRuleResponseVo rewardRuleResponseVo = rewardRuleFeignClient.calculateOrderRewardFee(rewardRuleRequestForm).getData();

    //5 计算分账信息
    ProfitsharingRuleRequestForm profitsharingRuleRequestForm = new ProfitsharingRuleRequestForm();
    profitsharingRuleRequestForm.setOrderAmount(feeRuleResponseVo.getTotalAmount());
    profitsharingRuleRequestForm.setOrderNum(orderNum);

    ProfitsharingRuleResponseVo profitsharingRuleResponseVo = profitsharingRuleFeignClient.calculateOrderProfitsharingFee(profitsharingRuleRequestForm).getData();

    //6 封装实体类,结束代驾更新订单,添加账单和分账信息
    UpdateOrderBillForm updateOrderBillForm = new UpdateOrderBillForm();
    updateOrderBillForm.setOrderId(orderFeeForm.getOrderId());
    updateOrderBillForm.setDriverId(orderFeeForm.getDriverId());
    //路桥费、停车费、其他费用
    updateOrderBillForm.setTollFee(orderFeeForm.getTollFee());
    updateOrderBillForm.setParkingFee(orderFeeForm.getParkingFee());
    updateOrderBillForm.setOtherFee(orderFeeForm.getOtherFee());
    //乘客好处费
    updateOrderBillForm.setFavourFee(orderInfo.getFavourFee());

    //实际里程
    updateOrderBillForm.setRealDistance(realDistance);
    //订单奖励信息
    BeanUtils.copyProperties(rewardRuleResponseVo, updateOrderBillForm);
    //代驾费用信息
    BeanUtils.copyProperties(feeRuleResponseVo, updateOrderBillForm);
    //分账相关信息
    BeanUtils.copyProperties(profitsharingRuleResponseVo, updateOrderBillForm);
    updateOrderBillForm.setProfitsharingRuleId(profitsharingRuleResponseVo.getProfitsharingRuleId());
    orderInfoFeignClient.endDrive(updateOrderBillForm);

    return true;
}

智能判断司机刷单行为

  • 什么是刷单行为?
    司机还没有到达代驾地点就点击到达,司机还没有到达终点就点击结束代驾,这样做是为了争取更多的订单,争取更多的平台奖励。

  • 司机到达代驾开始位置判断

– 通过腾讯地图,获取司机当前位置,当前位置到代驾开始位置距离

– 如果距离超过1公里,没有到达开始位置

  • 司机到达代驾结束位置判断

– 通过腾讯地图,获取司机当前位置,当前位置到代驾结束位置距离

– 如果距离超过2公里,没有到达开始位置

  • 判断预估里程和实际里程差别
//司机到达代驾起始地点
@Override
public Boolean driverArriveStartLocation(Long orderId, Long driverId) {
    //判断
    // orderInfo有代驾开始位置
    OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderId).getData();

    //司机当前位置
    OrderLocationVo orderLocationVo = locationFeignClient.getCacheOrderLocation(orderId).getData();

    //司机当前位置 和 代驾开始位置距离
    double distance = LocationUtil.getDistance(orderInfo.getStartPointLatitude().doubleValue(),
            orderInfo.getStartPointLongitude().doubleValue(),
            orderLocationVo.getLatitude().doubleValue(),
            orderLocationVo.getLongitude().doubleValue());
    if(distance > SystemConstant.DRIVER_START_LOCATION_DISTION) {
        throw new GuiguException(ResultCodeEnum.DRIVER_START_LOCATION_DISTION_ERROR);
    }
    
    return orderInfoFeignClient.driverArriveStartLocation(orderId,driverId).getData();
}









//防止刷
OrderServiceLastLocationVo orderServiceLastLocationVo = locationFeignClient.getOrderServiceLastLocation(orderFeeForm.getOrderId()).getData();

//司机当前位置 距离 结束代驾位置 
double distance = LocationUtil.getDistance(orderInfo.getEndPointLatitude().doubleValue(),
        orderInfo.getEndPointLongitude().doubleValue(),
        orderServiceLastLocationVo.getLatitude().doubleValue(),
        orderServiceLastLocationVo.getLongitude().doubleValue());
if(distance > SystemConstant.DRIVER_END_LOCATION_DISTION) {
    throw new GuiguException(ResultCodeEnum.DRIVER_END_LOCATION_DISTION_ERROR);
}

在她们脸上看见楼上两位女主人面貌的痕迹,知道了答案。

房思琪的初恋乐园
林奕含

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1952124.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【计算机网络】RIP路由协议实验

一&#xff1a;实验目的 1&#xff1a;掌握在路由器上配置RIPv2。 二&#xff1a;实验仪器设备及软件 硬件&#xff1a;RCMS交换机、网线、内网网卡接口、Windows 2019操作系统的计算机等。具体为&#xff1a;三层交换机1台、路由器2台。 软件&#xff1a;wireshark软件、记…

Qwen2-Audio:对话式AI突破,让你“声”临其境

阿里巴巴最新推出的音频处理模型Qwen2-Audio&#xff0c;不仅能直接用语音聊天&#xff0c;还能像一位专业的听觉大师一样分析各种声音&#xff0c;功能强大得令人难以置信。 Qwen2-Audio可以通过语音聊天和音频分析两种方式与用户互动&#xff0c;用户无需区分这两种模式&…

请问C语言到底允不允许动态定义数组大小?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「c语言的资料从专业入门到高级教程」&#xff0c;点个关注在评论区回复“666”之后私信回复“666”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 按照谭浩强的第五版C程序设…

vue实现电子签名、图片合成、及预览功能

业务功能&#xff1a;电子签名、图片合成、及预览功能 业务背景&#xff1a;需求说想要实现一个电子签名&#xff0c;然后需要提供一个预览的功能&#xff0c;可以查看签完名之后的完整效果。 需求探讨&#xff1a;后端大佬跟我说&#xff0c;文档我返回给你一个PDF的oss链接…

MySQL客户端命令一节将.sql文件导入MySQL

MySql客户端命令 直接输入SQL语句 使用MySQL客户端连接到服务器之后&#xff0c;可以发送SQL语句到服务器执行&#xff0c;并且以&#xff1b;和\g, \G作为结束不同的结束方式显示内容有所不同** TIPS: ;和\g结尾以表格的形式显示结果\G以行的形式显示结果 在连接到服务器之后…

小程序获取订阅消息状态

uni.getSetting获取用户的当前设置 uni.getSetting({success(res) {console.log(res)} })1. 当withSubscriptions&#xff1a;true的时候&#xff0c;只返回用户勾选过订阅面板中的“总是保持以上选择&#xff0c;不再询问”的订阅消息。 2.返回值中的subscriptionsSetting表示…

自动驾驶-机器人-slam-定位面经和面试知识系列05之常考公式推导(02)

这个博客系列会分为C STL-面经、常考公式推导和SLAM面经面试题等三个系列进行更新&#xff0c;基本涵盖了自己秋招历程被问过的面试内容&#xff08;除了实习和学校项目相关的具体细节&#xff09;。在知乎和牛客&#xff08;牛客上某些文章上会附上内推码&#xff09;也会同步…

【运维自动化-配置平台】模型及模型关联最小化实践

蓝鲸智云配置平台&#xff0c;以下简称配置平台 我们知道主机是配置平台最常见的管控资源对象&#xff0c;在业务拓扑里可以通过划分模块来清晰的可视化管理&#xff1b;那其他资源如何通过配置平台来纳管呢&#xff0c;比如网络设备交换机。场景需求&#xff1a;如何把交换机…

怎么培养政府机关的公文写作能力?

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频百万播放量 公文写作千万不能零起步&#xff0c;你有时间慢慢学习&#xff0c;但领导哪有时间等你慢慢进步啊。 如果问写公文有什么捷径&#xff0c;那就不得不靠「AI写作工具…

Study--Oracle-07-ASM相关参数(四)

一、ASM主要进程 1、ASM主要后台进程 ASM实例除了传统的DBWn、LGWR、CKPT、SMON和PMON等进程还包含如下几个新后台进程: 2、牛人笔记 邦德图文解读ASM架构,超详细 - 墨天轮 二、数据库实例于ASM实例之间的交互关系 数据库实例与ASM实例之间的交互关系涉及多个步骤和过程,…

联想教育电脑硬盘保护同传EDU系统使用简明教程

目录 一、原理概述 二、简明使用方法 1、软件下载 2、开机引导 3、开始安装 4、使用 &#xff08;1&#xff09;进入底层 &#xff08;2&#xff09;进行分区设置 &#xff08;3&#xff09;系统设置 &#xff08;4&#xff09;安装硬盘保护驱动 &#xff08;5&…

Android Studio导入源码

在有源码并且编译环境可用的情况下&#xff1a; 1.生成导入AS所需的配置文件 在源码的根目录执行以下命令&#xff1a; source build/ensetup.sh lunch 要编译的项目 make idegen //这一步会生成out/host/linux-x86/framework/idegen.jar development/tools/idegen/idegen.sh…

若依框架 : 生成代码

6.生成代码 6.1.配置生成设置 ruoyi-generator -> src -> main -> resources -> generator.yml 由于 案例中 表都有 前缀 为 tta_ , 这里设置去掉 6.2.生成代码 6.2.1.导入数据库中的表 6.2.2.修改设置 6.2.2.1.设置生成信息 点击 编辑 -> 生成信息 特别…

【数据结构-前缀和】力扣3152.特殊数组II

如果数组的每一对相邻元素都是两个奇偶性不同的数字&#xff0c;则该数组被认为是一个 特殊数组 。 周洋哥有一个整数数组 nums 和一个二维整数矩阵 queries&#xff0c;对于 queries[i] [fromi, toi]&#xff0c;请你帮助周洋哥检查子数组 nums[fromi…toi] 是不是一个 特殊…

19 Python常用内置函数——range()

range() 是 Python 开发中非常常用的一个内置函数。该函数返回具有惰性求值特点的 range 对象&#xff0c;其中包含左闭右开区间 [start, end) 内以 step 为步长的整数。 参数 start 默认为 0&#xff0c;step 默认为 1。 print(range(5)) print(list(range(5))) print(list(r…

科研绘图系列:R语言山脊图(Ridgeline Chart)

介绍 山脊图(Ridge Chart)是一种用于展示数据分布和比较不同类别或组之间差异的数据可视化技术。它通常用于展示多个维度或变量之间的关系,以及它们在不同组中的分布情况。山脊图的特点: 多变量展示:山脊图可以同时展示多个变量的分布情况,允许用户比较不同变量之间的关…

在MATLAB中使用importrobot导入机械臂刚体树时没有找到模型文件,只显示坐标;改为使用loadrobot

没有mesh文件夹&#xff0c;所以找不到模型文件 改为使用loadrobot,直接加载刚体树数据

深度解析Linux-C——结构体(初始化,结构体数组,结构体大小,位段操作,联合体,内存对齐,C的预处理,宏和带参宏,条件编译)

目录 结构体的三种初始化 结构体的两种引用 结构体数组 结构体大小 结构体实现位段操作 联合体 内存对齐 C的预处理 带参宏 条件编译 结构体的三种初始化 定义如下结构体 struct student {char name[100]; int age; float height; } ; 1、定义变量时初始化 s…

unity 实现图片的放大与缩小(根据鼠标位置拉伸放缩)

1创建UnityHelper.cs using UnityEngine.Events; using UnityEngine.EventSystems;public class UnityHelper {/// <summary>/// 简化向EventTrigger组件添加事件的操作。/// </summary>/// <param name"_eventTrigger">要添加事件监听的UI元素上…

Memcached开发(十四):常见问题与故障排除

目录 1. 内存使用问题 1.1 内存不足 1.2 内存泄漏 2. 连接问题 2.1 连接超时 2.2 连接断开 3. 数据一致性问题 3.1 缓存穿透 3.2 缓存雪崩 3.3 缓存击穿 4. 性能问题 4.1 响应时间过长 4.2 吞吐量不足 5. 安全问题 5.1 未授权访问 5.2 数据泄露 6. 版本兼容问…