zoukankan      html  css  js  c++  java
  • 原创 派单、抢单业务简单实现

    自动派单系统核心方法

    @RestController
    @RequestMapping(value="/api/client") // 通过这里配置使下面的映射都在/users下,可去除
    @Api(description="【客户端相关api接口】")
    public class ApiClientController extends BaseApiResult {

    @Autowired
    private WeChatConfigService weChatConfigService;
    
    @Autowired
    APIBaseService apiBaseService;
    
    @Autowired
    APIUserService apiUserService;
    
    @Autowired
    APIOrderService apiOrderService;
    
    @Autowired
    APICouponService apiCouponService;
    
    
    private static Logger logger = LoggerFactory.getLogger(ApiClientController.class);
    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
    
    
    
    /**
     * 下单
     * http://localhost:8080/jiama/api/client/order?userId=1&productId=1&couponId=1&area=上海市 浦东新区&address=张江镇益江路1000号…&phone=18321758957&lon=121.54664&lat=31.22593&cars=[{'carNo': '沪A12345', 'serviceDate': '2018-04-20 12:00:00'}, {'carNo': '沪12345', 'serviceDate': '2018-04-20 12:00:00'}]
     * 注意:一辆
     * @param userId
     * @param productId
     * @param lon
     * @param lat
     * @param phone
     * @param couponId
     * @param remarks
     * @param cars  [{'carNo': 'xxxx', 'serviceDate': '2018-04-20 12:00:00'}, {'carNo': 'xxxx', 'serviceDate': '2018-04-20 12:00:00'}]
     * @return
     */
    @ApiOperation(value = "下单", response = BaseResult.class, notes = "下单")
    @RequestMapping(value = "/order", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public String order(@ApiParam(name = "userId", value = "用户id", required = true) @RequestParam String userId,
                        @ApiParam(name = "productId", value = "产品id", required = true) @RequestParam String productId,
                        @ApiParam(name = "area", value = "所在区域", required = true) @RequestParam String area,
                        @ApiParam(name = "address", value = "地址", required = true) @RequestParam String address,
                        @ApiParam(name = "phone", value = "手机号", required = true) @RequestParam String phone,
                        @ApiParam(name = "couponId", value = "优惠券id", required = false) @RequestParam(required = false) String couponId,
                        @ApiParam(name = "remarks", value = "备注", required = false) @RequestParam(required = false) String remarks,
                        @ApiParam(name = "cars", value = "车辆", required = true) @RequestParam String cars,
                        @ApiParam(name = "lon", value = "经度", required = true) @RequestParam String lon,
                        @ApiParam(name = "lat", value = "纬度", required = true) @RequestParam String lat,
                        @ApiParam(name = "shopId", value = "商铺id", required = true) @RequestParam String shopId,
                        @ApiParam(name = "koucheId", value = "权益id", required = false) @RequestParam(required = false) String koucheId){
        // 0. 校验手机号
        if (!ApiUtils.checkPhone(phone)) {
            return buildFailedResultInfo(BAD_REQUEST, "手机号不合法");
        }
        // 1. 将json转换成JSONArray获取每个车牌号并校验车牌号的格式
        logger.info(cars);
        List<CarVO> carVOS = JSONObject.parseArray(cars, CarVO.class);
        List<Long> carIds = new ArrayList<>();
        Map<String, Object> product = apiBaseService.getByParam(TableEnum.jm_product, "*", "id", productId).get(0);
    	int service_mins = (int) product.get("service_mins");
    	Date pre_service_time = null;
    	String carNo = null;
        for (CarVO carVO: carVOS) {
            carNo = carVO.getCarNo();
            pre_service_time = carVO.getServiceDate();
            if (!ApiUtils.checkCarNo(carNo)) {
                return buildFailedResultInfo(BAD_REQUEST, "车牌号不合法");
            } else if (!judgeServiceTimes(shopId, service_mins, pre_service_time)) {//判断洗车时间是否有效
            	return buildFailedResultInfo(BAD_REQUEST, "当前洗车时间无效");
    		} else {
                // 2. 判断车牌号是否在jm_car 中,如果不存在插入该车辆的信息
                List<Map<String, Object>> carList = apiBaseService.getByParam(TableEnum.jm_car, "id", "car_no", carNo);
                long carId = 0;
                if (carList != null && carList.size() > 0) {
                    carId = (int) carList.get(0).get("id");
                } else {
                	Map<String, Object> car = new HashMap<String, Object>();
                	car.put("carNo", carNo);
                	car.put("userId", userId);
                    apiUserService.saveCar(car);
                    carId = (long) car.get("id");
                }
                carIds.add(carId);
            }
        }
        // 3. 判断优惠券是否可用
        Map<String, Object> coupon = null;
        if (couponId != null && couponId.length() > 0) {
            List<Map<String, Object>> coupons = apiBaseService.getByParam(TableEnum.jm_coupon, "*", "id", couponId);
            if (coupons != null && coupons.size() > 0) {
            	coupon = coupons.get(0);
                String error = validateCoupon(coupon, Integer.parseInt(userId), Integer.parseInt(productId));
                if (StringUtils.isNotEmpty(error)) {
                    return buildFailedResultInfo(FORBIDDEN, error);
                }
            }
        }
        //判断权益是否可用
        Map<String, Object> kouche = null;
        if (koucheId != null && koucheId.length() > 0) {
        	List<Map<String, Object>> kouches = apiCouponService.getKoucheById(carNo, koucheId, productId);
        	if (kouches.size() == 0) {
        		return buildFailedResultInfo(FORBIDDEN, "无法使用该权益");
    		}
        	kouche = kouches.get(0);
    	}
        long payAmount = (long) product.get("price");
        // 保存用户订单信息
        String orderNo = ApiUtils.getRandomNo(4);
        for (int i = 0; i < carIds.size(); i++) {
            Long carId = carIds.get(i);
            final Map<String, Object> order = new HashMap<String, Object>();
            order.put("user_id", userId);
            order.put("order_no", ApiUtils.getRandomNo(4));
            order.put("area", area);
            order.put("address", address);
            order.put("phone", phone);
            order.put("product_id", productId);
            order.put("car_id", carId);
            order.put("order_status", Constants.ORDER_STATUS_INIT);
            order.put("source_id", 1);
            order.put("remarks", remarks);
            order.put("type", 0);//0到店
            order.put("pre_service_time", carVOS.get(i).getServiceDate());
            order.put("pay_amount", payAmount);
            if (i == 0) {
            	order.put("order_no", orderNo);
            	if (coupon != null) {
            		payAmount = payAmount - (int)coupon.get("price");
            		order.put("coupon_id", couponId);
            		order.put("pay_amount", payAmount);
            		//优惠券修改状态
            		Map<String, Object> pMap2 = new HashMap<String, Object>();
            		pMap2.put("id", couponId);
            		pMap2.put("status", Constants.COUPON_STATUS_USED);
            		apiBaseService.update(TableEnum.jm_coupon, pMap2, "id");
    			}
            	if (kouche != null) {
            		payAmount = payAmount - (int)kouche.get("sum");
            		order.put("kouche_id", koucheId);
            		order.put("pay_amount", payAmount);
            		//权益修改状态
            		Map<String, Object> pMap = new HashMap<String, Object>();
            		pMap.put("id", koucheId);
            		pMap.put("valid", Constants.KOUCHE_STATUS_USRD);
            		apiBaseService.update(TableEnum.jm_kouche, pMap, "id");
    			}
            }
            order.put("create_date", new Date());
            String[] shop_ids = shopId.split(",");
            StringBuilder sb = new StringBuilder();
            boolean f = false;
            for (String id : shop_ids) {
            	Map<String, Object> shop = apiBaseService.getByParam(TableEnum.jm_shop, "*", "id", id).get(0);
            	if ((int)shop.get("type") == 0) {//先判断直营店是否能分派技师并分派锁定
            		if (judgeServiceTimes(id, service_mins, pre_service_time)) {
            			logger.info("直营店"+id+"尝试分派技师,订单编号:" + orderNo);
            			Map<String, Object> rMap = getTech(Constants.TECH_LEVEL_VIP, id, pre_service_time, productId);
            			if (rMap.size() == 0) {//派单给普通技师
            				rMap = getTech(Constants.TECH_LEVEL_NORMAL, id, pre_service_time, productId);
            			}
            			if (rMap.size() > 0) {
            				logger.info("订单生成成功编号:" + orderNo + ";锁定技师结果:" + rMap.get("tech_id"));
            				order.put("technician_id", rMap.get("tech_id"));
            				order.put("shop_id", id);
            				f = true;
            				break;
            			}
    				}
            	} else {
    				sb.append(id).append(",");
    			}
    		}
            if (!f) {//直营店均未能分派技师,转加盟商
            	JedisUtils.hsetnx("orderShop", orderNo, sb.toString());
    		}
            apiOrderService.saveOrder(order, area, address, userId);
            if (payAmount <= 0) {// 直接修改订单状态,并走抢/派单逻辑
            	order.put("id", apiBaseService.getByParam(TableEnum.jm_order, "id", "order_no", orderNo).get(0).get("id"));
            	Map<String, Object> pMap = new HashMap<String, Object>();
            	pMap.put("order_no", orderNo);
            	pMap.put("order_status", Constants.ORDER_STATUS_NO_ACCEPT);
            	apiBaseService.update(TableEnum.jm_order, pMap, "order_no");
            	fixedThreadPool.execute(new Runnable() {
            		@Override
            		public void run() {
            			systemAutoAssign(order);
            		}
            	});
            }
        }
        
        return buildSuccessResultInfo(orderNo);
    }
    
       
    @ApiOperation(value = "根据经纬度获取商铺,技师等信息", response = BaseResult.class, notes = "根据经纬度获取商铺,技师等信息")
    @RequestMapping(value = "/infosBylnla", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public String getInfosBylnla(@ApiParam(name = "lon", value = "经度", required = true) @RequestParam String lon,
    		@ApiParam(name = "lat", value = "纬度", required = true) @RequestParam String lat,
    		@ApiParam(name = "product_id", value = "商品id", required = true) @RequestParam String product_id) {
    	Map<String, String> orderLocation = new HashMap<String, String>();
    	orderLocation.put("X", lat);//121.47888,31.262438;117.228117,31.830429;121.481728,31.262569
    	orderLocation.put("Y", lon);
    	List<Map<String, Object>> shopList = apiUserService.getShopForTimes();
    	//遍历商铺,先遍历直营店
    	StringBuilder shop_id = new StringBuilder();
    	for (Map<String, Object> map : shopList) {
    		if (apiOrderService.getShopForOrder(map.get("id").toString(), product_id).size() > 0) {//产品有配
    			Map<String, Object> zoneMap = apiBaseService.getByParam(TableEnum.jm_zone, "point", "id", map.get("zone_id").toString()).get(0);
    			//获取商品区域顶点
    			String partitionLocation = (String)zoneMap.get("point");
    			if (!StringUtils.isEmpty(partitionLocation)) {
    				if (MapUtils.isInPolygon(orderLocation, partitionLocation)) {//该商铺区域合适
    					shop_id.append(map.get("id")).append(",");
    				}
    			}
    		}
    	}
    	if (shop_id.length() > 0) {
    		return buildSuccessResultInfo(shop_id.toString());
    	}
        return buildFailedResultInfo(BAD_REQUEST, "所选位置不在服务范围内!");
    }
    
    @ApiOperation(value = "根据商铺日期获取可服务时间信息", response = BaseResult.class, notes = "根据商铺日期获取可服务时间信息")
    @RequestMapping(value = "/serviceTimes", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public String getServiceTimes(@ApiParam(name = "shopId", value = "商铺id", required = true) @RequestParam String shopId,
    		@ApiParam(name = "date", value = "日期", required = true) @RequestParam String date,
    		@ApiParam(name = "service_mins", value = "商品服务时长", required = true) @RequestParam int service_mins) {
    	//区域重合店铺,时间段
    	String[] shopids = shopId.split(",");
    	Set<String> times = new HashSet<String>();
    	boolean f = false;
    	int count = 0;
    	//先获取每个商品对应不可选时段
    	Map<String, Integer> map = new HashMap<String, Integer>();
    	for (int i = 0; i < shopids.length; i++) {
    		Set<String> ts = getSvTimes(shopids[i], date, service_mins);
    		if (ts == null) {
    			continue;
    		}
    		if (ts.size() == 0) {
    			return buildSuccessResultInfo(times);
    		}
    		f = true;
    		count++;
    		for (String s : ts) {
    			if (map.containsKey(s)) {
    				map.put(s, map.get(s)+1);
    			} else {
    				map.put(s, 1);
    			}
    		}
    	}
    	if (!f) {
    		return buildFailedResultInfo(BAD_REQUEST, "暂无服务技师");
    	}
    	for (Entry<String, Integer> e : map.entrySet()) {
    		if (e.getValue() == count) {
    			times.add(e.getKey());
    		}
    	}
    	return buildSuccessResultInfo(times);
    }
    
    @ApiOperation(value = "判断可服务时间true可支付", response = BaseResult.class, notes = "判断可服务时间")
    @RequestMapping(value = "/judgeServiceTime", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public String judgeServiceTime(@ApiParam(name = "shopId", value = "商铺id", required = true) @RequestParam String shopId,
    		@ApiParam(name = "service_mins", value = "商品服务时长", required = true) @RequestParam int service_mins,
    		@ApiParam(name = "pre_service_time", value = "洗车时间", required = true) @RequestParam long pre_service_time) {
    	List<Map<String, Object>> techList = apiUserService.getTechForTimes(shopId);
    	//获取同一时间待服务中订单是否大于等于技师数量
    	if (techList.size() > 0) {
    		String[] pre_service = DateUtils.formatDate(new Date(pre_service_time), "yyyy-MM-dd HH:mm").split("\s");
    		List<Map<String, Object>> preTimeList = apiOrderService.getOrderByNum(shopId, techList.size(), pre_service[0]);
    		Set<String> times = new HashSet<String>();
    		for (Map<String, Object> map2 : preTimeList) {
    			int mins = (int)map2.get("service_mins");
    			Date d = (Date) map2.get("pre_service_time");
    			times.add(DateUtils.formatDate(d, "HH:mm"));
    			for (int i = 1; i < mins/30.0; i++) {
    				d = DateUtils.addMinutes(d, 30);
    				times.add(DateUtils.formatDate(d, "HH:mm"));
    			}
    			d = (Date) map2.get("pre_service_time");
    			for (int i = 1; i < service_mins/30.0; i++) {
    				d = DateUtils.addMinutes(d, -30);
    				times.add(DateUtils.formatDate(d, "HH:mm"));
    			}
    		}
    		return buildSuccessResultInfo(!times.contains(pre_service[1]));
    	}
    	return buildSuccessResultInfo(false);
    }
    
    @ApiOperation(value = "获取未过期最近的优惠券", response = BaseResult.class, notes = "获取未过期最近的优惠券")
    @RequestMapping(value = "/getLastCoupon", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public String getLastCoupon(@ApiParam(name = "userId", value = "用户id", required = true) @RequestParam String userId,
    		@ApiParam(name = "productId", value = "商品id", required = true) @RequestParam String productId){
        List<Map<String, Object>> coupons = apiCouponService.getCouponByProduct(userId, productId);
        Map<String, Object> coupon = coupons.size()>0?coupons.get(0):null;
        return buildSuccessResultInfo(coupon);
    }
    
    
    
    @ApiOperation(value = "取消订单", response = BaseResult.class, notes = "取消订单")
    @RequestMapping(value = "/cancelOrder", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public String cancelOrder(@ApiParam(name = "orderId", value = "订单id", required = true) @RequestParam String orderId,
    		@ApiParam(name = "cancelReason", value = "取消原因", required = false) @RequestParam(required = false) String cancelReason){
    	//判断该订单状态为未开始服务
    	List<Map<String, Object>> rList = apiBaseService.getByParam(TableEnum.jm_order, "*", "id", orderId);
    	if (rList.size() == 0) {
    		return buildFailedResultInfo(BAD_REQUEST, "参数错误");
    	}
    	Map<String, Object> rMap = rList.get(0);
    	int order_status = (int) rMap.get("order_status");
    	Map<String, Object> pMap = new HashMap<String, Object>();
    	pMap.put("id", orderId);
    	pMap.put("order_status", Constants.ORDER_STATUS_CANCEL);
    	try {
    		pMap.put("cancel_reason", URLDecoder.decode(cancelReason, "utf-8"));
    	} catch (UnsupportedEncodingException e) {
    		logger.info("decode_error", e);
    	}
    	if (order_status != Constants.ORDER_STATUS_IN_SERVICE && order_status != Constants.ORDER_STATUS_END_SERVICE) {//服务中,服务完成
    		apiBaseService.update(TableEnum.jm_order, pMap, "id");
    		//推送技师
    		Map<String, Object> techMap = new HashMap<String, Object>();
    		if (rMap.get("technician_id") != null) {
    			techMap = apiBaseService.getByParam(TableEnum.jm_technician, "*", "id", rMap.get("technician_id").toString()).get(0);
    			try {
    				WeiXinUtil.sendText(techMap.get("open_id").toString(), "<a href=""+Global.getConfig("techPage")+"">您有订单已取消!</a>", false);
    			} catch (Exception e) {
    				logger.info("取消订单推送技师失败", e);
    			}
    		}
    		//推送模板消息给用户已取消
    		Map<String, Object> pMap3 = new HashMap<String, Object>();
    		Map<String, Object> userMap = apiBaseService.getByParam(TableEnum.jm_user, "*", "id", rMap.get("user_id").toString()).get(0);
    		pMap3.put("openId", userMap.get("wx_open_id"));
    		pMap3.put("templateId", Global.getConfig("templateId_cancel"));
    		pMap3.put("first", "您预约的服务已取消!");
    		pMap3.put("keyword1", userMap.get("nickname"));
    		pMap3.put("keyword2", userMap.get("phone"));
    		pMap3.put("keyword3", DateUtils.formatDate((Date)rMap.get("pre_service_time"), "yyyy-MM-dd HH:mm"));
    		pMap3.put("keyword4", userMap.get("adderss"));
    		pMap3.put("keyword5", userMap.get("adderss"));
    		WeiXinUtil.sendWxTemplate(pMap3);
    		if (rMap.get("coupon_id") != null) {//退回优惠券
    			Map<String, Object> pMap2 = new HashMap<String, Object>();
    			pMap2.put("id", rMap.get("coupon_id"));
    			pMap2.put("status", Constants.COUPON_STATUS_ACTIVED);
    			apiBaseService.update(TableEnum.jm_coupon, pMap2, "id");
    		}
    		//退回权益
    		if (rMap.get("kouche_id") != null) {
    			Map<String, Object> pMap2 = new HashMap<String, Object>();
    			pMap2.put("id", rMap.get("kouche_id"));
    			pMap2.put("valid", Constants.KOUCHE_STATUS_NOUSE);
    			apiBaseService.update(TableEnum.jm_kouche, pMap2, "id");
    		}
    	} else {
    		return buildFailedResultInfo(BAD_REQUEST, "无法取消");
    	}
        return buildSuccessResultInfo();
    }
    
    // 我的订单
    @ApiOperation(value = "我的订单列表", response = BaseResult.class, notes = "我的订单列表")
    @RequestMapping(value = "/orders", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public String getMyOrders(@ApiParam(name = "userId", value = "用户id", required = true) @RequestParam String userId,
                              @ApiParam(name = "orderStatus", value = "订单状态", required = false) @RequestParam(required = false) String orderStatus) {
    	List<Map<String, Object>> rList = null;
    	if (orderStatus == null) {
    		rList = apiOrderService.getMyOrder(userId);
    	} else {
    		rList = apiOrderService.getMyOrderByStatus(userId, orderStatus);
    	}
    	for (Map<String, Object> map : rList) {
    		map.put("now", new Date());
    		map.put("end_time", DateUtils.addMinutes((Date)map.get("create_date"), Integer.valueOf(Global.getConfig("pay_time"))));
    		List<Map<String, Object>> rList2 = apiOrderService.getEvaluate(userId, map.get("id").toString());
    		map.put("evaluate", false);
    		if (rList2.size() > 0) {//已评价
    			map.put("evaluate", true);
    		}
    	}
        return buildSuccessResultInfo(rList);
    }
    
    /*@ApiOperation(value = "车辆报告", response = BaseResult.class, notes = "车辆报告")
    @RequestMapping(value = "/carReport", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public String carReport(HttpServletRequest request, HttpServletResponse response,
                              @ApiParam(name = "orderId", value = "车辆id", required = true) @RequestParam long orderId) {
    	CarReport carReport = carReportService.findUniqueByProperty("order_id", orderId);
    
        return buildSuccessResultInfo(carReport);
    }
    
    
    // 参考漫鱼 OneStepOrderAction.java
    @RequestMapping(value = "/payment", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public String payment() {
        // 支付宝支付、微信支付
        // 返回支付地址供前端调用
        return null;
    }
    */
    @RequestMapping(value = "/wechat/pay/callback", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public void wechatPayNotify(@RequestBody String callBackData, HttpServletResponse response) throws IOException, DocumentException {
    	logger.info("微信支付回调开始....返回数据:" + callBackData);
    	SortedMap<String, String> smap = dom4jXMLParse(callBackData);
    	
    	Map<String, Object> rMap = new HashMap<String, Object>();
    	if ("SUCCESS".equals(smap.get("return_code").toString())) {//支付成功
    		//MD5验证
    		if (!isWechatSign(smap, Global.getConfig("MY_WEBCHAT_APPKEY"))) {
    	    	String resXml = "<xml>"
    					+ "<return_code>FAIL</return_code>"
    					+ "<return_msg>签名失败</return_msg>"
    					+ "</xml>";
    	    	BufferedOutputStream out = new BufferedOutputStream(
                        response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
                return;
    		}
    		
    		// 修改订单状态,更新微信订单号,实际支付金额,支付完成时间
    		String orderNo = smap.get("out_trade_no");
    		logger.info("****************************************支付回掉订单号:"+orderNo);
    		
    		List<Map<String, Object>> orderList = apiBaseService.getByParam(TableEnum.jm_order, "*", "order_no", orderNo);
    		if (orderList.size() == 0) {
    	    	String resXml = "<xml>"
    					+ "<return_code>FAIL</return_code>"
    					+ "<return_msg>订单号错误</return_msg>"
    					+ "</xml>";
    	    	BufferedOutputStream out = new BufferedOutputStream(
                        response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
                return;
    		}
    		final Map<String, Object> order = orderList.get(0);
    		Map<String, Object> pMap = new HashMap<String, Object>();
    		pMap.put("order_no", orderNo);
    		pMap.put("wx_order_no", smap.get("transaction_id"));
    		pMap.put("real_pay_amount", smap.get("cash_fee"));
    		pMap.put("pay_time", smap.get("time_end"));
    		pMap.put("order_status", Constants.ORDER_STATUS_NO_ACCEPT);
    		apiBaseService.update(TableEnum.jm_order, pMap, "order_no");
    		// 如果使用了优惠券,将优惠券的状态改成已使用2
    		/*if (order.get("coupon_id") != null) {
    			int couponId = (int) order.get("coupon_id");
    			Map<String, Object> pMap2 = new HashMap<String, Object>();
        		pMap2.put("id", couponId);
        		pMap2.put("status", Constants.COUPON_STATUS_USED);
        		apiBaseService.update(TableEnum.jm_coupon, pMap2, "id");
    		}*/
    		// 如果支付成功,根据规则安排相应的技师处理,并通知技师(在微信公众号中给用户推送通知) 参考派单原则(原型)
    		fixedThreadPool.execute(new Runnable() {
    			@Override
    			public void run() {
    				systemAutoAssign(order);
    			}
    		});
    		rMap.put("return_code", "SUCCESS");
    		String resXml = "<xml>"
    				+ "<return_code>SUCCESS</return_code>"
    				+ "<return_msg>OK</return_msg>"
    				+ "</xml>";
        	BufferedOutputStream out = new BufferedOutputStream(
                    response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
            return;
    	}
    	String resXml = "<xml>"
    			+ "<return_code>FAIL</return_code>"
    			+ "<return_msg>支付失败</return_msg>"
    			+ "</xml>";
    	BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
        return;
    }
    
    @SuppressWarnings("rawtypes")
    private static SortedMap<String, String> dom4jXMLParse(String strXML) throws DocumentException {
    	SortedMap<String, String> smap = new TreeMap<String, String>();
    	Document doc = DocumentHelper.parseText(strXML);
    	Element root = doc.getRootElement();
    	for (Iterator iterator = root.elementIterator(); iterator.hasNext();) {
    		Element e = (Element) iterator.next();
    		smap.put(e.getName(), e.getText());
    	}
    	return smap;
    }
    
    @SuppressWarnings("rawtypes")
    public static boolean isWechatSign(SortedMap<String, String> smap,String apiKey) {
        StringBuffer sb = new StringBuffer();
        Set es = smap.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (!"sign".equals(k) && null != v && !"".equals(v) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + apiKey);
        /** 验证的签名 */
        String sign = EncryptHelp.getMD5Str(sb.toString());
        /** 微信端返回的合法签名 */
        String validSign = smap.get("sign").toUpperCase();
        return validSign.equals(sign);
    }
    
    // 系统自动派单
    public void systemAutoAssign(Map<String, Object> order) {
        // 根据shop_id查找对应商铺并查找出对应技师
    	Date pre_service_time = (Date) order.get("pre_service_time");
    	String productId = order.get("product_id").toString();
    	String orderId = order.get("id").toString();
    	String orderNo = order.get("order_no").toString();
    	//判断商铺是否是加盟商
    	if (order.get("technician_id") == null) {
    		boolean f = false;
    		String shopId = JedisUtils.hget("orderShop", orderNo);
    		String[] shop_ids = shopId.split(",");
    		logger.info("抢单开始,订单号:" + orderNo);
    		for (String id: shop_ids) {
    			//获取可选技师
    			Set<String> rSet = getTechForComplete(id, pre_service_time, productId);
    			logger.info("抢单订单号:" + orderNo + ";抢单商铺"+id+",技师数量结果:" + rSet.size());
    			StringBuilder sb = new StringBuilder();
    			for (String s : rSet) {
    				sb.append(s).append(",");
    				Map<String, Object> vipTech = apiBaseService.getByParam(TableEnum.jm_technician, "*", "id", s).get(0);
    				if (1 == (int)vipTech.get("is_vip")) {//vip技师
    					f = true;
    					try {
    						WeiXinUtil.sendText(vipTech.get("open_id").toString(), "<a href=""+Global.getConfig("completePage")+"?user_id="+s+"&order_id="+orderId+"">有新的订单了!点击抢单!</a>", false);
    					} catch (Exception e) {
    						logger.info("抢单推送技师失败", e);
    					}
    					JedisUtils.set("complete_" + orderId, id, 600);
    				}
    			}
    			JedisUtils.hsetnx("tid_"+orderId, id, sb.toString());
    			JedisUtils.expire("tid_"+orderId, 3600);
    		}
    		if (!f) {
    			String[] cs = JedisUtils.get("customer_service").split(",");
    			try {
    				for (int i = 0; i < cs.length; i++) {
    					WeiXinUtil.sendText(cs[i], "有未派单抢单!", false);
    				}
    			} catch (Exception e) {
    				logger.info("抢单推送运营失败", e);
    			}
    		}
    	} else {
    		String technician_id = order.get("technician_id").toString();
    		logger.info("支付成功推送技师,订单号:" + orderId + "技师id:"+ technician_id);
    		Map<String, Object> techMap = apiBaseService.getByParam(TableEnum.jm_technician, "*", "id", technician_id).get(0);
    		try {
    			WeiXinUtil.sendText(techMap.get("open_id").toString(), "<a href=""+Global.getConfig("techPage")+"">您好,您有新的服务订单!</a>", false);
    		} catch (Exception e) {
    			logger.info("派单推送技师失败", e);
    		}
    		//推送模板消息给用户,已派单
    		Map<String, Object> pMap3 = new HashMap<String, Object>();
    		Map<String, Object> userMap = apiBaseService.getByParam(TableEnum.jm_user, "*", "id", order.get("user_id").toString()).get(0);
    		pMap3.put("openId", userMap.get("wx_open_id"));
    		pMap3.put("templateId", Global.getConfig("templateId_assign"));
    		pMap3.put("first", "您好,您的订单已接单!");
    		pMap3.put("keyword1", techMap.get("name"));
    		pMap3.put("keyword2", techMap.get("phone"));
    		pMap3.put("keyword3", DateUtils.formatDate(pre_service_time, "yyyy-MM-dd HH:mm"));
    		WeiXinUtil.sendWxTemplate(pMap3);
    	}
    }
    
        
    @ApiOperation(value = "派单成功推送客户模板消息", response = BaseResult.class, notes = "派单成功推送客户模板消息")
    @RequestMapping(value = "/sendUserTemp", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public String sendUserTemp(@ApiParam(name = "orderId", value = "订单id", required = true) @RequestParam String orderId,
    		@ApiParam(name = "state", value = "模板类型1取消,2完成,3接单", required = true) @RequestParam int state) throws Exception {
    	Map<String, Object> orderMap = apiBaseService.getByParam(TableEnum.jm_order, "*", "id", orderId).get(0);
    	Map<String, Object> userMap = apiBaseService.getByParam(TableEnum.jm_user, "*", "id", orderMap.get("user_id").toString()).get(0);
    	Map<String, Object> pMap3 = new HashMap<String, Object>();
    	if (1 == state) {
    		pMap3.put("openId", userMap.get("wx_open_id"));
    		pMap3.put("templateId", Global.getConfig("templateId_cancel"));
    		pMap3.put("first", "您预约的服务已取消!");
    		pMap3.put("keyword1", userMap.get("nickname"));
    		pMap3.put("keyword2", userMap.get("phone"));
    		pMap3.put("keyword3", DateUtils.formatDate((Date)orderMap.get("pre_service_time"), "yyyy-MM-dd HH:mm"));
    		pMap3.put("keyword4", userMap.get("adderss"));
    		pMap3.put("keyword5", userMap.get("adderss"));
    	} else if (2 == state) {
    		pMap3.put("openId", userMap.get("wx_open_id"));
    		pMap3.put("templateId", Global.getConfig("templateId_end"));
    		pMap3.put("first", "服务已完成,感谢您选择甲马服务!");
    		pMap3.put("keyword1", DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
    		pMap3.put("keyword2", orderMap.get("order_no"));
    	} else {
    		pMap3.put("openId", userMap.get("wx_open_id"));
    		pMap3.put("templateId", Global.getConfig("templateId_assign"));
    		pMap3.put("first", "您好,您的订单已接单!");
    		Map<String, Object> techMap = apiBaseService.getByParam(TableEnum.jm_technician, "*", "id", orderMap.get("technician_id").toString()).get(0);
    		pMap3.put("keyword1", techMap.get("name"));
    		pMap3.put("keyword2", techMap.get("phone"));
    		pMap3.put("keyword3", DateUtils.formatDate((Date)orderMap.get("pre_service_time"), "yyyy-MM-dd HH:mm"));
    	}
    	WeiXinUtil.sendWxTemplate(pMap3);
    	return buildSuccessResultInfo();
    }
    
        
    private String validateCoupon(Map<String, Object> coupon, Integer userId, Integer productId){
        if (coupon == null) {
            return "优惠券不存在";
        }
        // 判断优惠券是否存并且是未激活状态
        Integer status = (Integer) coupon.get("status");
        if (status == Constants.COUPON_STATUS_NOT_ACTIVE) {
        	return  "优惠券尚未绑定";
        } else if (status == Constants.COUPON_STATUS_USED) {
        	return  "优惠券已使用";
        }
        // 判断时间段
        Date beginTime = (Date) coupon.get("begin_time");
        Date endTime = (Date) coupon.get("end_time");
        Date now = new Date();
        if (!DateUtils.isInRange(beginTime, now, endTime)) {
        	return  "该时间段不允许使用此优惠券";
        }
        // 如果优惠码指定某个用户使用还要校验是否为该用户
        Integer userIdForCoupon = (Integer) coupon.get("user_id");
        if (userIdForCoupon == null) {
        	return  "优惠券尚未绑定用户";
        } else if(userIdForCoupon - userId != 0){
        	return  "优惠券绑定用户不匹配";
        }
        if (coupon.get("product_id") != null) {
            Integer productID = (Integer) coupon.get("product_id");
            if (productID - productId != 0) {
            	return  "该服务不能使用该优惠券";
            }
        }
    
        return null;
    }
    
    private Map<String, Object> getTech(String level, String shopId, Date pre_service_time, String productId) {
    	Map<String, Object> rMap = new HashMap<String, Object>();
    	List<Map<String, Object>> techList = apiUserService.getTechByLevelForOrder(shopId, level, DateUtils.formatDate(pre_service_time, "yyyy-MM-dd HH:mm:ss"));
    	if (techList.size() > 0) {
    		List<Map<String, Object>> techList2 = apiUserService.getTechByLevelForOrder2(shopId, level, DateUtils.formatDate(pre_service_time, "yyyy-MM-dd"));
    		if (techList2.size() > 0) {//该预约时间之前无订单及之后无订单
    			rMap.put("tech_id", techList2.get(0).get("id").toString());
    			rMap.put("open_id", techList2.get(0).get("open_id").toString());
    			rMap.put("name", techList2.get(0).get("name").toString());
    			rMap.put("phone", techList2.get(0).get("phone").toString());
    		} else {
    			//有订单的技师排序
    			List<String> techIds = new ArrayList<String>();
    			for (Map<String, Object> map : techList) {
    				techIds.add(map.get("id").toString());
    			}
    			Map<String, Object> pMap = new HashMap<String, Object>();
    			pMap.put("techIds", techIds);
    			pMap.put("date", DateUtils.formatDate(pre_service_time, "yyyy-MM-dd"));
    			List<Map<String, Object>> techList3 =  apiUserService.getTechOrderNum(pMap);
    			Map<String, Object> productMap = apiBaseService.getByParam(TableEnum.jm_product, "*", "id", productId).get(0);
    			int service_mins = (int) productMap.get("service_mins");
    			Date service_end = DateUtils.addMinutes(pre_service_time, service_mins);
    			for (Map<String, Object> map : techList3) {
    				String t_id = map.get("technician_id").toString();
    				Map<String, Object> techMap = apiBaseService.getByParam(TableEnum.jm_technician, "*", "id", t_id).get(0);
    				String workTime = (String) techMap.get("service_time");
    				if (!ApiUtils.judgeWorkTime(workTime, pre_service_time) || (int)techMap.get("status") == 2 || techMap.get("open_id") == null) {
    					continue;
    				}
    				//获取洗车结束时间内有无订单
    				List<Map<String, Object>> orders = apiUserService.getTechByLevelForOrder3(t_id, DateUtils.formatDate(service_end, "yyyy-MM-dd HH:mm:ss"));
    				if (orders.size() == 0) {
    					rMap.put("tech_id", t_id);
    					rMap.put("open_id", techMap.get("open_id").toString());
    					rMap.put("name", techMap.get("name").toString());
    					rMap.put("phone", techMap.get("phone").toString());
    					break;
    				} else {//查看最后一单时间是否合适
    					Map<String, Object> od = orders.get(0);
    					Date d1 = DateUtils.addMinutes((Date)od.get("pre_service_time"), (int)od.get("service_mins"));
    					if (d1.before(pre_service_time)) {//上一单时间不超出预约时间
    						rMap.put("tech_id", t_id);
    						rMap.put("open_id", techMap.get("open_id").toString());
    						rMap.put("name", techMap.get("name").toString());
    						rMap.put("phone", techMap.get("phone").toString());
    						break;
    					}
    				}
    			}
    		}
    	}
    	
    	return rMap;
    }
    
    private Set<String> getTechForComplete(String shopId, Date pre_service_time, String productId) {
    	Set<String> idSet = new HashSet<String>();
    	List<Map<String, Object>> techList = apiUserService.getTechForOrder(shopId, DateUtils.formatDate(pre_service_time, "yyyy-MM-dd HH:mm:ss"));
    	if (techList.size() > 0) {
    		List<Map<String, Object>> techList2 = apiUserService.getTechForOrder2(shopId, DateUtils.formatDate(pre_service_time, "yyyy-MM-dd"));
    		if (techList2.size() > 0) {//该预约时间之前无订单及之后无订单
    			for (Map<String, Object> map : techList2) {
    				if (map.get("open_id") != null) {
    					idSet.add(map.get("id").toString());
    				}
    			}
    		}
    		//有订单的技师排序
    		List<String> techIds = new ArrayList<String>();
    		for (Map<String, Object> map : techList) {
    			techIds.add(map.get("id").toString());
    		}
    		Map<String, Object> pMap = new HashMap<String, Object>();
    		pMap.put("techIds", techIds);
    		pMap.put("date", DateUtils.formatDate(pre_service_time, "yyyy-MM-dd"));
    		List<Map<String, Object>> techList3 =  apiUserService.getTechOrderNum(pMap);
    		Map<String, Object> productMap = apiBaseService.getByParam(TableEnum.jm_product, "*", "id", productId).get(0);
    		int service_mins = (int) productMap.get("service_mins");
    		Date service_end = DateUtils.addMinutes(pre_service_time, service_mins);
    		for (Map<String, Object> map : techList3) {
    			String t_id = map.get("technician_id").toString();
    			Map<String, Object> techMap = apiBaseService.getByParam(TableEnum.jm_technician, "*", "id", t_id).get(0);
    			String workTime = (String) techMap.get("service_time");
    			if (!ApiUtils.judgeWorkTime(workTime, pre_service_time) || (int)techMap.get("status") == 2 || techMap.get("open_id") == null) {
    				continue;
    			}
    			//获取洗车结束时间内有无订单
    			List<Map<String, Object>> orders = apiUserService.getTechByLevelForOrder3(t_id, DateUtils.formatDate(service_end, "yyyy-MM-dd HH:mm:ss"));
    			if (orders.size() == 0) {
    				idSet.add(techMap.get("id").toString());
    			} else {//查看最后一单时间是否合适
    				Map<String, Object> od = orders.get(0);
    				Date d1 = DateUtils.addMinutes((Date)od.get("pre_service_time"), (int)od.get("service_mins"));
    				if (d1.before(pre_service_time)) {//上一单时间不超出预约时间
    					idSet.add(techMap.get("id").toString());
    				}
    			}
    		}
    	}
    	return idSet;
    }
    
    private boolean judgeServiceTimes(String shopId, int service_mins, Date pre_service_time) {
    	String[] shopids = shopId.split(",");
    	Set<String> times = new HashSet<String>();
    	int count = 0;
    	//先获取每个商品对应不可选时段
    	Map<String, Integer> map = new HashMap<String, Integer>();
    	boolean flag = false;
    	String[] pre_service = DateUtils.formatDate(pre_service_time, "yyyy-MM-dd HH:mm").split("\s");
    	for (int i = 0; i < shopids.length; i++) {
    		Set<String> ts = getSvTimes(shopids[i], pre_service[0], service_mins);
    		if (ts == null) {
    			continue;
    		}
    		if (ts.size() == 0) {
    			return true;
    		}
    		flag = true;
    		count++;
    		for (String s : ts) {
    			if (map.containsKey(s)) {
    				map.put(s, map.get(s)+1);
    			} else {
    				map.put(s, 1);
    			}
    		}
    	}
    	if (!flag) {
    		return false;
    	}
    	for (Entry<String, Integer> e : map.entrySet()) {
    		if (e.getValue() == count) {
    			times.add(e.getKey());
    		}
    	}
    	return !times.contains(pre_service[1]);
    }
    
    
    }
    

    简单实现完成

    化繁为简,极致高效。 所有代码为本人原创,转载请联系本人。
  • 相关阅读:
    安装kafka
    linux安装jdk
    rabbitmq
    企业级docker镜像仓库----Harbor高可用部署
    kubernetes基础概念理解
    kubeadm安装kubernetes集群v1.14.3
    salt-stack深入学习
    salt-stack的数据系统Pillars
    salt-stack的数据系统Grains
    salt-stack
  • 原文地址:https://www.cnblogs.com/crissblog/p/14861912.html
Copyright © 2011-2022 走看看