Authored by chenjian

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

  1 +package com.yohoufo.dal.product;
  2 +
  3 +
  4 +import com.yohoufo.dal.product.model.StoreInfo;
  5 +
  6 +public interface IStoreInfoDAO {
  7 +
  8 + StoreInfo selectByPrimaryKey(Integer id);
  9 +
  10 +}
  1 +package com.yohoufo.dal.product;
  2 +
  3 +
  4 +import com.yohoufo.dal.product.model.StoreInfoExtend;
  5 +
  6 +public interface IStoreInfoExtendDAO {
  7 +
  8 + StoreInfoExtend selectByStoreId(Integer storeId);
  9 +
  10 +}
  1 +package com.yohoufo.dal.product.model;
  2 +
  3 +public class StoreInfo {
  4 + private Integer id;
  5 +
  6 + private Integer storeCode;
  7 +
  8 + private String storeName;
  9 +
  10 + private Integer warehouseId;
  11 +
  12 + private Integer createTime;
  13 +
  14 + private Integer status;
  15 +
  16 + private Integer updateTime;
  17 +
  18 + private Integer ftpPort;
  19 +
  20 + private String ftpIp;
  21 +
  22 + private String ftpUser;
  23 +
  24 + private String ftpPassword;
  25 +
  26 + private String printerFtpIp;
  27 +
  28 + private Integer printerFtpPort;
  29 +
  30 + private String printerFtpUser;
  31 +
  32 + private String printerFtpPassword;
  33 +
  34 + private Integer wechatpayChannel;
  35 +
  36 + private Integer alipayChannel;
  37 +
  38 + private Integer unionMposChannel;
  39 +
  40 + private Integer unionMposAppleChannel;
  41 +
  42 + private Integer classId;
  43 +
  44 + public String getPrinterFtpIp() {
  45 + return printerFtpIp;
  46 + }
  47 +
  48 + public void setPrinterFtpIp(String printerFtpIp) {
  49 + this.printerFtpIp = printerFtpIp;
  50 + }
  51 +
  52 + public Integer getPrinterFtpPort() {
  53 + return printerFtpPort;
  54 + }
  55 +
  56 + public void setPrinterFtpPort(Integer printerFtpPort) {
  57 + this.printerFtpPort = printerFtpPort;
  58 + }
  59 +
  60 + public String getPrinterFtpUser() {
  61 + return printerFtpUser;
  62 + }
  63 +
  64 + public void setPrinterFtpUser(String printerFtpUser) {
  65 + this.printerFtpUser = printerFtpUser;
  66 + }
  67 +
  68 + public String getPrinterFtpPassword() {
  69 + return printerFtpPassword;
  70 + }
  71 +
  72 + public void setPrinterFtpPassword(String printerFtpPassword) {
  73 + this.printerFtpPassword = printerFtpPassword;
  74 + }
  75 +
  76 + public Integer getFtpPort() {
  77 + return ftpPort;
  78 + }
  79 +
  80 + public void setFtpPort(Integer ftpPort) {
  81 + this.ftpPort = ftpPort;
  82 + }
  83 +
  84 + public String getFtpIp() {
  85 + return ftpIp;
  86 + }
  87 +
  88 + public void setFtpIp(String ftpIp) {
  89 + this.ftpIp = ftpIp;
  90 + }
  91 +
  92 + public String getFtpUser() {
  93 + return ftpUser;
  94 + }
  95 +
  96 + public void setFtpUser(String ftpUser) {
  97 + this.ftpUser = ftpUser;
  98 + }
  99 +
  100 + public String getFtpPassword() {
  101 + return ftpPassword;
  102 + }
  103 +
  104 + public void setFtpPassword(String ftpPassword) {
  105 + this.ftpPassword = ftpPassword;
  106 + }
  107 +
  108 + public Integer getId() {
  109 + return id;
  110 + }
  111 +
  112 + public void setId(Integer id) {
  113 + this.id = id;
  114 + }
  115 +
  116 + public Integer getStoreCode() {
  117 + return storeCode;
  118 + }
  119 +
  120 + public void setStoreCode(Integer storeCode) {
  121 + this.storeCode = storeCode;
  122 + }
  123 +
  124 + public String getStoreName() {
  125 + return storeName;
  126 + }
  127 +
  128 + public void setStoreName(String storeName) {
  129 + this.storeName = storeName == null ? null : storeName.trim();
  130 + }
  131 +
  132 + public Integer getWarehouseId() {
  133 + return warehouseId;
  134 + }
  135 +
  136 + public void setWarehouseId(Integer warehouseId) {
  137 + this.warehouseId = warehouseId;
  138 + }
  139 +
  140 + public Integer getCreateTime() {
  141 + return createTime;
  142 + }
  143 +
  144 + public void setCreateTime(Integer createTime) {
  145 + this.createTime = createTime;
  146 + }
  147 +
  148 + public Integer getStatus() {
  149 + return status;
  150 + }
  151 +
  152 + public void setStatus(Integer status) {
  153 + this.status = status;
  154 + }
  155 +
  156 + public Integer getUpdateTime() {
  157 + return updateTime;
  158 + }
  159 +
  160 + public void setUpdateTime(Integer updateTime) {
  161 + this.updateTime = updateTime;
  162 + }
  163 +
  164 + public Integer getWechatpayChannel() {
  165 + return wechatpayChannel;
  166 + }
  167 +
  168 + public void setWechatpayChannel(Integer wechatpayChannel) {
  169 + this.wechatpayChannel = wechatpayChannel;
  170 + }
  171 +
  172 + public Integer getAlipayChannel() {
  173 + return alipayChannel;
  174 + }
  175 +
  176 + public void setAlipayChannel(Integer alipayChannel) {
  177 + this.alipayChannel = alipayChannel;
  178 + }
  179 +
  180 + public Integer getUnionMposChannel() {
  181 + return unionMposChannel;
  182 + }
  183 +
  184 + public void setUnionMposChannel(Integer unionMposChannel) {
  185 + this.unionMposChannel = unionMposChannel;
  186 + }
  187 +
  188 + public Integer getUnionMposAppleChannel() {
  189 + return unionMposAppleChannel;
  190 + }
  191 +
  192 + public void setUnionMposAppleChannel(Integer unionMposAppleChannel) {
  193 + this.unionMposAppleChannel = unionMposAppleChannel;
  194 + }
  195 +
  196 + public Integer getClassId() {
  197 + return classId;
  198 + }
  199 +
  200 + public void setClassId(Integer classId) {
  201 + this.classId = classId;
  202 + }
  203 +}
  1 +package com.yohoufo.dal.product.model;
  2 +
  3 +import lombok.Data;
  4 +
  5 +@Data
  6 +public class StoreInfoExtend {
  7 +
  8 + private Integer storeId;
  9 +
  10 + private Integer regionId;
  11 +
  12 + private String address;
  13 +
  14 + private float longitude;
  15 +
  16 + private float latitude;
  17 +
  18 + private String businessTime;
  19 +
  20 + private String telephone;
  21 +
  22 + private String thumbnailUrl;
  23 +
  24 + private String pictureUrl;
  25 +
  26 + private String introduction;
  27 +
  28 + private Integer createUserId;
  29 +
  30 + private Integer createTime;
  31 +
  32 + private Integer updateTime;
  33 +
  34 + private String detail;
  35 +
  36 + private Integer province;
  37 +
  38 + private Integer city;
  39 +
  40 + private Integer district;
  41 +
  42 + private Integer signRange;
  43 +}
  1 +<?xml version="1.0" encoding="UTF-8" ?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3 +<mapper namespace="com.yohoufo.dal.product.IStoreInfoExtendDAO" >
  4 + <resultMap id="BaseResultMap" type="com.yohoufo.dal.product.model.StoreInfoExtend" >
  5 + <id column="store_id" property="storeId" jdbcType="INTEGER" />
  6 + <result column="region_id" property="regionId" jdbcType="INTEGER" />
  7 + <result column="address" property="address" jdbcType="VARCHAR" />
  8 + <result column="longitude" property="longitude" jdbcType="FLOAT" />
  9 + <result column="latitude" property="latitude" jdbcType="FLOAT" />
  10 + <result column="business_time" property="businessTime" jdbcType="VARCHAR" />
  11 + <result column="telephone" property="telephone" jdbcType="VARCHAR" />
  12 + <result column="thumbnail_url" property="thumbnailUrl" jdbcType="VARCHAR" />
  13 + <result column="picture_url" property="pictureUrl" jdbcType="VARCHAR" />
  14 + <result column="introduction" property="introduction" jdbcType="VARCHAR" />
  15 + <result column="create_user_id" property="createUserId" jdbcType="INTEGER" />
  16 + <result column="create_time" property="createTime" jdbcType="INTEGER" />
  17 + <result column="update_time" property="updateTime" jdbcType="INTEGER" />
  18 + <result column="province" property="province" jdbcType="INTEGER" />
  19 + <result column="city" property="city" jdbcType="INTEGER" />
  20 + <result column="district" property="district" jdbcType="INTEGER" />
  21 + <result column="sign_range" property="signRange" javaType="INTEGER" />
  22 + </resultMap>
  23 + <sql id="Base_Column_List" >
  24 + store_id, region_id, address, longitude, latitude, sign_range, business_time,
  25 + telephone, thumbnail_url, picture_url, introduction, create_user_id, create_time,
  26 + update_time,update_time,province,city,district
  27 + </sql>
  28 +
  29 + <select id="selectByStoreId" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
  30 + select
  31 + <include refid="Base_Column_List" />
  32 + from store_info_extend
  33 + where store_id = #{storeId,jdbcType=INTEGER}
  34 + </select>
  35 +
  36 +</mapper>
  1 +<?xml version="1.0" encoding="UTF-8" ?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3 +<mapper namespace="com.yohoufo.dal.product.IStoreInfoDAO" >
  4 + <resultMap id="BaseResultMap" type="com.yohoufo.dal.product.model.StoreInfo" >
  5 + <id column="id" property="id" jdbcType="INTEGER" />
  6 + <result column="store_code" property="storeCode" jdbcType="INTEGER" />
  7 + <result column="store_name" property="storeName" jdbcType="VARCHAR" />
  8 + <result column="warehouse_id" property="warehouseId" jdbcType="INTEGER" />
  9 + <result column="create_time" property="createTime" jdbcType="INTEGER" />
  10 + <result column="status" property="status" jdbcType="INTEGER" />
  11 + <result column="update_time" property="updateTime" jdbcType="INTEGER" />
  12 + <result column="class_id" property="classId" jdbcType="INTEGER" />
  13 + </resultMap>
  14 + <sql id="Base_Column_List" >
  15 + id, store_code, store_name, warehouse_id, create_time, status, update_time,class_id
  16 + </sql>
  17 + <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
  18 + select
  19 + <include refid="Base_Column_List" />
  20 + from store_info
  21 + where id = #{id,jdbcType=INTEGER}
  22 + </select>
  23 +
  24 +
  25 +</mapper>
@@ -94,6 +94,12 @@ @@ -94,6 +94,12 @@
94 94
95 <dependency> 95 <dependency>
96 <groupId>com.yoho.ufo.model</groupId> 96 <groupId>com.yoho.ufo.model</groupId>
  97 + <artifactId>product-ufo-model</artifactId>
  98 + <version>${model.version}</version>
  99 + </dependency>
  100 +
  101 + <dependency>
  102 + <groupId>com.yoho.ufo.model</groupId>
97 <artifactId>order-ufo-model</artifactId> 103 <artifactId>order-ufo-model</artifactId>
98 <version>${model.version}</version> 104 <version>${model.version}</version>
99 </dependency> 105 </dependency>
@@ -28,6 +28,10 @@ @@ -28,6 +28,10 @@
28 </dependency> 28 </dependency>
29 <dependency> 29 <dependency>
30 <groupId>com.yoho.ufo.model</groupId> 30 <groupId>com.yoho.ufo.model</groupId>
  31 + <artifactId>product-ufo-model</artifactId>
  32 + </dependency>
  33 + <dependency>
  34 + <groupId>com.yoho.ufo.model</groupId>
31 <artifactId>order-ufo-model</artifactId> 35 <artifactId>order-ufo-model</artifactId>
32 </dependency> 36 </dependency>
33 <dependency> 37 <dependency>
  1 +package com.yohoufo.product.controller;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.yohobuy.ufo.model.response.store.StoreInfoBo;
  5 +import com.yohoufo.common.ApiResponse;
  6 +import com.yohoufo.common.annotation.IgnoreSession;
  7 +import com.yohoufo.common.exception.UfoServiceException;
  8 +import com.yohoufo.product.service.StoreService;
  9 +import org.slf4j.Logger;
  10 +import org.slf4j.LoggerFactory;
  11 +import org.springframework.beans.factory.annotation.Autowired;
  12 +import org.springframework.web.bind.annotation.RequestMapping;
  13 +import org.springframework.web.bind.annotation.RequestParam;
  14 +import org.springframework.web.bind.annotation.RestController;
  15 +
  16 +@RestController
  17 +public class StoreController {
  18 +
  19 + private final Logger LOG = LoggerFactory.getLogger(this.getClass());
  20 +
  21 + @Autowired
  22 + private StoreService storeService;
  23 +
  24 + @IgnoreSession
  25 + @RequestMapping(params = "method=ufo.store.queryStoreInfoById")
  26 + public ApiResponse queryStoreInfoById(@RequestParam("storeId") Integer storeId) {
  27 + if(storeId == null || storeId < 1) {
  28 + LOG.warn("queryStoreInfoById failed, invalid storeId: {}", storeId);
  29 + return new ApiResponse.ApiResponseBuilder().code(500).message("查询门店失败").build();
  30 + }
  31 +
  32 + StoreInfoBo storeInfoBo = storeService.queryStoreInfoById(storeId);
  33 + if(storeInfoBo == null) {
  34 + LOG.info("none storeInfo exists, storeId: {}", storeId);
  35 + return new ApiResponse.ApiResponseBuilder().code(500).message("查询门店为空").build();
  36 + }
  37 + LOG.info("queryStoreInfoById result: {}", storeInfoBo);
  38 + return new ApiResponse.ApiResponseBuilder().code(200).data(storeInfoBo).build();
  39 + }
  40 +
  41 + @IgnoreSession
  42 + @RequestMapping(params = "method=ufo.store.isLocationInStore")
  43 + public ApiResponse isLocationInStore(@RequestParam("storeId") Integer storeId,
  44 + @RequestParam("longitude") Double longitude,
  45 + @RequestParam("latitude") Double latitude) {
  46 + LOG.info("location for store req, storeId: {}, longitude: {}, latitude: {}",
  47 + storeId, longitude, latitude);
  48 + if(storeId < 1 || longitude <= 0 || latitude <= 0) {
  49 + LOG.warn("param invalid, storeId: {}, longitude: {}, latitude: {}",
  50 + storeId, longitude, latitude);
  51 + throw new UfoServiceException(400, "定位请求异常");
  52 + }
  53 +
  54 +
  55 + boolean isInRange = storeService.isLocationInStore(storeId, longitude, latitude);
  56 + LOG.info("location result, isInRange: {}", isInRange);
  57 +
  58 + JSONObject json = new JSONObject();
  59 + json.put("isInRange", latitude);
  60 + return new ApiResponse.ApiResponseBuilder().code(200).data(json).build();
  61 + }
  62 +
  63 +}
  1 +package com.yohoufo.product.service;
  2 +
  3 +import com.yohobuy.ufo.model.response.store.StoreInfoBo;
  4 +
  5 +public interface StoreService {
  6 +
  7 + StoreInfoBo queryStoreInfoById(int storeId);
  8 +
  9 + boolean isLocationInStore(int storeId, double userLongitude, double userLatitude);
  10 +
  11 +}
  1 +package com.yohoufo.product.service.impl;
  2 +
  3 +import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
  4 +import com.yohobuy.ufo.model.response.store.StoreInfoBo;
  5 +import com.yohoufo.common.cache.CacheClient;
  6 +import com.yohoufo.common.exception.UfoServiceException;
  7 +import com.yohoufo.dal.product.IStoreInfoDAO;
  8 +import com.yohoufo.dal.product.IStoreInfoExtendDAO;
  9 +import com.yohoufo.dal.product.model.StoreInfo;
  10 +import com.yohoufo.dal.product.model.StoreInfoExtend;
  11 +import com.yohoufo.product.service.StoreService;
  12 +import org.slf4j.Logger;
  13 +import org.slf4j.LoggerFactory;
  14 +import org.springframework.beans.factory.annotation.Autowired;
  15 +import org.springframework.stereotype.Service;
  16 +
  17 +@Service
  18 +public class StoreServiceImpl implements StoreService {
  19 +
  20 + @Autowired
  21 + private CacheClient cacheClient;
  22 +
  23 + @Autowired
  24 + private IStoreInfoDAO storeInfoDao;
  25 +
  26 + @Autowired
  27 + private IStoreInfoExtendDAO storeInfoExtendDao;
  28 +
  29 + private static final String STORE_CACHE_KEY_PREFIX = "ufo:offline:store:";
  30 +
  31 + private static final int STORE_CACHE_TIME_MINUTES = 10;
  32 +
  33 + private static final int SIGN_RANGE_DEFAULT = 800;
  34 +
  35 + private final Logger LOG = LoggerFactory.getLogger(this.getClass());
  36 +
  37 + @Override
  38 + public StoreInfoBo queryStoreInfoById(int storeId) {
  39 + String key = RedisKeyBuilder.newInstance().appendFixed(STORE_CACHE_KEY_PREFIX).appendVar(storeId).getKey();
  40 + StoreInfoBo storeInfoCache = cacheClient.get(key, StoreInfoBo.class);
  41 + if(storeInfoCache != null)
  42 + return storeInfoCache;
  43 +
  44 + StoreInfoBo storeInfoBo = getStoreInfoFromDb(storeId);
  45 + if(storeInfoBo != null)
  46 + cacheClient.set(key, STORE_CACHE_TIME_MINUTES * 60, storeInfoBo);
  47 +
  48 + return storeInfoBo;
  49 + }
  50 +
  51 + private StoreInfoBo getStoreInfoFromDb(int storeId) {
  52 + if(storeId < 1) {
  53 + LOG.warn("getStoreInfoFromDb invalid storeId: {}", storeId);
  54 + return null;
  55 + }
  56 +
  57 + StoreInfo storeInfo = storeInfoDao.selectByPrimaryKey(storeId);
  58 + StoreInfoExtend storeInfoExtend = storeInfoExtendDao.selectByStoreId(storeId);
  59 + if(storeInfo == null || storeInfoExtend == null) {
  60 + LOG.warn("getStoreInfoFromDb null for storeId: {}", storeId);
  61 + return null;
  62 + }
  63 +
  64 + StoreInfoBo storeInfoBo = StoreInfoBo.builder()
  65 + .storeId(storeInfo.getId())
  66 + .storeName(storeInfo.getStoreName())
  67 + .storeAddress(storeInfoExtend.getAddress())
  68 + .latitude(storeInfoExtend.getLatitude())
  69 + .longitude(storeInfoExtend.getLongitude())
  70 + .locationRadius(storeInfoExtend.getSignRange())
  71 + .build();
  72 +
  73 + LOG.info("get storeInfo from db: {}", storeInfoBo);
  74 + return storeInfoBo;
  75 + }
  76 +
  77 +
  78 + @Override
  79 + public boolean isLocationInStore(int storeId, double userLongitude, double userLatitude) {
  80 + StoreInfoBo storeInfoBo = queryStoreInfoById(storeId);
  81 + if(storeInfoBo == null) {
  82 + LOG.warn("none storeInfo by storeId: {}", storeId);
  83 + throw new UfoServiceException(500, "门店信息不存在");
  84 + }
  85 + return isInRange(userLongitude, userLatitude, storeInfoBo);
  86 + }
  87 +
  88 + private boolean isInRange(Double userLongitude, Double userLatitude, StoreInfoBo storeInfoBo) {
  89 + if (storeInfoBo == null) {
  90 + return false;
  91 + }
  92 + Double latitude = new Double(storeInfoBo.getLatitude());
  93 + Double longitude = new Double(storeInfoBo.getLongitude());
  94 +
  95 + Double degree = (24901 * 1609) / 360.0;
  96 + double raidusMile = (storeInfoBo.getLocationRadius() == null) ? SIGN_RANGE_DEFAULT : storeInfoBo.getLocationRadius();
  97 +
  98 + Double dpmLat = 1 / degree;
  99 + Double radiusLat = dpmLat * raidusMile;
  100 + Double minLat = latitude - radiusLat;
  101 + Double maxLat = latitude + radiusLat;
  102 +
  103 + Double mpdLng = degree * Math.cos(latitude * (Math.PI / 180));
  104 + Double dpmLng = 1 / mpdLng;
  105 + Double radiusLng = dpmLng * raidusMile;
  106 + Double minLng = longitude - radiusLng;
  107 + Double maxLng = longitude + radiusLng;
  108 +
  109 + if (userLongitude >= minLng && userLongitude <= maxLng && userLatitude >= minLat && userLatitude <= maxLat) {
  110 + return true;
  111 + } else {
  112 + return false;
  113 + }
  114 + }
  115 +}