From abf1d55dab11baeed5f989a273a776abce50cfc6 Mon Sep 17 00:00:00 2001 From: puzhibing <393733352@qq.com> Date: 星期二, 23 五月 2023 01:00:38 +0800 Subject: [PATCH] 新增订单添加功能 --- management/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TOrderServiceImpl.java | 408 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 380 insertions(+), 28 deletions(-) diff --git a/management/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TOrderServiceImpl.java b/management/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TOrderServiceImpl.java index f86cfce..43d547b 100644 --- a/management/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TOrderServiceImpl.java +++ b/management/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TOrderServiceImpl.java @@ -1,6 +1,7 @@ package com.stylefeng.guns.modular.system.service.impl; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.service.impl.ServiceImpl; @@ -16,15 +17,21 @@ import com.stylefeng.guns.modular.system.dao.TDriverMapper; import com.stylefeng.guns.modular.system.dao.TOrderMapper; import com.stylefeng.guns.modular.system.enums.OrderStateEnum; -import com.stylefeng.guns.modular.system.model.TAppUser; -import com.stylefeng.guns.modular.system.model.TBranchOffice; -import com.stylefeng.guns.modular.system.model.TDriver; -import com.stylefeng.guns.modular.system.model.TOrder; -import com.stylefeng.guns.modular.system.service.ITAppUserService; -import com.stylefeng.guns.modular.system.service.ITOrderService; -import com.stylefeng.guns.modular.system.util.DateUtil; -import com.stylefeng.guns.modular.system.util.ResultUtil; +import com.stylefeng.guns.modular.system.model.*; +import com.stylefeng.guns.modular.system.service.*; +import com.stylefeng.guns.modular.system.util.*; +import com.stylefeng.guns.modular.system.util.GaoDe.MapUtil; +import com.stylefeng.guns.modular.system.util.GaoDe.model.District; +import com.stylefeng.guns.modular.system.util.juhe.WeatherUtil; +import com.stylefeng.guns.modular.system.util.mongodb.model.Location; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.geo.Circle; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Metrics; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.geo.GeoJsonPoint; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; import org.springframework.stereotype.Service; import org.springframework.ui.Model; import org.springframework.util.CollectionUtils; @@ -32,9 +39,12 @@ import javax.annotation.Resource; import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.util.*; +import java.util.stream.Collectors; /** * <p> @@ -61,6 +71,27 @@ @Autowired private ITAppUserService appUserService; + + @Autowired + private RedisUtil redisUtil; + + @Autowired + private ITSystemConfigService systemConfigService; + + @Autowired + private ITYouTuiDriverService youTuiDriverService; + + @Resource + private MongoTemplate mongoTemplate; + + @Autowired + private IWeatherCityService weatherCityService; + + @Autowired + private PushUtil pushUtil; + + + @Override public List<TOrderResp> getOrderList(String createTime, String code, Integer source, String userName, String userPhone, Integer state, String driverName,Integer isException) { @@ -381,13 +412,19 @@ tOrder.setUserId(tAppUser.getId()); } JSONObject jsonObject = JSON.parseObject(startAddress); - tOrder.setStartAddress(jsonObject.getString("address")); + String address = jsonObject.getString("address"); + address = address.replaceAll("& #40;", "("); + address = address.replaceAll("& #41;", ")"); + tOrder.setStartAddress(address); tOrder.setStartLat(jsonObject.getString("lat")); tOrder.setStartLng(jsonObject.getString("lon")); tOrder.setSource(3); if(ToolUtil.isNotEmpty(endAddress)){ jsonObject = JSON.parseObject(endAddress); - tOrder.setEndAddress(jsonObject.getString("address")); + String address1 = jsonObject.getString("address"); + address1 = address1.replaceAll("& #40;", "("); + address1 = address1.replaceAll("& #41;", ")"); + tOrder.setEndAddress(address1); tOrder.setEndLat(jsonObject.getString("lat")); tOrder.setEndLng(jsonObject.getString("lon")); } @@ -399,35 +436,350 @@ return ResultUtil.error("获取预估距离出错", ""); } d = Double.valueOf(distance.get("distance")) / 1000; - order.setEstimatedMileage(d); - order.setEstimatedTime(Integer.valueOf(distance.get("duration")) / 60); + tOrder.setEstimatedMileage(d); + tOrder.setEstimatedTime(Integer.valueOf(distance.get("duration")) / 60); } String city = ""; - District geocode = MapUtil.geocode(order.getStartLng(), order.getStartLat()); + District geocode = MapUtil.geocode(tOrder.getStartLng(), tOrder.getStartLat()); if(null != geocode){ WeatherCity weatherCity = weatherCityService.selectOne(new EntityWrapper<WeatherCity>() .where("'" + geocode.getCity() + "' like CONCAT('%', city, '%') and '" + geocode.getDistrict() + "' like CONCAT('%', district, '%') ")); city = null != weatherCity ? weatherCity.getId().toString() : ""; } - order = getOrderPrice(1, d, 0, order, city); - order.setState(null == order.getDriverId() ? 101 : 102); - order.setStatus(1); - order.setCreateTime(new Date()); - this.insert(order); - driverService.updateById(driver); + tOrder = getOrderPrice(1, d, 0, tOrder, city); + tOrder.setState(101); + tOrder.setStatus(1); + tOrder.setCreateTime(new Date()); + this.insert(tOrder); //推送状态 - if(null != order.getDriverId()){ - pushUtil.pushOrderStatus(uid, 2, order.getId(), order.getStatus()); - }else{ - //开始推单 - Order finalOrder = order; - new Thread(new Runnable() { + pushOrder(tOrder); + return ResultUtil.success(); + } + + + + /** + * 获取订单价格 + * @param type 计算类型(1=预估价,2=订单费) + * @param distance 行驶公里 + * @param waitTime 等待时长 + * @param order 订单数据 + * @param city 查询天气的城市 + * @return + */ + public TOrder getOrderPrice(Integer type, Double distance, Integer waitTime, TOrder order, String city){ + order = getOrderInitialPrice(order); + TSystemConfig systemConfig = systemConfigService.selectOne(new EntityWrapper<TSystemConfig>().eq("type", 5)); + if(null == systemConfig){ + if(type == 1){//预估金额 + order.setEstimatedPrice(new BigDecimal(0)); + } + if(type == 2){//订单金额 + order.setOrderMoney(new BigDecimal(0)); + } + return order; + } + JSONObject jsonObject = JSON.parseObject(systemConfig.getContent()); + JSONArray chargeStandard = jsonObject.getJSONArray("ChargeStandard"); + JSONObject extraCost = jsonObject.getJSONObject("ExtraCost"); + Date date = new Date(); + for (int i = 0; i < chargeStandard.size(); i++) { + JSONObject jsonObject1 = chargeStandard.getJSONObject(i); + String num1 = jsonObject1.getString("num1"); + String num2 = jsonObject1.getString("num2"); + Double num3 = jsonObject1.getDouble("num3");//起步里程 + Double num4 = jsonObject1.getDouble("num4");//起步价格 + Double num5 = jsonObject1.getDouble("num5");//超过公里 + Double num6 = jsonObject1.getDouble("num6");//超过num3每num5公里收取num6 + Double num7 = jsonObject1.getDouble("num7");//长途起始公里 + Double num8 = jsonObject1.getDouble("num8");//长途结束公里 + Double num9 = jsonObject1.getDouble("num9");//长途费 + Double num10 = jsonObject1.getDouble("num10");//超出长途里程每num10公里 + Double num11 = jsonObject1.getDouble("num11");//超过num8每num10公里收取num11 + + String[] split = num1.split(":"); + Calendar s = Calendar.getInstance(); + s.setTime(date); + s.set(Calendar.HOUR_OF_DAY, Integer.valueOf(split[0])); + s.set(Calendar.MINUTE, Integer.valueOf(split[1])); + s.set(Calendar.SECOND, 0); + + split = num2.split(":"); + Calendar e = Calendar.getInstance(); + e.setTime(date); + e.set(Calendar.HOUR_OF_DAY, Integer.valueOf(split[0])); + e.set(Calendar.MINUTE, Integer.valueOf(split[1])); + e.set(Calendar.SECOND, 0); + + if(date.getTime() >= s.getTimeInMillis() && date.getTime() < e.getTimeInMillis()){ + if(num3.compareTo(distance) >= 0){//起步里程内 + order.setStartDistance(distance);//起步里程 + order.setStartPrice(new BigDecimal(num4));//起步价 + }else{ + BigDecimal subtract = new BigDecimal(distance).subtract(new BigDecimal(num3));//超出起步里程 + BigDecimal divide = subtract.divide(new BigDecimal(num5), new MathContext(2, RoundingMode.HALF_EVEN)); + BigDecimal multiply = divide.multiply(new BigDecimal(num6)); + order.setStartDistance(num3);//起步里程 + order.setStartPrice(new BigDecimal(num4));//起步价 + order.setOverDriveDistance(subtract.doubleValue());//超出起步里程 + order.setOverDrivePrice(multiply);//超出起步里程费 + + //计算长途费 + if(distance.compareTo(num7) > 0){ + order.setLongDistance(num7 + "-" + num8);//长途里程 + order.setLongDistancePrice(new BigDecimal(num9));//长途费 + } + //计算长途里程超出的部分 + if(distance.compareTo(num8) > 0){ + BigDecimal subtract1 = new BigDecimal(distance).subtract(new BigDecimal(num8)); + BigDecimal divide1 = subtract1.divide(new BigDecimal(num10), new MathContext(2, RoundingMode.HALF_EVEN)); + BigDecimal multiply1 = divide1.multiply(new BigDecimal(num11)); + order.setOverLongDistance(subtract1.doubleValue());//超出长途里程 + order.setOverLongDistancePrice(multiply1);//超出长途里程费 + } + } + break; + } + } + + //计算额外费用 + Integer num1 = extraCost.getInteger("num1");//等待时长 + Double num2 = extraCost.getDouble("num2");//等待费 + Integer num3 = extraCost.getInteger("num3");//等待超出时长 + Double num4 = extraCost.getDouble("num4");//等到超出时长费用单价 X/分钟 + Double num5 = extraCost.getDouble("num5");//恶劣天气公里 + Double num6 = extraCost.getDouble("num6");//恶劣天气费 + Double num7 = extraCost.getDouble("num7");//恶劣天气超出公里 + Double num8 = extraCost.getDouble("num8");//恶劣天气超出公里单价 X/公里 + Double num9 = extraCost.getDouble("num9");//恶劣天气最高收取金额 + + //等待费用 + if(waitTime.compareTo(num1) >= 0){ + order.setWaitTime(num1);//等待时长 + order.setWaitTimePrice(new BigDecimal(num2));//等待费用 + + Integer w = waitTime - num3; + BigDecimal multiply = new BigDecimal(w).multiply(new BigDecimal(num4)); + order.setOutWaitTime(w);//等待时长超出分钟 + order.setOutWaitTimePrice(multiply);//等待时长超出费用 + } + + //恶劣天气 + systemConfig = systemConfigService.selectOne(new EntityWrapper<TSystemConfig>().eq("type", 8)); + if(null != systemConfig) { + JSONObject jsonObject1 = JSON.parseObject(systemConfig.getContent()); + Integer num11 = jsonObject1.getInteger("num1");//开启恶劣天气计价 + if(1 == num11){ + boolean badWeather = WeatherUtil.isBadWeather(city); + if(badWeather){ + order.setBadWeatherDistance(new BigDecimal(num5));//恶劣天气公里 + order.setBadWeatherPrice(new BigDecimal(num6));//恶劣天气费 + if(distance.compareTo(num7) > 0){ + BigDecimal subtract = new BigDecimal(distance).subtract(new BigDecimal(num7)); + BigDecimal multiply = subtract.multiply(new BigDecimal(num8)); + order.setOverBadWeatherDistance(subtract.doubleValue());//恶劣天气超出公里 + order.setOverBadWeatherPrice(multiply);//恶劣天气超出公里费 + } + + double add = order.getOverBadWeatherPrice().add(order.getBadWeatherPrice()).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue(); + if(num9.compareTo(add) < 0){//超出最高金额(重新调整金额) + if(num9.compareTo(num6) < 0){//如果恶劣天气费大于最高金额 + order.setBadWeatherPrice(new BigDecimal(num9));//恶劣天气费 + order.setOverBadWeatherPrice(new BigDecimal(0));//恶劣天气超出公里费 + }else{ + BigDecimal subtract = new BigDecimal(num9).subtract(new BigDecimal(add)); + order.setOverBadWeatherPrice(subtract);//恶劣天气超出公里费 + } + } + } + } + } + + + //计算折扣 + if(null != order.getUserId()){ + + } + + //计算总金额 + BigDecimal bigDecimal = order.getStartPrice().add(order.getOverDrivePrice()).add(order.getLongDistancePrice()).add(order.getOverLongDistancePrice()) + .add(order.getWaitTimePrice()).add(order.getOutWaitTimePrice()).add(order.getBadWeatherPrice()).add(order.getOverBadWeatherPrice()).subtract(order.getDiscountAmount()).setScale(2, BigDecimal.ROUND_HALF_EVEN); + + if(type == 1){//预估价 + order.setEstimatedPrice(bigDecimal); + } + if(type == 2){//订单金额 + order.setOrderMoney(bigDecimal); + } + return order; + } + + + /** + * 初始订单费用 + * @param order + * @return + */ + public TOrder getOrderInitialPrice(TOrder order){ + order.setStartDistance(0D);//起步里程 + order.setStartPrice(new BigDecimal(0));//起步价 + order.setOverDriveDistance(0D);//超出起步里程 + order.setOverDrivePrice(new BigDecimal(0));//超出起步里程费 + order.setLongDistance("");//长途里程 + order.setLongDistancePrice(new BigDecimal(0));//长途里程费 + order.setOverLongDistance(0D);//超出长途里程 + order.setOverLongDistancePrice(new BigDecimal(0));//超出长途里程费 + order.setWaitTime(0);//等待时长 + order.setWaitTimePrice(new BigDecimal(0));//等待费 + order.setOutWaitTime(0);//超出等待时长 + order.setOutWaitTimePrice(new BigDecimal(0));//超出等待时长费 + order.setBadWeatherDistance(new BigDecimal(0));//恶劣天气里程 + order.setBadWeatherPrice(new BigDecimal(0));//恶劣天气里程费 + order.setOverBadWeatherDistance(0D);//恶劣天气超出里程 + order.setOverBadWeatherPrice(new BigDecimal(0));//恶劣天气超出里程费 + order.setDiscountedPrice(new BigDecimal(0));//优惠金额 + order.setCouponId(null);//优惠券 + order.setDiscountAmount(new BigDecimal(0));//折扣优惠金额 + order.setDiscount(0D);//折扣 + return order; + } + + + + + /** + * 订单推送逻辑 + * @param order + */ + public void pushOrder(TOrder order){ + /** + * 1.先找最大推单范围内的优推司机 -》 距离最近 + * 没有1 - 》 + * 2.按照后台推送配置在范围内查找合适司机 + * 合适司:积分 > 评分 > 距离 + * 3.司机没有接单直接将订单置入大厅 + */ + TSystemConfig systemConfig = systemConfigService.selectOne(new EntityWrapper<TSystemConfig>().eq("type", 1)); + if(null == systemConfig){ + return; + } + JSONObject jsonObject = JSON.parseObject(systemConfig.getContent()); + Double num3 = jsonObject.getDouble("num3");//推单最大范围 + Integer num4 = jsonObject.getInteger("num4");//接单时间 + String startLat = order.getStartLat(); + String startLng = order.getStartLng(); + + //1 + //找到中心点 + GeoJsonPoint geoJsonPoint = new GeoJsonPoint(Double.valueOf(startLng), Double.valueOf(startLat)); + Double num = num3 / 1000;//范围公里 + //构造半径 + Distance distanceR = new Distance(num, Metrics.KILOMETERS); + //画圆 + Circle circle = new Circle(geoJsonPoint, distanceR); + // 构造query对象 + Query query = Query.query(Criteria.where("location").withinSphere(circle)); + List<Location> locations = mongoTemplate.find(query, Location.class); + List<Integer> driverIds = locations.stream().map(Location::getDriverId).collect(Collectors.toList()); + Integer driver = null; + TYouTuiDriver youTuiDriver1 = null; + if(driverIds.size() > 0){ + List<TYouTuiDriver> youTuiDrivers = youTuiDriverService.selectList(new EntityWrapper<TYouTuiDriver>().in("driverId", driverIds) + .eq("state", 2).last(" and (surplusQuantity > 0 or now() < endTime) and now() < failureTime")); + Double d = null; + for (TYouTuiDriver youTuiDriver : youTuiDrivers) { + String value = redisUtil.getValue("DRIVER" + youTuiDriver.getDriverId()); + if(ToolUtil.isEmpty(value)){ + continue; + } + Map<String, Double> distance = GeodesyUtil.getDistance(value, order.getStartLng() + "," + order.getStartLat()); + Double wgs84 = distance.get("WGS84"); + if(d == null || d.compareTo(wgs84) > 0){ + d = wgs84; + driver = youTuiDriver.getDriverId(); + youTuiDriver1 = youTuiDriver; + } + } + } + + if(null != youTuiDriver1 && youTuiDriver1.getType() == 1){ + youTuiDriver1.setSurplusQuantity(youTuiDriver1.getSurplusQuantity() - 1); + youTuiDriverService.updateById(youTuiDriver1); + } + + //开始范围查找 + if(null == driver){ + for (int i = 1; i < 4; i++) { + if(null != driver){ + break; + } + num = jsonObject.getDouble("num" + i) / 1000;//范围公里 + //构造半径 + distanceR = new Distance(num, Metrics.KILOMETERS); + //画圆 + circle = new Circle(geoJsonPoint, distanceR); + // 构造query对象 + query = Query.query(Criteria.where("location").withinSphere(circle)); + locations = mongoTemplate.find(query, Location.class); + + driverIds = locations.stream().map(Location::getDriverId).collect(Collectors.toList()); + if(driverIds.size() > 0){ + List<TDriver> drivers = tDriverMapper.selectList(new EntityWrapper<TDriver>().eq("approvalStatus", 2).eq("serverStatus", 1).eq("status", 1).in("id", driverIds)); + if(drivers.size() == 0){ + continue; + } + + Integer integral = null; + Double score = null; + Double d = null; + for (TDriver driver1 : drivers) { + if(integral == null || integral.compareTo(driver1.getIntegral()) < 0){//积分大 + integral = driver1.getIntegral(); + score = driver1.getScore(); + driver = driver1.getId(); + continue; + } + if(integral.compareTo(driver1.getIntegral()) == 0 && score.compareTo(driver1.getScore()) < 0){//积分相同对比评分 + integral = driver1.getIntegral(); + score = driver1.getScore(); + driver = driver1.getId(); + continue; + } + if(integral.compareTo(driver1.getIntegral()) == 0 && score.compareTo(driver1.getScore()) == 0){//积分相同/评分相同对比距离 + String value = redisUtil.getValue("DRIVER" + driver1.getId()); + if(ToolUtil.isEmpty(value)){ + continue; + } + Map<String, Double> distance = GeodesyUtil.getDistance(value, order.getStartLng() + "," + order.getStartLat()); + Double wgs84 = distance.get("WGS84"); + if(d == null || d.compareTo(wgs84) > 0){ + d = wgs84; + driver = driver1.getId(); + continue; + } + } + } + + } + } + } + + if(null != driver){ + pushUtil.pushGrabOrder(driver, 2, order.getId(), num4); + //创建定时任务处理订单到大厅 + new Timer().schedule(new TimerTask() { @Override public void run() { - pushOrder(finalOrder); + TOrder order1 = TOrderServiceImpl.this.selectById(order.getId()); + if(order1.getState() == 101 || order1.getState() == 201){ + order1.setHallOrder(1); + TOrderServiceImpl.this.updateById(order1); + } } - }).start(); + }, num4 * 1000); + }else{ + order.setHallOrder(1); + this.updateById(order); } - return ResultUtil.success(order.getState() == 102 ? order.getId() : null); } } -- Gitblit v1.7.1