Authored by chenjian

Merge branch 'dev-offline-buy' into test6.8.5

package com.yohoufo.dal.product;
import com.yohoufo.dal.product.model.StoreInfo;
public interface IStoreInfoDAO {
StoreInfo selectByPrimaryKey(Integer id);
}
\ No newline at end of file
... ...
package com.yohoufo.dal.product;
import com.yohoufo.dal.product.model.StoreInfoExtend;
public interface IStoreInfoExtendDAO {
StoreInfoExtend selectByStoreId(Integer storeId);
}
\ No newline at end of file
... ...
package com.yohoufo.dal.product.model;
public class StoreInfo {
private Integer id;
private Integer storeCode;
private String storeName;
private Integer warehouseId;
private Integer createTime;
private Integer status;
private Integer updateTime;
private Integer ftpPort;
private String ftpIp;
private String ftpUser;
private String ftpPassword;
private String printerFtpIp;
private Integer printerFtpPort;
private String printerFtpUser;
private String printerFtpPassword;
private Integer wechatpayChannel;
private Integer alipayChannel;
private Integer unionMposChannel;
private Integer unionMposAppleChannel;
private Integer classId;
public String getPrinterFtpIp() {
return printerFtpIp;
}
public void setPrinterFtpIp(String printerFtpIp) {
this.printerFtpIp = printerFtpIp;
}
public Integer getPrinterFtpPort() {
return printerFtpPort;
}
public void setPrinterFtpPort(Integer printerFtpPort) {
this.printerFtpPort = printerFtpPort;
}
public String getPrinterFtpUser() {
return printerFtpUser;
}
public void setPrinterFtpUser(String printerFtpUser) {
this.printerFtpUser = printerFtpUser;
}
public String getPrinterFtpPassword() {
return printerFtpPassword;
}
public void setPrinterFtpPassword(String printerFtpPassword) {
this.printerFtpPassword = printerFtpPassword;
}
public Integer getFtpPort() {
return ftpPort;
}
public void setFtpPort(Integer ftpPort) {
this.ftpPort = ftpPort;
}
public String getFtpIp() {
return ftpIp;
}
public void setFtpIp(String ftpIp) {
this.ftpIp = ftpIp;
}
public String getFtpUser() {
return ftpUser;
}
public void setFtpUser(String ftpUser) {
this.ftpUser = ftpUser;
}
public String getFtpPassword() {
return ftpPassword;
}
public void setFtpPassword(String ftpPassword) {
this.ftpPassword = ftpPassword;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getStoreCode() {
return storeCode;
}
public void setStoreCode(Integer storeCode) {
this.storeCode = storeCode;
}
public String getStoreName() {
return storeName;
}
public void setStoreName(String storeName) {
this.storeName = storeName == null ? null : storeName.trim();
}
public Integer getWarehouseId() {
return warehouseId;
}
public void setWarehouseId(Integer warehouseId) {
this.warehouseId = warehouseId;
}
public Integer getCreateTime() {
return createTime;
}
public void setCreateTime(Integer createTime) {
this.createTime = createTime;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Integer updateTime) {
this.updateTime = updateTime;
}
public Integer getWechatpayChannel() {
return wechatpayChannel;
}
public void setWechatpayChannel(Integer wechatpayChannel) {
this.wechatpayChannel = wechatpayChannel;
}
public Integer getAlipayChannel() {
return alipayChannel;
}
public void setAlipayChannel(Integer alipayChannel) {
this.alipayChannel = alipayChannel;
}
public Integer getUnionMposChannel() {
return unionMposChannel;
}
public void setUnionMposChannel(Integer unionMposChannel) {
this.unionMposChannel = unionMposChannel;
}
public Integer getUnionMposAppleChannel() {
return unionMposAppleChannel;
}
public void setUnionMposAppleChannel(Integer unionMposAppleChannel) {
this.unionMposAppleChannel = unionMposAppleChannel;
}
public Integer getClassId() {
return classId;
}
public void setClassId(Integer classId) {
this.classId = classId;
}
}
\ No newline at end of file
... ...
package com.yohoufo.dal.product.model;
import lombok.Data;
@Data
public class StoreInfoExtend {
private Integer storeId;
private Integer regionId;
private String address;
private float longitude;
private float latitude;
private String businessTime;
private String telephone;
private String thumbnailUrl;
private String pictureUrl;
private String introduction;
private Integer createUserId;
private Integer createTime;
private Integer updateTime;
private String detail;
private Integer province;
private Integer city;
private Integer district;
private Integer signRange;
}
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.yohoufo.dal.product.IStoreInfoExtendDAO" >
<resultMap id="BaseResultMap" type="com.yohoufo.dal.product.model.StoreInfoExtend" >
<id column="store_id" property="storeId" jdbcType="INTEGER" />
<result column="region_id" property="regionId" jdbcType="INTEGER" />
<result column="address" property="address" jdbcType="VARCHAR" />
<result column="longitude" property="longitude" jdbcType="FLOAT" />
<result column="latitude" property="latitude" jdbcType="FLOAT" />
<result column="business_time" property="businessTime" jdbcType="VARCHAR" />
<result column="telephone" property="telephone" jdbcType="VARCHAR" />
<result column="thumbnail_url" property="thumbnailUrl" jdbcType="VARCHAR" />
<result column="picture_url" property="pictureUrl" jdbcType="VARCHAR" />
<result column="introduction" property="introduction" jdbcType="VARCHAR" />
<result column="create_user_id" property="createUserId" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="INTEGER" />
<result column="update_time" property="updateTime" jdbcType="INTEGER" />
<result column="province" property="province" jdbcType="INTEGER" />
<result column="city" property="city" jdbcType="INTEGER" />
<result column="district" property="district" jdbcType="INTEGER" />
<result column="sign_range" property="signRange" javaType="INTEGER" />
</resultMap>
<sql id="Base_Column_List" >
store_id, region_id, address, longitude, latitude, sign_range, business_time,
telephone, thumbnail_url, picture_url, introduction, create_user_id, create_time,
update_time,update_time,province,city,district
</sql>
<select id="selectByStoreId" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from store_info_extend
where store_id = #{storeId,jdbcType=INTEGER}
</select>
</mapper>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.yohoufo.dal.product.IStoreInfoDAO" >
<resultMap id="BaseResultMap" type="com.yohoufo.dal.product.model.StoreInfo" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="store_code" property="storeCode" jdbcType="INTEGER" />
<result column="store_name" property="storeName" jdbcType="VARCHAR" />
<result column="warehouse_id" property="warehouseId" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="INTEGER" />
<result column="status" property="status" jdbcType="INTEGER" />
<result column="update_time" property="updateTime" jdbcType="INTEGER" />
<result column="class_id" property="classId" jdbcType="INTEGER" />
</resultMap>
<sql id="Base_Column_List" >
id, store_code, store_name, warehouse_id, create_time, status, update_time,class_id
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from store_info
where id = #{id,jdbcType=INTEGER}
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -94,6 +94,12 @@
<dependency>
<groupId>com.yoho.ufo.model</groupId>
<artifactId>product-ufo-model</artifactId>
<version>${model.version}</version>
</dependency>
<dependency>
<groupId>com.yoho.ufo.model</groupId>
<artifactId>order-ufo-model</artifactId>
<version>${model.version}</version>
</dependency>
... ...
... ... @@ -28,6 +28,10 @@
</dependency>
<dependency>
<groupId>com.yoho.ufo.model</groupId>
<artifactId>product-ufo-model</artifactId>
</dependency>
<dependency>
<groupId>com.yoho.ufo.model</groupId>
<artifactId>order-ufo-model</artifactId>
</dependency>
<dependency>
... ...
package com.yohoufo.product.controller;
import com.alibaba.fastjson.JSONObject;
import com.yohobuy.ufo.model.response.store.StoreInfoBo;
import com.yohoufo.common.ApiResponse;
import com.yohoufo.common.annotation.IgnoreSession;
import com.yohoufo.common.exception.UfoServiceException;
import com.yohoufo.product.service.StoreService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class StoreController {
private final Logger LOG = LoggerFactory.getLogger(this.getClass());
@Autowired
private StoreService storeService;
@IgnoreSession
@RequestMapping(params = "method=ufo.store.queryStoreInfoById")
public ApiResponse queryStoreInfoById(@RequestParam("storeId") Integer storeId) {
if(storeId == null || storeId < 1) {
LOG.warn("queryStoreInfoById failed, invalid storeId: {}", storeId);
return new ApiResponse.ApiResponseBuilder().code(500).message("查询门店失败").build();
}
StoreInfoBo storeInfoBo = storeService.queryStoreInfoById(storeId);
if(storeInfoBo == null) {
LOG.info("none storeInfo exists, storeId: {}", storeId);
return new ApiResponse.ApiResponseBuilder().code(500).message("查询门店为空").build();
}
LOG.info("queryStoreInfoById result: {}", storeInfoBo);
return new ApiResponse.ApiResponseBuilder().code(200).data(storeInfoBo).build();
}
@IgnoreSession
@RequestMapping(params = "method=ufo.store.isLocationInStore")
public ApiResponse isLocationInStore(@RequestParam("storeId") Integer storeId,
@RequestParam("longitude") Double longitude,
@RequestParam("latitude") Double latitude) {
LOG.info("location for store req, storeId: {}, longitude: {}, latitude: {}",
storeId, longitude, latitude);
if(storeId < 1 || longitude <= 0 || latitude <= 0) {
LOG.warn("param invalid, storeId: {}, longitude: {}, latitude: {}",
storeId, longitude, latitude);
throw new UfoServiceException(400, "定位请求异常");
}
boolean isInRange = storeService.isLocationInStore(storeId, longitude, latitude);
LOG.info("location result, isInRange: {}", isInRange);
JSONObject json = new JSONObject();
json.put("isInRange", latitude);
return new ApiResponse.ApiResponseBuilder().code(200).data(json).build();
}
}
... ...
package com.yohoufo.product.service;
import com.yohobuy.ufo.model.response.store.StoreInfoBo;
public interface StoreService {
StoreInfoBo queryStoreInfoById(int storeId);
boolean isLocationInStore(int storeId, double userLongitude, double userLatitude);
}
... ...
package com.yohoufo.product.service.impl;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yohobuy.ufo.model.response.store.StoreInfoBo;
import com.yohoufo.common.cache.CacheClient;
import com.yohoufo.common.exception.UfoServiceException;
import com.yohoufo.dal.product.IStoreInfoDAO;
import com.yohoufo.dal.product.IStoreInfoExtendDAO;
import com.yohoufo.dal.product.model.StoreInfo;
import com.yohoufo.dal.product.model.StoreInfoExtend;
import com.yohoufo.product.service.StoreService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class StoreServiceImpl implements StoreService {
@Autowired
private CacheClient cacheClient;
@Autowired
private IStoreInfoDAO storeInfoDao;
@Autowired
private IStoreInfoExtendDAO storeInfoExtendDao;
private static final String STORE_CACHE_KEY_PREFIX = "ufo:offline:store:";
private static final int STORE_CACHE_TIME_MINUTES = 10;
private static final int SIGN_RANGE_DEFAULT = 800;
private final Logger LOG = LoggerFactory.getLogger(this.getClass());
@Override
public StoreInfoBo queryStoreInfoById(int storeId) {
String key = RedisKeyBuilder.newInstance().appendFixed(STORE_CACHE_KEY_PREFIX).appendVar(storeId).getKey();
StoreInfoBo storeInfoCache = cacheClient.get(key, StoreInfoBo.class);
if(storeInfoCache != null)
return storeInfoCache;
StoreInfoBo storeInfoBo = getStoreInfoFromDb(storeId);
if(storeInfoBo != null)
cacheClient.set(key, STORE_CACHE_TIME_MINUTES * 60, storeInfoBo);
return storeInfoBo;
}
private StoreInfoBo getStoreInfoFromDb(int storeId) {
if(storeId < 1) {
LOG.warn("getStoreInfoFromDb invalid storeId: {}", storeId);
return null;
}
StoreInfo storeInfo = storeInfoDao.selectByPrimaryKey(storeId);
StoreInfoExtend storeInfoExtend = storeInfoExtendDao.selectByStoreId(storeId);
if(storeInfo == null || storeInfoExtend == null) {
LOG.warn("getStoreInfoFromDb null for storeId: {}", storeId);
return null;
}
StoreInfoBo storeInfoBo = StoreInfoBo.builder()
.storeId(storeInfo.getId())
.storeName(storeInfo.getStoreName())
.storeAddress(storeInfoExtend.getAddress())
.latitude(storeInfoExtend.getLatitude())
.longitude(storeInfoExtend.getLongitude())
.locationRadius(storeInfoExtend.getSignRange())
.build();
LOG.info("get storeInfo from db: {}", storeInfoBo);
return storeInfoBo;
}
@Override
public boolean isLocationInStore(int storeId, double userLongitude, double userLatitude) {
StoreInfoBo storeInfoBo = queryStoreInfoById(storeId);
if(storeInfoBo == null) {
LOG.warn("none storeInfo by storeId: {}", storeId);
throw new UfoServiceException(500, "门店信息不存在");
}
return isInRange(userLongitude, userLatitude, storeInfoBo);
}
private boolean isInRange(Double userLongitude, Double userLatitude, StoreInfoBo storeInfoBo) {
if (storeInfoBo == null) {
return false;
}
Double latitude = new Double(storeInfoBo.getLatitude());
Double longitude = new Double(storeInfoBo.getLongitude());
Double degree = (24901 * 1609) / 360.0;
double raidusMile = (storeInfoBo.getLocationRadius() == null) ? SIGN_RANGE_DEFAULT : storeInfoBo.getLocationRadius();
Double dpmLat = 1 / degree;
Double radiusLat = dpmLat * raidusMile;
Double minLat = latitude - radiusLat;
Double maxLat = latitude + radiusLat;
Double mpdLng = degree * Math.cos(latitude * (Math.PI / 180));
Double dpmLng = 1 / mpdLng;
Double radiusLng = dpmLng * raidusMile;
Double minLng = longitude - radiusLng;
Double maxLng = longitude + radiusLng;
if (userLongitude >= minLng && userLongitude <= maxLng && userLatitude >= minLat && userLatitude <= maxLat) {
return true;
} else {
return false;
}
}
}
... ...