自動派單系統核心方法
@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]);
}
}
簡單實現完成
