Authored by caoyan

UFO比价

package com.yoho.ufo.dal;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.yoho.ufo.model.ChannelSkuCompare;
import com.yoho.ufo.model.ChannelSkuCompareReq;
/**
* Created by caoyan.
*/
public interface ChannelSkuCompareMapper {
int selectTotalByCondition(@Param("channelSkuCompareReq") ChannelSkuCompareReq req);
List<ChannelSkuCompare> selectByCondition(@Param("channelSkuCompareReq") ChannelSkuCompareReq req);
}
... ...
... ... @@ -2,7 +2,6 @@ package com.yoho.ufo.dal;
import java.util.List;
import com.yoho.ufo.model.brand.Brand;
import org.apache.ibatis.annotations.Param;
import com.yoho.ufo.dal.model.Product;
... ... @@ -72,4 +71,6 @@ public interface ProductMapper {
int selectProductStorageCount(@Param("product")Product product);
List<Product> selectProductStorageList(@Param("product")Product product, @Param("start")int start, @Param("rows")Integer rows);
List<Product> selectByProductName(@Param("productName") String productName);
}
\ No newline at end of file
... ...
... ... @@ -2,7 +2,6 @@ package com.yoho.ufo.dal;
import java.util.List;
import com.yoho.ufo.dal.model.Product;
import org.apache.ibatis.annotations.Param;
import com.yoho.ufo.dal.model.StoragePrice;
... ... @@ -47,4 +46,6 @@ public interface StoragePriceMapper {
// 根据SKup等信息查询其所属productId列表 最多查询出最新的300 productId
List<Integer> selectProductIdsBySkupInfo(@Param("storagePrice")StoragePrice storagePrice);
List<StoragePrice> selectMinPriceByStorageIdList(@Param("list") List<Integer> storageIdList);
}
\ No newline at end of file
... ...
package com.yoho.ufo.dal;
import com.yoho.ufo.model.commoditybasicrole.color.ProductColor;
import com.yoho.ufo.model.commoditybasicrole.size.Size;
import com.yohobuy.ufo.model.common.PageModel;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import com.yoho.ufo.model.commoditybasicrole.size.Size;
import com.yohobuy.ufo.model.common.PageModel;
/**
* 品类mapper
... ... @@ -83,4 +83,11 @@ public interface UfoSizeMapper {
* @return
*/
List<Size> selectAllSize();
/**
* 根据尺码名称查询尺码对象
* @param sizeName
* @return
*/
List<Size> selectBySizeName(@Param("sizeName") String sizeName);
}
... ...
package com.yoho.ufo.dal.model;
import java.math.BigDecimal;
public class Storage {
private Integer id;
... ... @@ -14,6 +16,10 @@ public class Storage {
private Integer updateTime;
private Integer createTime;
private BigDecimal suggestLowPrice;
private BigDecimal suggestHighPrice;
public Integer getId() {
return id;
... ... @@ -70,4 +76,21 @@ public class Storage {
public void setCreateTime(Integer createTime) {
this.createTime = createTime;
}
public BigDecimal getSuggestLowPrice() {
return suggestLowPrice;
}
public void setSuggestLowPrice(BigDecimal suggestLowPrice) {
this.suggestLowPrice = suggestLowPrice;
}
public BigDecimal getSuggestHighPrice() {
return suggestHighPrice;
}
public void setSuggestHighPrice(BigDecimal suggestHighPrice) {
this.suggestHighPrice = suggestHighPrice;
}
}
\ No newline at end of file
... ...
package com.yoho.ufo.model;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 爬虫跟毒价
*/
public class ChannelSkuCompare implements Serializable {
private static final long serialVersionUID = 1613330087543482073L;
/**
* 主键
*/
private Integer id;
/**
* 商品ID
*/
private Integer productId;
private Integer sku;
private Integer sizeId;
private BigDecimal channelPrice;
private BigDecimal lowRate;
private BigDecimal highRate;
private Integer updateTime;
private String channelUrl;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public Integer getSku() {
return sku;
}
public void setSku(Integer sku) {
this.sku = sku;
}
public Integer getSizeId() {
return sizeId;
}
public void setSizeId(Integer sizeId) {
this.sizeId = sizeId;
}
public BigDecimal getChannelPrice() {
return channelPrice;
}
public void setChannelPrice(BigDecimal channelPrice) {
this.channelPrice = channelPrice;
}
public BigDecimal getLowRate() {
return lowRate;
}
public void setLowRate(BigDecimal lowRate) {
this.lowRate = lowRate;
}
public BigDecimal getHighRate() {
return highRate;
}
public void setHighRate(BigDecimal highRate) {
this.highRate = highRate;
}
public Integer getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Integer updateTime) {
this.updateTime = updateTime;
}
public String getChannelUrl() {
return channelUrl;
}
public void setChannelUrl(String channelUrl) {
this.channelUrl = channelUrl;
}
@Override
public String toString() {
return "ProductPool{" +
"id=" + id +
", productId='" + productId +
", sku=" + sku +
", sizeId=" + sizeId +
", channelPrice=" + channelPrice +
", lowRate=" + lowRate +
", highRate=" + highRate +
", updateTime=" + updateTime +
", channelUrl=" + channelUrl +
'}';
}
}
... ...
package com.yoho.ufo.model;
import java.util.List;
import com.alibaba.fastjson.JSONObject;
import com.yoho.ufo.service.model.PageRequestBO;
public class ChannelSkuCompareReq extends PageRequestBO {
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer sku;
private Integer productId;
private Integer status;
private String productName;
private String sizeName;
private List<Integer> productIdList;
private List<Integer> sizeIdList;
public Integer getSku() {
return sku;
}
public void setSku(Integer sku) {
this.sku = sku;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getSizeName() {
return sizeName;
}
public void setSizeName(String sizeName) {
this.sizeName = sizeName;
}
public List<Integer> getProductIdList() {
return productIdList;
}
public void setProductIdList(List<Integer> productIdList) {
this.productIdList = productIdList;
}
public List<Integer> getSizeIdList() {
return sizeIdList;
}
public void setSizeIdList(List<Integer> sizeIdList) {
this.sizeIdList = sizeIdList;
}
public String toString() {
return JSONObject.toJSONString(this);
}
}
... ...
<?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.yoho.ufo.dal.ChannelSkuCompareMapper">
<resultMap id="BaseResultMap" type="com.yoho.ufo.model.ChannelSkuCompare">
<result column="id" property="id" jdbcType="INTEGER" />
<result column="product_id" property="productId" jdbcType="INTEGER" />
<result column="sku" property="sku" jdbcType="INTEGER" />
<result column="size_id" property="sizeId" jdbcType="INTEGER" />
<result column="channel_price" property="channelPrice" jdbcType="DECIMAL" />
<result column="low_rate" property="lowRate" jdbcType="DECIMAL" />
<result column="high_rate" property="highRate" jdbcType="DECIMAL" />
<result column="update_time" property="updateTime" jdbcType="INTEGER" />
<result column="channel_url" property="channelUrl" jdbcType="VARCHAR" />
</resultMap>
<sql id="Base_Column_List">
id, product_id, sku, size_id, channel_price, low_rate, high_rate, update_time, channel_url
</sql>
<sql id="Query_Sql" >
<if test="channelSkuCompareReq.sku != null and channelSkuCompareReq.sku != 0 ">
and a.sku = #{channelSkuCompareReq.sku}
</if>
<if test="channelSkuCompareReq.productId != null and channelSkuCompareReq.productId != 0 ">
and a.product_id = #{channelSkuCompareReq.productId}
</if>
<if test="channelSkuCompareReq.productIdList != null and channelSkuCompareReq.productIdList.size()>0">
and a.product_id in
<foreach collection="channelSkuCompareReq.productIdList" item="productId" open="(" close=")" separator=",">
#{productId}
</foreach>
</if>
<if test="channelSkuCompareReq.sizeIdList != null and channelSkuCompareReq.sizeIdList.size()>0">
and a.size_id in
<foreach collection="channelSkuCompareReq.sizeIdList" item="sizeId" open="(" close=")" separator=",">
#{sizeId}
</foreach>
</if>
<if test="channelSkuCompareReq.status != null and channelSkuCompareReq.status == 0 ">
and b.min_price &lt; a.channel_price
</if>
<if test="channelSkuCompareReq.status != null and channelSkuCompareReq.status == 1 ">
and b.min_price &gt; a.channel_price
</if>
</sql>
<select id="selectTotalByCondition" resultType="java.lang.Integer" parameterType="com.yoho.ufo.model.ChannelSkuCompareReq">
select count(a.id)
from channel_sku_compare a
<if test="channelSkuCompareReq.status != null">
LEFT JOIN product b
ON( b.id=a.product_id)
</if>
where 1=1
<include refid="Query_Sql" />
</select>
<select id="selectByCondition" resultMap="BaseResultMap" parameterType="com.yoho.ufo.model.ChannelSkuCompareReq">
select a.*
from channel_sku_compare a
<if test="channelSkuCompareReq.status != null">
LEFT JOIN product b
ON( b.id=a.product_id)
</if>
where 1=1
<include refid="Query_Sql" />
order by a.product_id desc, a.sku asc
<if test="channelSkuCompareReq.start!=null and channelSkuCompareReq.size != null">
limit #{channelSkuCompareReq.start},#{channelSkuCompareReq.size}
</if>
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -222,4 +222,7 @@
</foreach>
</if>
</sql>
<select id="selectByProductName" resultMap="BaseResultMap">
select id, product_name from product where product_name like "%"#{productName}"%"
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -9,6 +9,8 @@
<result column="storage_num" jdbcType="INTEGER" property="storageNum" />
<result column="update_time" jdbcType="INTEGER" property="updateTime" />
<result column="create_time" jdbcType="INTEGER" property="createTime" />
<result column="suggest_low_price" jdbcType="DECIMAL" property="suggestLowPrice" />
<result column="suggest_high_price" jdbcType="DECIMAL" property="suggestHighPrice" />
</resultMap>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from storage
... ... @@ -58,7 +60,7 @@
where id = #{storageId,jdbcType=INTEGER} and storage_num = #{oldStorageNum,jdbcType=INTEGER}
</update>
<select id="selectByIds" resultMap="BaseResultMap">
select id, product_id, goods_id, size_id, storage_num, update_time, create_time
select id, product_id, goods_id, size_id, storage_num, update_time, create_time, suggest_low_price, suggest_high_price
from storage where id in
<foreach item="item" index="index" collection="storageIdList" open="(" separator="," close=")">
#{item}
... ...
... ... @@ -161,4 +161,13 @@
</if>
order by create_time desc limit 300
</select>
<select id="selectMinPriceByStorageIdList" resultMap="BaseResultMap">
select storage_id, min(price) as price
from storage_price where storage_id in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
and status = 1 group by storage_id
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -103,4 +103,7 @@
select id, sort_id, size_name from size
</select>
<select id="selectBySizeName" resultMap="sizeMap">
select id, size_name from size where size_name = #{sizeName}
</select>
</mapper>
\ No newline at end of file
... ...
package com.yoho.ufo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yoho.ufo.model.ChannelSkuCompareReq;
import com.yoho.ufo.service.IChannelSkuCompareService;
import com.yoho.ufo.service.model.ApiResponse;
import com.yoho.ufo.service.model.PageResponseBO;
import com.yohobuy.ufo.model.resp.product.ChannelSkuCompareRspBo;
@RestController
@RequestMapping(value = "/channelSkuCompare")
public class ChannelSkuCompareController {
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelSkuCompareController.class);
@Autowired
private IChannelSkuCompareService channelSkuCompareService;
@RequestMapping(value = "/queryList")
public ApiResponse queryList(@RequestBody ChannelSkuCompareReq req) {
LOGGER.info("queryOrderList in. req is {}", req);
PageResponseBO<ChannelSkuCompareRspBo> result = channelSkuCompareService.queryList(req);
return new ApiResponse.ApiResponseBuilder().code(200).message("查询成功").data(result).build();
}
}
... ...
package com.yoho.ufo.service;
import com.yoho.ufo.model.ChannelSkuCompareReq;
import com.yoho.ufo.service.model.PageResponseBO;
import com.yohobuy.ufo.model.resp.product.ChannelSkuCompareRspBo;
/**
* @author caoyan
*/
public interface IChannelSkuCompareService {
PageResponseBO<ChannelSkuCompareRspBo> queryList(ChannelSkuCompareReq req);
}
... ...
package com.yoho.ufo.service.impl;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yoho.ufo.dal.ChannelSkuCompareMapper;
import com.yoho.ufo.dal.ProductMapper;
import com.yoho.ufo.dal.StorageMapper;
import com.yoho.ufo.dal.StoragePriceMapper;
import com.yoho.ufo.dal.UfoSizeMapper;
import com.yoho.ufo.dal.model.Product;
import com.yoho.ufo.dal.model.Storage;
import com.yoho.ufo.dal.model.StoragePrice;
import com.yoho.ufo.model.ChannelSkuCompare;
import com.yoho.ufo.model.ChannelSkuCompareReq;
import com.yoho.ufo.model.commoditybasicrole.size.Size;
import com.yoho.ufo.service.IChannelSkuCompareService;
import com.yoho.ufo.service.model.PageResponseBO;
import com.yohobuy.ufo.model.resp.product.ChannelSkuCompareRspBo;
/**
* @author caoyan
*/
@Service
public class ChannelSkuCompareServiceImpl implements IChannelSkuCompareService {
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelSkuCompareServiceImpl.class);
@Autowired
private ChannelSkuCompareMapper channelSkuCompareMapper;
@Autowired
private ProductMapper productMapper;
@Autowired
private UfoSizeMapper ufoSizeMapper;
@Autowired
private StorageMapper storageMapper;
@Autowired
private StoragePriceMapper storagePriceMapper;
@Override
public PageResponseBO<ChannelSkuCompareRspBo> queryList(ChannelSkuCompareReq req) {
LOGGER.info("queryList in. req is {}", req);
if(!checkAndBuildParam(req)) {
return null;
}
int total = channelSkuCompareMapper.selectTotalByCondition(req);
if(total == 0) {
return null;
}
List<ChannelSkuCompare> cscList = channelSkuCompareMapper.selectByCondition(req);
if(CollectionUtils.isEmpty(cscList)) {
return null;
}
//查询商品名称
List<Integer> productIdList = cscList.stream().map(ChannelSkuCompare::getProductId).collect(Collectors.toList());
List<Product> productList = productMapper.selectProductListByIds(productIdList);
if(CollectionUtils.isEmpty(productList)) {
return null;
}
Map<Integer, Product> productMap = productList.stream().collect(Collectors.toMap(Product::getId, p->p));
//查询尺码名称
List<Integer> sizeIdList = cscList.stream().map(ChannelSkuCompare::getSizeId).collect(Collectors.toList());
List<Size> sizeList = ufoSizeMapper.selectByIdList(sizeIdList);
Map<Integer, String> sizeIdNameMap = sizeList.stream().collect(Collectors.toMap(Size::getId, Size::getSizeName));
//查询平台建议价
List<Integer> skuList = cscList.stream().map(ChannelSkuCompare::getSku).collect(Collectors.toList());
List<Storage> storageList = storageMapper.selectByIds(skuList);
Map<Integer, Storage> storageMap = storageList.stream().collect(Collectors.toMap(Storage::getId, s->s));
//计算UFO当前价,可售sku最低价
List<StoragePrice> storagePriceList = storagePriceMapper.selectMinPriceByStorageIdList(skuList);
Map<Integer, BigDecimal> storageMinPriceMap = storagePriceList.stream().collect(Collectors.toMap(StoragePrice::getStorageId, StoragePrice::getPrice));
List<ChannelSkuCompareRspBo> respList = convertToResp(cscList, productMap, sizeIdNameMap, storageMap, storageMinPriceMap);
PageResponseBO<ChannelSkuCompareRspBo> result=new PageResponseBO<>();
result.setList(respList);
result.setPage(req.getPage());
result.setSize(req.getSize());
result.setTotal(total);
return result;
}
private List<ChannelSkuCompareRspBo> convertToResp(List<ChannelSkuCompare> cscList, Map<Integer, Product> productMap,
Map<Integer, String> sizeIdNameMap, Map<Integer, Storage> storageMap, Map<Integer, BigDecimal> storageMinPriceMap){
List<ChannelSkuCompareRspBo> boList = Lists.newArrayList();
for(ChannelSkuCompare csc : cscList) {
ChannelSkuCompareRspBo bo = new ChannelSkuCompareRspBo();
bo.setProductId(csc.getProductId());
bo.setSku(csc.getSku());
bo.setProductName(productMap.get(csc.getProductId()).getProductName());
bo.setSizeName(sizeIdNameMap.get(csc.getSizeId()));
bo.setChannelPrice(getFormatPrice(csc.getChannelPrice()));
bo.setChannelUrl(csc.getChannelUrl());
bo.setLowRate(csc.getLowRate().multiply(BigDecimal.valueOf(100)) + "%");
bo.setHighRate(csc.getHighRate().multiply(BigDecimal.valueOf(100)) + "%");
BigDecimal channelLowPrice = csc.getChannelPrice().multiply(BigDecimal.valueOf(1).subtract(csc.getLowRate()));
BigDecimal channelHighPrice = csc.getChannelPrice().multiply(BigDecimal.valueOf(1).add(csc.getHighRate()));
bo.setChannelPriceRange(getFormatPrice(channelLowPrice) + "~" + getFormatPrice(channelHighPrice));
bo.setUfoCurrentPrice(getFormatPrice(storageMinPriceMap.get(csc.getSku())));
BigDecimal ufoMinPrice = productMap.get(csc.getProductId()).getMinPrice();
bo.setUfoMinPrice(getFormatPrice(ufoMinPrice));
//毒当前价低于UFO价格红线则为异常,那么显示上回的建议价
BigDecimal suggestLowPrice = storageMap.get(csc.getSku()).getSuggestLowPrice();
BigDecimal suggestHighPrice = storageMap.get(csc.getSku()).getSuggestHighPrice();
if(null != suggestLowPrice && null != suggestHighPrice) {
bo.setSuggestPriceRange(getFormatPrice(suggestLowPrice) + "~" + getFormatPrice(suggestHighPrice));
}
if(csc.getChannelPrice().compareTo(ufoMinPrice) < 0) {//异常
bo.setStatus(1);
}else {
bo.setStatus(0);//正常
}
boList.add(bo);
}
return boList;
}
private static String getFormatPrice(BigDecimal price) {
return String.format("%d", price.intValue());
}
private boolean checkAndBuildParam(ChannelSkuCompareReq req) {
if(StringUtils.isNotEmpty(req.getProductName())) {
List<Product> productList = productMapper.selectByProductName(req.getProductName());
if(CollectionUtils.isEmpty(productList)) {
return false;
}else {
req.setProductIdList(productList.stream().map(Product::getId).collect(Collectors.toList()));
}
}
if(StringUtils.isNotEmpty(req.getSizeName())) {
List<Size> sizeList = ufoSizeMapper.selectBySizeName(req.getSizeName());
if(CollectionUtils.isEmpty(sizeList)) {
return false;
}else {
req.setSizeIdList(sizeList.stream().map(Size::getId).collect(Collectors.toList()));
}
}
return true;
}
}
... ...