Browse Source

Merge remote-tracking branch 'origin/master'

guozhaoshun 6 years ago
parent
commit
7c9427eddd
23 changed files with 676 additions and 18 deletions
  1. 84 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/controller/ProductController.java
  2. 30 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/controller/RecommendController.java
  3. 47 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/controller/UserController.java
  4. 46 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/service/product/ProductClient.java
  5. 5 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/service/product/ProductService.java
  6. 2 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/service/user/UserClient.java
  7. 13 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/service/user/UserService.java
  8. 5 0
      rankin-api-web/src/main/java/cn/rankin/apiweb/utils/RequestHeaderManager.java
  9. 43 0
      rankin-common-utils/src/main/java/cn/rankin/common/utils/Proxy/ProxyWrapper.java
  10. 2 0
      rankin-data-api/src/main/java/cn/rankin/data/api/app/vo/ItemGoodsVo.java
  11. 4 0
      rankin-data-api/src/main/java/cn/rankin/data/api/product/entity/Goods.java
  12. 56 0
      rankin-data-api/src/main/java/cn/rankin/data/api/product/entity/Poster.java
  13. 8 0
      rankin-data-api/src/main/java/cn/rankin/data/api/product/entity/Product.java
  14. 42 0
      rankin-product-service/src/main/java/cn/rankin/productservice/controller/MerchantController.java
  15. 43 0
      rankin-product-service/src/main/java/cn/rankin/productservice/controller/PackageController.java
  16. 42 2
      rankin-product-service/src/main/java/cn/rankin/productservice/controller/cms/ProductController.java
  17. 80 4
      rankin-product-service/src/main/java/cn/rankin/productservice/controller/auth/AuthController.java
  18. 9 0
      rankin-product-service/src/main/java/cn/rankin/productservice/repository/PosterRepository.java
  19. 56 1
      rankin-product-service/src/main/java/cn/rankin/productservice/service/PackageService.java
  20. 49 4
      rankin-product-service/src/main/java/cn/rankin/productservice/service/ProductService.java
  21. 1 0
      rankin-product-service/src/main/java/cn/rankin/productservice/service/app/ItemService.java
  22. 4 3
      rankin-product-service/src/main/java/cn/rankin/productservice/service/auth/AuthClient.java
  23. 5 4
      rankin-user-service/src/main/java/cn/rankin/userservice/controller/TerminalUserController.java

+ 84 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/controller/ProductController.java

@@ -0,0 +1,84 @@
+package cn.rankin.apiweb.controller;
+
+import cn.rankin.apiweb.assist.resolver.NeedUser;
+import cn.rankin.apiweb.service.product.ProductClient;
+import cn.rankin.apiweb.service.product.ProductService;
+import cn.rankin.common.utils.api.model.APIResult;
+import cn.rankin.data.api.app.vo.DeviceUserVo;
+import cn.rankin.data.api.product.entity.Product;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.*;
+
+
+@RestController
+@RequestMapping(value = "/product")
+@Slf4j
+public class ProductController {
+
+    @Autowired
+    private ProductService productService;
+
+    @Autowired
+    private ProductClient productClient;
+
+    @RequestMapping(value = "/{pid}/relatedPkg", method = RequestMethod.GET)
+    public APIResult getRelatedPkg(@NeedUser DeviceUserVo user, @PathVariable("pid") String pid) {
+        String merchantId = user.getMerchantId();
+
+        //get Pkg
+        List<Product> packages = productClient.getRelatedPackages(pid, merchantId, 0L, 10, "id", Sort.Direction.ASC);
+
+        //get each product in Pkg
+        List<Map<String, Object>> recs = new ArrayList<>();
+
+        for(Product pkg : packages){
+
+            if(null == pkg.getPid()){
+                log.error("Related Package pid is Null, pid={}", pid);
+                continue;
+            }
+
+            Product targetPkg =  productClient.getPackage(pkg.getPid());
+
+            List<Product> pkgContents = Optional.ofNullable(targetPkg).map(v -> v.getChildrens()).orElse(new ArrayList<>());
+
+            if(null == pkgContents){
+                pkgContents = new ArrayList<>();
+            }
+
+            List<Map<String, Object>> lightProducts = new ArrayList<>();
+            for(Product content : pkgContents){
+               Map<String, Object> tmp = new HashMap<>();
+               tmp.put("id", content.getPid());
+               tmp.put("name", content.getName());
+               tmp.put("type", content.getType());
+               tmp.put("code", content.getCode());
+               lightProducts.add(tmp);
+            }
+
+            Map<String, Object> rec = new HashMap<String, Object>();
+            rec.put("id", pkg.getPid());
+            rec.put("name", pkg.getName());
+            rec.put("code", pkg.getCode());
+            rec.put("goods", pkg.getGoods());
+            rec.put("recs", lightProducts);
+
+            recs.add(rec);
+        }
+
+        Map<String, Object> data = new HashMap<>();
+
+        data.put("totalNum", recs.size());
+        data.put("recs", recs);
+
+        return APIResult.ok(data);
+
+    }
+}

+ 30 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/controller/RecommendController.java

@@ -6,11 +6,14 @@ import cn.rankin.apiweb.service.product.ProductService;
 import cn.rankin.common.utils.api.model.APIResult;
 import cn.rankin.data.api.app.vo.DeviceUserVo;
 import cn.rankin.data.api.app.vo.RecommendVo;
+import cn.rankin.data.api.product.entity.Poster;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
 @RestController
@@ -29,4 +32,31 @@ public class RecommendController {
         String merchantId = user.getMerchantId();
         return productService.getRecommendCourses(merchantId);
     }
+
+    /**
+     * Get recommend posters
+      * @param user
+     * @return
+     */
+    @RequestMapping(value = "/posters", method = RequestMethod.GET)
+    public APIResult<Object> getPosters(@NeedUser DeviceUserVo user) {
+        if (user == null) {
+            return APIResult.error(ApiWebCode.NOT_EXISTS);
+        }
+
+        String merchantId = user.getMerchantId();
+
+        //productService.getRecommendCourses(merchantId);
+
+        List<Poster> posters = productService.getPosters(merchantId);
+        if (null == posters){
+            posters = new ArrayList<>();
+        }
+
+        HashMap<String, Object> data = new HashMap<String, Object>();
+        data.put("num", posters.size());
+        data.put("recs",posters);
+
+        return APIResult.ok(data);
+    }
 }

+ 47 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/controller/UserController.java

@@ -2,23 +2,34 @@ package cn.rankin.apiweb.controller;
 
 import cn.rankin.apiweb.assist.resolver.NeedUser;
 import cn.rankin.apiweb.code.ApiWebCode;
+import cn.rankin.apiweb.service.product.ProductService;
 import cn.rankin.apiweb.service.user.UserService;
 import cn.rankin.common.utils.api.model.APIResult;
 import cn.rankin.data.api.app.vo.DeviceUserVo;
 import cn.rankin.data.api.app.vo.UserInfoVo;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 @RestController
 @RequestMapping(value = "/user")
+@Slf4j
 public class UserController {
 
     @Autowired
     private UserService userService;
 
+    @Autowired
+    private ProductService productService;
+
     @RequestMapping(method = RequestMethod.GET)
     public APIResult<UserInfoVo> getUserInfo(@NeedUser DeviceUserVo deviceUserVo) {
         String uid = deviceUserVo.getUid();
@@ -30,4 +41,40 @@ public class UserController {
         return APIResult.ok(userInfoVo);
     }
 
+    @RequestMapping(value="/product/valid", method = RequestMethod.GET)
+    public APIResult getProductValid(@NeedUser DeviceUserVo user) {
+        String uid = user.getUid();
+        if (StringUtils.isEmpty(uid)) {
+            log.error("Uid-Empty, uid={}", uid);
+            return APIResult.error(ApiWebCode.NOT_EXISTS);
+        }
+
+        List<Map<String, Object>> products =  userService.getProductValid(uid);
+
+
+        if (null == products){
+            products = new ArrayList<>();
+        }
+
+        log.error("Valid-Product-Get-From-Service, product={}, len={}", products, products.size());
+
+        List<Map<String, Object> > recs = new ArrayList<>();
+
+        for(Map<String, Object> item : products){
+            Map<String, Object> rec = new HashMap<>();
+            rec.put("id", item.get("pid"));
+            rec.put("title", item.get("name"));
+            rec.put("beginTime", item.get("beginTime"));
+            rec.put("endTime", item.get("endTime"));
+
+            recs.add(rec);
+        }
+
+        HashMap<String, Object> data = new HashMap<String, Object>();
+        data.put("totalNum", recs.size());
+        data.put("recs", recs);
+
+        return APIResult.ok(data);
+    }
+
 }

+ 46 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/service/product/ProductClient.java

@@ -11,10 +11,13 @@ import cn.rankin.data.api.product.vo.CourseItemVo;
 import cn.rankin.data.api.product.vo.SupportItemVo;
 import cn.rankin.data.api.product.vo.TrainingItemVo;
 import org.springframework.cloud.netflix.feign.FeignClient;
+import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Component;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 @FeignClient(name = "${service.product.name}")
 public interface ProductClient {
@@ -55,6 +58,25 @@ public interface ProductClient {
     @RequestMapping(value = "/goods/{goodsId}", method = RequestMethod.GET)
     APIResult<Goods> findGoods(@PathVariable("goodsId") String goodsId);
 
+    @RequestMapping(value = "/merchant/{merchantId}/posters", method = RequestMethod.GET)
+    List<Poster> getPosters(@PathVariable("merchantId") String merchantId, @RequestParam("start") Long start,
+                                   @RequestParam("offset") Integer offset, @RequestParam("sortKey") String sortKey,
+                                   @RequestParam("direction") Sort.Direction direction);
+
+    @RequestMapping(value = "/user/{uid}/product/valid", method = RequestMethod.GET)
+    List<Map<String, Object>> getProductValid(@PathVariable("uid") String uid, @RequestParam("start") Long start,
+                                              @RequestParam("offset") Integer offset, @RequestParam("sortKey") String sortKey,
+                                              @RequestParam("direction") Sort.Direction direction);
+
+    @RequestMapping(value = "/product/{pid}/relatedPkg", method = RequestMethod.GET)
+    List<Product> getRelatedPackages(@PathVariable("pid") String pid, @RequestParam("merchantId") String merchantId, @RequestParam("start") Long start,
+                                              @RequestParam("offset") Integer offset, @RequestParam("sortKey") String sortKey,
+                                              @RequestParam("direction") Sort.Direction direction);
+
+    @RequestMapping(value = "/package/{pid}", method = RequestMethod.GET)
+    Product getPackage(@PathVariable("pid") String pid);
+
+
     @Component
     class ProductClientHystrix implements ProductClient {
 
@@ -117,5 +139,29 @@ public interface ProductClient {
         public APIResult<Goods> findGoods(String goodsId) {
             return APIResult.error(ApiWebCode.SERVER_ERROR);
         }
+
+        public List<Poster> getPosters(String merchantId, Long start,
+                                Integer offset, String sortKey, Sort.Direction direction){
+            return new ArrayList<>();
+        }
+
+
+        @Override
+        public List<Map<String, Object>> getProductValid(String uid, Long start,
+                                                         Integer offset, String sortKey, Sort.Direction direction){
+            return new ArrayList<>();
+        }
+
+        @Override
+        public List<Product> getRelatedPackages(String pid, String merchantId, Long start,
+                                                         Integer offset, String sortKey, Sort.Direction direction){
+            return new ArrayList<>();
+        }
+
+        @Override
+        public Product getPackage(String pid){
+            return null;
+        }
+
     }
 }

+ 5 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/service/product/ProductService.java

@@ -12,6 +12,7 @@ import cn.rankin.data.api.product.vo.CourseItemVo;
 import cn.rankin.data.api.product.vo.SupportItemVo;
 import cn.rankin.data.api.product.vo.TrainingItemVo;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
@@ -101,4 +102,8 @@ public class ProductService {
         return APIResult.error(ApiWebCode.ACCESS_DENIED);
     }
 
+    public List<Poster> getPosters(String merchantId){
+        return productClient.getPosters(merchantId, 0L, 10, "sort", Sort.Direction.ASC);
+    }
+
 }

+ 2 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/service/user/UserClient.java

@@ -34,6 +34,7 @@ public interface UserClient {
     @RequestMapping(value = "/white/user/{userId}", method = RequestMethod.GET)
     APIResult<WhiteUserVo> findWhiteUserById(@PathVariable("userId") String userId);
 
+
     @Component
     class UserServiceHystrix implements UserClient {
 
@@ -71,5 +72,6 @@ public interface UserClient {
         public APIResult<WhiteUserVo> findWhiteUserById(String userId) {
             return APIResult.error(ApiWebCode.SERVER_ERROR);
         }
+
     }
 }

+ 13 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/service/user/UserService.java

@@ -1,6 +1,7 @@
 package cn.rankin.apiweb.service.user;
 
 import cn.rankin.apiweb.code.ApiWebCode;
+import cn.rankin.apiweb.service.product.ProductClient;
 import cn.rankin.apiweb.utils.SecurityManager;
 import cn.rankin.common.utils.api.model.APIResult;
 import cn.rankin.common.utils.api.model.BaseCode;
@@ -10,6 +11,7 @@ import cn.rankin.common.utils.service.RedisService;
 import cn.rankin.data.api.app.dto.LoginInfoDTO;
 import cn.rankin.data.api.app.vo.DeviceUserVo;
 import cn.rankin.data.api.app.vo.UserInfoVo;
+import cn.rankin.data.api.product.entity.Product;
 import cn.rankin.data.api.user.dto.TerminalDeviceDTO;
 import cn.rankin.data.api.user.vo.TerminalDeviceVo;
 import cn.rankin.data.api.user.vo.TerminalUserVo;
@@ -18,9 +20,12 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.time.DateUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
 
 import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 
 @Service
@@ -39,6 +44,9 @@ public class UserService {
     private UserClient userClient;
 
     @Autowired
+    private ProductClient productClient;
+
+    @Autowired
     private RedisService redisService;
 
     public APIResult<UserInfoVo> login(LoginInfoDTO loginInfoDTO) {
@@ -248,4 +256,9 @@ public class UserService {
         deviceUserVo.setExpireAt(expireAt);
         deviceUserVo.setRefreshAt(nowTime);
     }
+
+    public List<Map<String, Object>> getProductValid(String uid){
+        //TODO: move this method to userCient
+        return productClient.getProductValid(uid, 0L, 50, "endTime", Sort.Direction.ASC);
+    }
 }

+ 5 - 0
rankin-api-web/src/main/java/cn/rankin/apiweb/utils/RequestHeaderManager.java

@@ -34,10 +34,15 @@ public class RequestHeaderManager {
      */
     public static String getRequestParameter(HttpServletRequest request, String key){
         //first check header
+        /*
         if (null != request.getHeader(key)){
             return request.getHeader(key);
         }
         return request.getParameter(key);
+        */
+
+        //use Header directly
+        return request.getHeader(key);
     }
 
 

+ 43 - 0
rankin-common-utils/src/main/java/cn/rankin/common/utils/Proxy/ProxyWrapper.java

@@ -0,0 +1,43 @@
+package cn.rankin.common.utils.Proxy;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+
+class ProxyWrapper implements InvocationHandler {
+    //被代理类的对象
+    private Object target;
+
+    //绑定被代理对象
+    public Object bind(Object target){
+        this.target = target;
+        //返回实现了被代理类所实现的所有接口的Object对象,即动态代理,需要强制转型
+        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
+                target.getClass().getInterfaces(), this);
+    }
+
+    //日志记录方法
+    private void log(String method){
+        return;
+    }
+
+    /**
+     * <p>Discription:覆盖InvocationHandler接口中的invoke()方法</p>
+     * @param proxy 需要代理的对象
+     * @param method 真实主体要调用的执行方法
+     * @param args 调用方法时传递的参数
+     * @return
+     * @throws Throwable
+     * @author       : lcma
+     * @update       : 2016年10月9日下午2:46:29
+     */
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        //使用反射中的invoke()对方法进行动态调用
+        Object obj = method.invoke(this.target, args);
+        return obj;
+    }
+
+}
+

+ 2 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/app/vo/ItemGoodsVo.java

@@ -17,4 +17,6 @@ public class ItemGoodsVo implements Serializable {
     private BigDecimal terminalPrice;
 
     private Boolean isInCart;
+
+    private String shopQR;
 }

+ 4 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/product/entity/Goods.java

@@ -82,6 +82,10 @@ public class Goods implements Serializable {
     @Temporal(TemporalType.TIMESTAMP)
     private Date gmtModified;
 
+    @Column(name = "shop_qr")
+    //shop qr code
+    private String shopQR;
+
     @Transient
     private Boolean isInCart;
 }

+ 56 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/product/entity/Poster.java

@@ -0,0 +1,56 @@
+package cn.rankin.data.api.product.entity;
+
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.ProductTypeEnum;
+import lombok.Data;
+import lombok.ToString;
+import org.hibernate.annotations.DynamicInsert;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@ToString
+@Entity
+@Table(name = "p_posters")
+@DynamicInsert
+@DynamicUpdate
+public class Poster implements Serializable {
+    /**
+     * 推荐
+     */
+    private static final long serialVersionUID = 1L;
+
+    @Id
+    private String id;
+
+    @Column(name = "merchant_id")
+    private String merchantId;
+
+    @Column
+    private String pid;
+
+    @Column
+    private String img;
+
+    @Column
+    private Integer sort;
+
+    @Enumerated(EnumType.ORDINAL)
+    private ProductTypeEnum type;
+
+    @Enumerated(EnumType.ORDINAL)
+    private BaseStatusEnum status;
+
+    @Column(name = "gmt_created", updatable = false, insertable = false, columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP")
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date gmtCreated;
+
+    @Column(name = "gmt_modified", updatable = false, insertable = false, columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date gmtModified;
+
+}
+

+ 8 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/product/entity/Product.java

@@ -10,6 +10,7 @@ import org.hibernate.annotations.DynamicUpdate;
 import javax.persistence.*;
 import java.io.Serializable;
 import java.util.Date;
+import java.util.List;
 
 @Data
 @ToString
@@ -45,5 +46,12 @@ public class Product implements Serializable {
     @Column(name = "gmt_modified", updatable = false, insertable = false, columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
     @Temporal(TemporalType.TIMESTAMP)
     private Date gmtModified;
+
+    @Transient
+    private List<Goods> goods;
+
+    //Just For Packages
+    @Transient
+    private List<Product> childrens;
 }
 

+ 42 - 0
rankin-product-service/src/main/java/cn/rankin/productservice/controller/MerchantController.java

@@ -0,0 +1,42 @@
+package cn.rankin.productservice.controller;
+
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.data.api.product.entity.Poster;
+import cn.rankin.productservice.repository.PosterRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RestController
+@RequestMapping(value = "/merchant")
+@Slf4j
+public class MerchantController {
+
+    @Autowired
+    private PosterRepository posterRepo;
+
+    @RequestMapping(value = "/{merchantId}/posters", method = RequestMethod.GET)
+    public List<Poster> getPosters(@PathVariable("merchantId") String merchantId, @RequestParam("start") Long start,
+                                         @RequestParam("offset") Integer offset, @RequestParam("sortKey") String sortKey,
+                                         @RequestParam("direction") Sort.Direction direction) {
+
+        //get posters
+        Poster findSample = new Poster();
+        findSample.setMerchantId(merchantId);
+        findSample.setStatus(BaseStatusEnum.NORMAL);
+
+        List<Poster> posters = posterRepo.find(findSample, start, offset, new Sort(direction, sortKey));
+
+        if (null == posters){
+            posters = new ArrayList<>();
+        }
+
+        log.info("Find Posters, len={}, merchantId={}", posters.size(), merchantId);
+        return posters;
+    }
+}
+

+ 43 - 0
rankin-product-service/src/main/java/cn/rankin/productservice/controller/PackageController.java

@@ -0,0 +1,43 @@
+package cn.rankin.productservice.controller;
+
+import cn.rankin.data.api.product.entity.Product;
+import cn.rankin.productservice.repository.GoodsRepository;
+import cn.rankin.productservice.service.PackageService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+
+@RestController
+@RequestMapping(value = "/package")
+@Slf4j
+public class PackageController {
+
+    @Autowired
+    private PackageService packageService;
+
+    @Autowired
+    private GoodsRepository goodsRepository;
+
+    @RequestMapping(value = "/{pid}", method = RequestMethod.GET)
+    public Product getPackage(@PathVariable("pid") String pid) {
+
+        if(null == pid || pid.isEmpty()){
+            return null;
+        }
+
+        Product pkg =  packageService.get(pid);
+
+        if (null == pkg){
+            log.info("Cannot Find Package By pkgId, pkgId={}", pid);
+            return null;
+        }
+
+        //List<Goods> goods = goodsRepository.findByPidAndMerchantId(pid, merchantId);
+
+        //pkg.setGoods(goods);
+
+        return pkg;
+    }
+}
+

+ 42 - 2
rankin-product-service/src/main/java/cn/rankin/productservice/controller/cms/ProductController.java

@@ -1,4 +1,4 @@
-package cn.rankin.productservice.controller.cms;
+package cn.rankin.productservice.controller;
 
 import cn.rankin.common.utils.api.model.APIResult;
 import cn.rankin.common.utils.api.page.Page;
@@ -7,11 +7,15 @@ import cn.rankin.data.api.product.dto.*;
 import cn.rankin.data.api.product.entity.*;
 import cn.rankin.data.api.product.entity.Package;
 import cn.rankin.productservice.code.ProductServiceAPICode;
+import cn.rankin.productservice.repository.GoodsRepository;
+import cn.rankin.productservice.service.PackageService;
 import cn.rankin.productservice.service.ProductService;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -23,6 +27,12 @@ public class ProductController {
     @Autowired
     private ProductService productService;
 
+    @Autowired
+    private PackageService packageService;
+
+    @Autowired
+    private GoodsRepository goodsRepository;
+
     @RequestMapping(method = RequestMethod.GET)
     public APIResult<Page<Product>> search(ProductSearchDTO searchDTO) {
         Product product = new Product();
@@ -56,7 +66,7 @@ public class ProductController {
         Map<String, Object> product = productService.getProduct(productId);
         if(null == product){
             return APIResult.error(ProductServiceAPICode.NOT_EXISTS);
-        }else{
+        } else{
             return APIResult.ok(product);
         }
 
@@ -117,4 +127,34 @@ public class ProductController {
     public APIResult<List<Product>> findByPids(@RequestParam("id") List<String> pidList) {
         return productService.findByPids(pidList);
     }
+
+
+    @RequestMapping(value = "/{pid}/relatedPkg", method = RequestMethod.GET)
+    public List<Product> getRelatedPkg(@PathVariable("pid") String pid, @RequestParam("merchantId") String merchantId, @RequestParam("start") Long start,
+                                       @RequestParam("offset") Integer offset, @RequestParam("sortKey") String sortKey,
+                                       @RequestParam("direction") Sort.Direction direction) {
+
+        //get pkgs
+        List<Product> pkgs = productService.getRelatedPackages(pid, merchantId, start, offset, sortKey, Sort.Direction.ASC);
+        for (Product pkg :pkgs){
+
+            List<Product> childrens = packageService.getChildrens(pkg.getPid());
+
+            //goods
+            List<Goods> goodsList = null;
+
+            if(null != pkg.getPid()){
+                goodsList = goodsRepository.findByPidAndMerchantId(pkg.getPid(), merchantId);
+            }
+
+            pkg.setChildrens(childrens);
+            pkg.setGoods(goodsList);
+        }
+
+        if(null == pkgs){
+            pkgs = new ArrayList<>();
+        }
+
+        return pkgs;
+    }
 }

+ 80 - 4
rankin-product-service/src/main/java/cn/rankin/productservice/controller/auth/AuthController.java

@@ -1,21 +1,42 @@
 package cn.rankin.productservice.controller.auth;
 
 import cn.rankin.common.utils.api.model.APIResult;
+import cn.rankin.common.utils.constant.Constant;
+import cn.rankin.common.utils.util.BeanUtil;
 import cn.rankin.data.api.auth.dto.InnerAuthDTO;
 import cn.rankin.data.api.auth.vo.AuthResult;
+import cn.rankin.data.api.auth.vo.AuthVo;
+import cn.rankin.data.api.product.entity.Product;
+import cn.rankin.productservice.repository.ProductRepository;
+import cn.rankin.productservice.service.ProductService;
+import cn.rankin.productservice.service.auth.AuthClient;
 import cn.rankin.productservice.service.auth.AuthService;
+import lombok.extern.slf4j.Slf4j;
 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.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.data.domain.Sort;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 @RestController
+@Slf4j
 public class AuthController {
 
     @Autowired
     private AuthService authService;
 
+    @Autowired
+    private AuthClient authClient;
+
+    @Autowired
+    private ProductRepository productRepository;
+
+    @Autowired
+    private ProductService  productService;
+
     @RequestMapping(value = "/auth", method = RequestMethod.POST)
     public APIResult<AuthResult> auth(@RequestBody InnerAuthDTO authDTO) {
         String userId = authDTO.getUserId();
@@ -23,4 +44,59 @@ public class AuthController {
         String merchantId = authDTO.getMerchantId();
         return authService.auth(userId, merchantId, itemId);
     }
+
+    @RequestMapping(value = "/user/{uid}/product/valid", method = RequestMethod.GET)
+    public List<Map<String, Object>> getProductValid(@PathVariable("uid") String uid, @RequestParam("start") Long start,
+                                                     @RequestParam("offset") Integer offset, @RequestParam("sortKey") String sortKey,
+                                                     @RequestParam("direction") Sort.Direction direction){
+
+        List<AuthVo> authItems =  authClient.getUserValidProduct(uid, Constant.BIZ_CODE).getData();
+        if (null == authItems){
+            authItems = new ArrayList<>();
+        }
+
+        ArrayList<String> pids = new ArrayList<>();
+
+        HashMap<String, AuthVo> authMap = new HashMap<>();
+        for (AuthVo item: authItems ) {
+            if(null == item.getPid()) {
+                log.error("Pid Is Null, uid={}", uid);
+                continue;
+            }
+            pids.add(item.getPid());
+            authMap.put(item.getPid(), item);
+        }
+
+        List< Map<String, Object> > result = new ArrayList<>();
+
+        if (pids.isEmpty()){
+            log.error("No Valid Pids For User, uid={}", uid);
+            return result;
+        }
+
+        List<Product> products = productRepository.findByPids(pids);
+
+        //assemble result
+        for(Product product : products){
+
+            String pid = product.getPid();
+            if (!authMap.containsKey(pid)){
+                log.error("Pid Not Exist in AuthMap, pid={}", pid);
+                continue;
+            }
+
+            AuthVo authInfo = authMap.get(pid);
+
+            Map<String, Object> rec = BeanUtil.convertToMap(product, true);
+
+            rec.put("beginTime", authInfo.getStartTime());
+            rec.put("endTime", authInfo.getEndTime());
+
+            result.add(rec);
+
+        }
+
+        return result;
+    }
+
 }

+ 9 - 0
rankin-product-service/src/main/java/cn/rankin/productservice/repository/PosterRepository.java

@@ -0,0 +1,9 @@
+package cn.rankin.productservice.repository;
+
+import cn.rankin.common.utils.jpa.BasicJpaRepository;
+import cn.rankin.data.api.product.entity.Poster;
+
+public interface PosterRepository extends BasicJpaRepository<Poster, String> {
+
+}
+

+ 56 - 1
rankin-product-service/src/main/java/cn/rankin/productservice/service/PackageService.java

@@ -12,19 +12,20 @@ import cn.rankin.productservice.code.ProductServiceAPICode;
 import cn.rankin.productservice.repository.PackageRepository;
 import cn.rankin.productservice.repository.ProductRepository;
 import cn.rankin.productservice.utils.DTOConverter;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
 import javax.transaction.Transactional;
-import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 @Service
+@Slf4j
 public class PackageService {
 
     @Autowired
@@ -44,6 +45,60 @@ public class PackageService {
         return count > 0;
     }
 
+    /**
+     *
+     * @param pid
+     * @return package's children list
+     */
+    public List<Product> getChildrens(String pid){
+
+        List<PackageProductVo> packageProductVoList = getPackageProducts(pid);
+
+        //get Product by pids
+        List<String> pids = new ArrayList<>();
+
+        for(PackageProductVo tmp : packageProductVoList){
+            if (null == tmp.getPid() || pid.equals(tmp.getPid())){
+                continue;
+            }
+            pids.add(tmp.getPid());
+        }
+
+        if(pids.isEmpty()){
+            log.info("Cannot Find Package Childrens, pid={}", pid);
+            return new ArrayList<>();
+        }
+
+        List<Product> products = productRepository.findByPids(pids);
+
+        if (null == products){
+            products = new ArrayList<>();
+        }
+
+        return products;
+    }
+
+    /**
+     *
+     * @param pid
+     * @return product, with valid package fields
+     */
+    public Product get(String pid){
+
+        Product pkg = productRepository.findByPid(pid);
+
+        if (null == pkg){
+            log.error("Cannot Find Product By pid, pid={}", pid);
+            return null;
+        }
+
+        List<Product> childrens = getChildrens(pid);
+
+        pkg.setChildrens(childrens);
+
+        return pkg;
+    }
+
     public APIResult<Package> getPackage(String pkgId) {
         Package pkg = packageRepository.find(pkgId);
         if (pkg == null) {

+ 49 - 4
rankin-product-service/src/main/java/cn/rankin/productservice/service/ProductService.java

@@ -14,18 +14,20 @@ import cn.rankin.data.api.product.entity.*;
 import cn.rankin.data.api.product.entity.Package;
 import cn.rankin.productservice.code.ProductServiceAPICode;
 import cn.rankin.productservice.repository.MerchantProductRepository;
+import cn.rankin.productservice.repository.PackageProductRelationRepository;
 import cn.rankin.productservice.repository.ProductRepository;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
 
 import javax.transaction.Transactional;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 import static cn.rankin.productservice.utils.DTOConverter.convert;
 
 @Service
+@Slf4j
 public class ProductService {
 
     @Autowired
@@ -46,6 +48,9 @@ public class ProductService {
     @Autowired
     private TrainingService trainingService;
 
+    @Autowired
+    private PackageProductRelationRepository packageProductRelationRepository;
+
     public APIResult<Page<Product>> search(Product product, Integer pageNo, Integer pageSize, LinkedHashMap<String, BaseOrderEnum> sort) {
         Long count = productRepository.count(product);
         Page<Product> page = new Page<>(count, pageNo, pageSize);
@@ -89,7 +94,7 @@ public class ProductService {
     }
 
     public Map<String, Object> getProduct(String productId) {
-        Map<String, Object> result = null;
+        Map<String, Object> result = new HashMap<>();
 
 
         Product product = productRepository.findByPid(productId);
@@ -139,6 +144,46 @@ public class ProductService {
         return packageService.getPackage(productId);
     }
 
+    /**
+     * Get Related Packge by pid
+     * @param pid
+     * @param start
+     * @param offset
+     * @param sortKey
+     * @param direction
+     * @return Plain Product, without extra fields like childrens etc.
+     */
+    public List<Product> getRelatedPackages(String pid, String merchantId, Long start, Integer offset, String sortKey, Sort.Direction direction){
+        List<PackageProductRelation> currentRelationList = packageProductRelationRepository.findByPid(pid);
+
+        //get pkgs
+        List<String> pids = new ArrayList<>();
+
+        for(PackageProductRelation rel : currentRelationList){
+            //skip pid not belong merchant
+            String pkgId = rel.getPkgId();
+            if(null == pkgId || null == merchantProductRepository.findByPidAndMerchantId(pkgId, merchantId)){
+                log.info("Skip, pkgId not Belong Merchant, pkgId={}, merchantId={}", pkgId, merchantId);
+                continue;
+            }
+
+            pids.add(pkgId);
+        }
+
+        if (pids.isEmpty()){
+            log.info("No Related Package Find By pid, pid={}", pid);
+            return new ArrayList<>();
+        }
+
+        List<Product> pkgs = productRepository.findByPids(pids);
+
+        if (null == pkgs){
+            pkgs = new ArrayList<>();
+        }
+        return pkgs;
+    }
+
+
     @Transactional
     public APIResult delete(String productId) {
         Product product = productRepository.findByPid(productId);

+ 1 - 0
rankin-product-service/src/main/java/cn/rankin/productservice/service/app/ItemService.java

@@ -401,6 +401,7 @@ public class ItemService {
         itemGoodsVo.setId(goods.getId());
         itemGoodsVo.setChargeUnit(goods.getChargeUnit());
         itemGoodsVo.setTerminalPrice(goods.getTerminalPrice());
+        itemGoodsVo.setShopQR(goods.getShopQR());
         return itemGoodsVo;
     }
 }

+ 4 - 3
rankin-product-service/src/main/java/cn/rankin/productservice/service/auth/AuthClient.java

@@ -4,9 +4,7 @@ import cn.rankin.common.utils.api.model.APIResult;
 import cn.rankin.data.api.auth.dto.AuthQueryDTO;
 import cn.rankin.data.api.auth.vo.AuthVo;
 import org.springframework.cloud.netflix.feign.FeignClient;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
@@ -16,6 +14,9 @@ public interface AuthClient {
     @RequestMapping(value = "/acenter/v1/auth/list", method = RequestMethod.POST, consumes = "application/json")
     APIResult<List<AuthVo>> auth(@RequestBody AuthQueryDTO authQueryDTO);
 
+    @RequestMapping(value = "/acenter/v1/auth/uid/{uid}", method = RequestMethod.GET, consumes = "application/json")
+    APIResult<List<AuthVo>> getUserValidProduct(@PathVariable("uid") String uid, @RequestParam("bizCode") String bizCode);
+
 //    @Component
 //    class AuthServiceHystrix implements AuthClient {
 //

+ 5 - 4
rankin-user-service/src/main/java/cn/rankin/userservice/controller/TerminalUserController.java

@@ -2,17 +2,17 @@ package cn.rankin.userservice.controller;
 
 import cn.rankin.common.utils.api.model.APIResult;
 import cn.rankin.common.utils.api.page.Page;
+import cn.rankin.common.utils.enums.BaseOrderEnum;
 import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.util.HttpUtil;
 import cn.rankin.common.utils.util.ProvinceUtil;
 import cn.rankin.data.api.user.dto.TerminalUserDTO;
 import cn.rankin.data.api.user.dto.TerminalUserSearchDTO;
-import cn.rankin.common.utils.enums.BaseOrderEnum;
-import cn.rankin.common.utils.util.HttpUtil;
-import cn.rankin.userservice.code.UserServiceAPICode;
-import cn.rankin.userservice.dto.RemoteUser;
 import cn.rankin.data.api.user.entity.Campus;
 import cn.rankin.data.api.user.entity.Merchant;
 import cn.rankin.data.api.user.entity.TerminalUser;
+import cn.rankin.userservice.code.UserServiceAPICode;
+import cn.rankin.userservice.dto.RemoteUser;
 import cn.rankin.userservice.proxy.RemoteUserProxy;
 import cn.rankin.userservice.service.CampusService;
 import cn.rankin.userservice.service.MerchantService;
@@ -241,6 +241,7 @@ public class TerminalUserController {
         return terminalUserService.delete(id);
     }
 
+
     public static void setUserInfo(TerminalUser terminalUser, Campus campus, Merchant merchant) {
         if (terminalUser == null) {
             return;