自动派单系统核心方法
@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]);
}
}
简单实现完成