puzhibing
2023-02-17 d6955542a70118191d51046fc0c2489d6039e180
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
package com.supersavedriving.driver.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;
import com.supersavedriving.driver.modular.system.dao.OrderMapper;
import com.supersavedriving.driver.modular.system.model.*;
import com.supersavedriving.driver.modular.system.service.*;
import com.supersavedriving.driver.modular.system.util.GaoDe.MapUtil;
import com.supersavedriving.driver.modular.system.util.GeodesyUtil;
import com.supersavedriving.driver.modular.system.util.PushUtil;
import com.supersavedriving.driver.modular.system.util.ResultUtil;
import com.supersavedriving.driver.modular.system.util.UUIDUtil;
import com.supersavedriving.driver.modular.system.util.mongodb.model.Location;
import com.supersavedriving.driver.modular.system.warpper.AddOrderWarpper;
import com.supersavedriving.driver.modular.system.warpper.HallOrderList;
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 java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
 
 
/**
* 订单
* @author pzb
* @Date 2023/2/16 15:57
*/
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
 
    @Autowired
    private IDriverWorkService driverWorkService;
 
    @Autowired
    private IDriverService driverService;
 
    @Autowired
    private ISystemConfigService systemConfigService;
 
    @Autowired
    private PushUtil pushUtil;
 
    @Autowired
    private MongoTemplate mongoTemplate;
 
    @Autowired
    private IAppUserService appUserService;
 
 
 
 
 
    /**
     * 获取服务中的订单id
     * @param uid
     * @return
     * @throws Exception
     */
    @Override
    public Long queryDriverServerOrder(Integer uid) throws Exception {
        Order order = this.selectOne(new EntityWrapper<Order>().eq("driverId", uid).eq("status", 1).in("state", Arrays.asList(102, 103, 104, 105, 201)));
        if(null != order){
            return order.getId();
        }
        return 0L;
    }
 
 
    /**
     * 司机代客下单
     * @param uid
     * @param addOrderWarpper
     * @return
     * @throws Exception
     */
    @Override
    public ResultUtil driverAddOrder(Integer uid, AddOrderWarpper addOrderWarpper) throws Exception {
        /**
         * 司机上线且空闲,下单直接给当前司机,其余进大厅
         * 司机下的订单不需要创建新用户,且只能走线下支付
         */
 
        int count = this.selectCount(new EntityWrapper<Order>().eq("userPhone", addOrderWarpper.getPhone()).eq("status", 1).in("state", Arrays.asList(101, 102, 103, 104, 105, 106, 201)));
        if(count > 0){
            return ResultUtil.error("该用户还有未完成的订单");
        }
        Driver driver = driverService.selectById(uid);
        DriverWork driverWork = driverWorkService.selectOne(new EntityWrapper<DriverWork>().eq("driverId", uid).eq("status", 1));
        Order order1 = this.selectOne(new EntityWrapper<Order>().eq("driverId", uid).eq("status", 1).in("state", Arrays.asList(102, 103, 104, 105, 201)));
        Order order = new Order();
        if(driverWork != null && null == order1){
            order.setDriverId(uid);
            driver.setServerStatus(2);
        }
        order.setCode(UUIDUtil.getTimeStr() + UUIDUtil.getNumberRandom(3));
        order.setSource(2);
 
        AppUser appUser = appUserService.selectOne(new EntityWrapper<AppUser>().eq("phone", addOrderWarpper.getPhone()).eq("status", 1));
        if(null != appUser){
            order.setUserId(appUser.getId());
        }
        order.setUserName(addOrderWarpper.getUserName());
        order.setUserPhone(addOrderWarpper.getPhone());
        order.setAgentId(driver.getAgentId());
        order.setBranchOfficeId(driver.getBranchOfficeId());
        order.setStartAddress(addOrderWarpper.getStartAddress());
        order.setStartLat(addOrderWarpper.getStartLat());
        order.setStartLng(addOrderWarpper.getStartLng());
        order.setEndAddress(addOrderWarpper.getEndAddress());
        order.setEndLat(addOrderWarpper.getEndLat());
        order.setEndLng(addOrderWarpper.getEndLng());
        Map<String, String> distance = MapUtil.getDistance(order.getStartLng() + "," + order.getStartLat(), order.getEndLng() + "," + order.getEndLat(), 1);
        if(null == distance){
            return ResultUtil.error("获取预估距离出错");
        }
        Double d = Double.valueOf(distance.get("distance")) / 1000;
        order.setEstimatedMileage(d);
        order = getOrderPrice(1, d, 0, order);
        order.setHallOrder(0);
        order.setState(null == order.getDriverId() ? 101 : 102);
        order.setStatus(1);
        order.setCreateTime(new Date());
        this.insert(order);
        driverService.updateById(driver);
        //推送状态
        if(null != order.getDriverId()){
            pushUtil.pushOrderStatus(uid, 2, order.getId(), order.getStatus());
        }else{
            //开始推单
            pushOrder(order);
        }
        return ResultUtil.success();
    }
 
 
    /**
     * 获取订单价格
     * @param type
     * @param distance
     * @param waitTime
     * @param order
     * @return
     */
    public Order getOrderPrice(Integer type, Double distance, Integer waitTime, Order order){
        order = getOrderInitialPrice(order);
        SystemConfig systemConfig = systemConfigService.selectOne(new EntityWrapper<SystemConfig>().eq("type", 5));
        if(null == systemConfig){
            if(type == 1){//预估金额
                order.setEstimatedPrice(0D);
            }
            if(type == 2){//订单金额
                order.setOrderMoney(0D);
            }
            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(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(num4);//起步价
                    order.setOverDriveDistance(subtract.doubleValue());//超出起步里程
                    order.setOverDrivePrice(multiply.doubleValue());//超出起步里程费
 
                    //计算长途费
                    if(distance.compareTo(num7) > 0){
                        order.setLongDistance(num7 + "-" + num8);//长途里程
                        order.setLongDistancePrice(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.doubleValue());//超出长途里程费
                    }
                }
                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(num2);//等待费用
 
            Integer w = waitTime - num3;
            BigDecimal multiply = new BigDecimal(w).multiply(new BigDecimal(num4));
            order.setOutWaitTime(w);//等待时长超出分钟
            order.setOutWaitTimePrice(multiply.doubleValue());//等待时长超出费用
        }
 
        //恶劣天气
        if(true){
            order.setBadWeatherDistance(num5);//恶劣天气公里
            order.setBadWeatherPrice(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.doubleValue());//恶劣天气超出公里费
            }
 
            double add = new BigDecimal(order.getOverBadWeatherPrice()).add(new BigDecimal(order.getBadWeatherPrice())).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
            if(num9.compareTo(add) < 0){//超出最高金额(重新调整金额)
                if(num9.compareTo(num6) < 0){//如果恶劣天气费大于最高金额
                    order.setBadWeatherPrice(num9);//恶劣天气费
                    order.setOverBadWeatherPrice(0D);//恶劣天气超出公里费
                }else{
                    BigDecimal subtract = new BigDecimal(num9).subtract(new BigDecimal(add));
                    order.setOverBadWeatherPrice(subtract.doubleValue());//恶劣天气超出公里费
                }
            }
        }
 
        //计算总金额
        BigDecimal bigDecimal = new BigDecimal(order.getStartPrice() + order.getOverDrivePrice() + order.getLongDistancePrice() + order.getOverLongDistancePrice() +
                order.getWaitTimePrice() + order.getOutWaitTimePrice() + order.getBadWeatherPrice() + order.getOverBadWeatherPrice()).setScale(2, BigDecimal.ROUND_HALF_EVEN);
        if(type == 1){//预估价
            order.setEstimatedPrice(bigDecimal.doubleValue());
        }
        if(type == 2){//订单金额
            order.setOrderMoney(bigDecimal.doubleValue());
        }
        return order;
    }
 
 
    /**
     * 初始订单费用
     * @param order
     * @return
     */
    public Order getOrderInitialPrice(Order order){
        order.setStartDistance(0D);//起步里程
        order.setStartPrice(0D);//起步价
        order.setOverDriveDistance(0D);//超出起步里程
        order.setOverDrivePrice(0D);//超出起步里程费
        order.setLongDistance("");//长途里程
        order.setLongDistancePrice(0D);//长途里程费
        order.setOverLongDistance(0D);//超出长途里程
        order.setOverLongDistancePrice(0d);//超出长途里程费
        order.setWaitTime(0);//等待时长
        order.setWaitTimePrice(0D);//等待费
        order.setOutWaitTime(0);//超出等待时长
        order.setOutWaitTimePrice(0D);//超出等待时长费
        order.setBadWeatherDistance(0D);//恶劣天气里程
        order.setBadWeatherPrice(0D);//恶劣天气里程费
        order.setOverBadWeatherDistance(0D);//恶劣天气超出里程
        order.setOverBadWeatherPrice(0D);//恶劣天气超出里程费
        order.setDiscountedPrice(0D);//优惠金额
        order.setCouponId(null);//优惠券
        return order;
    }
 
 
    /**
     * 订单推送逻辑
     * @param order
     */
    public void pushOrder(Order order){
        /**
         * 系统根据配置进行三轮的范围查找司机。
         * 只要找到司机就直接推出去。
         * 当推出去的司机都没有接单,直接将订单放入大厅,不再去更大范围找司机。
         */
        SystemConfig systemConfig = systemConfigService.selectOne(new EntityWrapper<SystemConfig>().eq("type", 1));
        if(null != systemConfig){
            JSONObject jsonObject = JSON.parseObject(systemConfig.getContent());
            Integer num4 = jsonObject.getInteger("num4");//接单时间
            String startLat = order.getStartLat();
            String startLng = order.getStartLng();
 
            //找到中心点
            GeoJsonPoint geoJsonPoint = new GeoJsonPoint(Double.valueOf(startLat), Double.valueOf(startLng));
            for (int i = 1; i < 4; i++) {
                Double num = jsonObject.getDouble("num" + i) / 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());
                if(driverIds.size() > 0){
                    List<Driver> drivers = driverService.selectList(new EntityWrapper<Driver>().eq("approvalStatus", 2).eq("serverStatus", 1).eq("status", 1).in("id", driverIds));
                    if(drivers.size() == 0){
                        continue;
                    }
 
                    for (Driver driver : drivers) {
                        pushUtil.pushGrabOrder(driver.getId(), 2, order.getId(), num4);
                    }
 
                    //创建定时任务处理订单到大厅
                    new Timer().schedule(new TimerTask() {
                        @Override
                        public void run() {
                            Order order1 = OrderServiceImpl.this.selectById(order.getId());
                            if(order1.getState() == 101){
                                order1.setHallOrder(1);
                                OrderServiceImpl.this.updateById(order1);
                            }
                        }
                    }, num4 * 1000);
                }
            }
        }
    }
 
 
 
    /**
     * 获取大厅订单列表
     * @param uid
     * @param pageNum
     * @param pageSize
     * @return
     * @throws Exception
     */
    @Override
    public List<HallOrderList> queryOrderHall(Integer uid, Integer pageNum, Integer pageSize) throws Exception {
        pageNum = (pageNum - 1) * pageSize;
        List<HallOrderList> hallOrderLists = this.baseMapper.queryOrderHall(pageNum, pageSize);
        hallOrderLists.forEach(hallOrderList -> {
            Map<String, Double> distance = GeodesyUtil.getDistance(hallOrderList.getStartLng() + "," + hallOrderList.getStartLat(), hallOrderList.getEndLng() + "," + hallOrderList.getEndLat());
            Double wgs84 = distance.get("WGS84");
            hallOrderList.setCurrentDistance(wgs84);
        });
        return hallOrderLists;
    }
}