原创 派单、抢单业务简单实现

自动派单系统核心方法

@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]);
}


}

简单实现完成

posted @ 2021-06-08 10:57  cris's  阅读(839)  评论(0编辑  收藏  举报