huodongdong vor 7 Jahren
Ursprung
Commit
30ccda2563
18 geänderte Dateien mit 665 neuen und 86 gelöschten Zeilen
  1. 1 1
      rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/OrderDetailStatusEnum.java
  2. 1 1
      rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/OrderStatusEnum.java
  3. 3 0
      rankin-data-api/src/main/java/cn/rankin/data/api/trade/entity/OrderProductSnapshot.java
  4. 5 0
      rankin-product-service/src/main/java/cn/rankin/productservice/controller/GoodsController.java
  5. 1 1
      rankin-product-service/src/main/java/cn/rankin/productservice/repository/ProductRepository.java
  6. 5 1
      rankin-product-service/src/main/java/cn/rankin/productservice/service/GoodsService.java
  7. 7 1
      rankin-task/src/main/java/cn/rankin/task/configuration/FeignConfiguration.java
  8. 9 1
      rankin-task/src/main/java/cn/rankin/task/repository/OrderDetailRepository.java
  9. 1 1
      rankin-task/src/main/java/cn/rankin/task/repository/ProductSoldSnapshotRepository.java
  10. 8 0
      rankin-task/src/main/java/cn/rankin/task/repository/OrderRepository.java
  11. 13 2
      rankin-task/src/main/java/cn/rankin/task/service/AuthService.java
  12. 70 6
      rankin-task/src/main/java/cn/rankin/task/service/OrderService.java
  13. 9 0
      rankin-task/src/main/java/cn/rankin/task/service/ProductService.java
  14. 9 0
      rankin-task/src/main/java/cn/rankin/task/service/UserService.java
  15. 24 69
      rankin-task/src/main/java/cn/rankin/task/task/order/OrderCompleteTask.java
  16. 492 0
      rankin-task/src/main/java/cn/rankin/task/task/order/OrderDetailCompleteTask.java
  17. 3 2
      rankin-task/src/main/java/cn/rankin/task/task/order/OrderSplitTask.java
  18. 4 0
      rankin-task/src/main/resources/bootstrap.yml

+ 1 - 1
rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/OrderDetailStatusEnum.java

@@ -2,7 +2,7 @@ package cn.rankin.common.utils.enums;
 
 public enum OrderDetailStatusEnum {
 
-    UNPAID("待支付"), PAYOK("已支付"), CANCEL("取消"), REFUND("退款"), COMPLETE("完成"), FORSEND("等待发货"), SENT("已发货"), RECEIVED("已收货");
+    UNPAID("待支付 0"), PAYOK("已支付 1"), CANCEL("取消 2"), REFUND("退款 3"), COMPLETE("完成 4"), FORSEND("等待发货 5"), SENT("已发货 6"), RECEIVED("已收货 7");
 
     String name;
 

+ 1 - 1
rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/OrderStatusEnum.java

@@ -2,7 +2,7 @@ package cn.rankin.common.utils.enums;
 
 public enum OrderStatusEnum {
 
-    UNPAID("待支付"), PAYOK("已支付"), CANCEL("取消"), REFUND("退款"), COMPLETE("完成");
+    UNPAID("待支付 0"), PAYOK("已支付 1"), CANCEL("取消 2"), REFUND("退款 3"), COMPLETE("完成 4");
 
     protected String name;
 

+ 3 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/trade/entity/OrderProductSnapshot.java

@@ -70,6 +70,9 @@ public class OrderProductSnapshot implements Serializable {
     @Column(name = "order_id")
     private String orderId;
 
+    @Column(name = "detail_id")
+    private String detailId;
+
     @Column(name = "goods_id")
     private String goodsId;
 

+ 5 - 0
rankin-product-service/src/main/java/cn/rankin/productservice/controller/GoodsController.java

@@ -40,4 +40,9 @@ public class GoodsController {
     public APIResult<List<Goods>> findByIds(@RequestParam("id") List<String> goodsIdList) {
         return goodsService.findByIds(goodsIdList);
     }
+
+    @RequestMapping(value = "/package/{pkgId}", method = RequestMethod.GET)
+    public APIResult<List<Goods>> findPackageGoods(@PathVariable("pkgId") String pkgId, @RequestParam("merchantId") String merchantId) {
+        return goodsService.findPackageGoods(pkgId, merchantId);
+    }
 }

+ 1 - 1
rankin-product-service/src/main/java/cn/rankin/productservice/repository/ProductRepository.java

@@ -11,7 +11,7 @@ public interface ProductRepository extends BasicJpaRepository<Product, String> {
 
     Product findByPid(String pid);
 
-    @Query(value = "select p from Product p where p.pid in (?1) and p.status = 0")
+    @Query(value = "select p from Product p where p.pid in (?1)")
     List<Product> findByPids(List<String> pids);
 
     @Modifying

+ 5 - 1
rankin-product-service/src/main/java/cn/rankin/productservice/service/GoodsService.java

@@ -68,8 +68,12 @@ public class GoodsService {
     }
 
     public APIResult<List<Goods>> findByIds(List<String> goodsIdList) {
-        List<Goods> goodsList = goodsRepository.findByIds(goodsIdList, BaseStatusEnum.NORMAL);
+        List<Goods> goodsList = goodsRepository.findByIds(goodsIdList);
         return APIResult.ok(goodsList);
     }
 
+    public APIResult<List<Goods>> findPackageGoods(String pkgId, String merchantId) {
+        List<Goods> goodsList = goodsRepository.findByPkgIdAndMerchantId(pkgId, merchantId);
+        return APIResult.ok(goodsList);
+    }
 }

+ 7 - 1
rankin-task/src/main/java/cn/rankin/task/configuration/FeignConfiguration.java

@@ -25,13 +25,19 @@ public class FeignConfiguration {
             requestTemplate.header("dist", "1112");
             requestTemplate.header("terminal", "mobile");
             requestTemplate.header("Content-Type", "application/json");
-            requestTemplate.header("userIp", "0.0.0.0");
+            requestTemplate.header("userIp", "123.126.111.3");
             requestTemplate.header("appVer", "6.1.1");
+            requestTemplate.header("Accept", "application/json, text/javascript, */*");
             log.info("run header interceptor");
         }
     }
 
     @Bean
+    public FeignHeaderInterceptor feignHeaderInterceptor() {
+        return new FeignHeaderInterceptor();
+    }
+
+    @Bean
     public Logger.Level feignLoggerLevel() {
 
         return Logger.Level.HEADERS;

+ 9 - 1
rankin-task/src/main/java/cn/rankin/task/repository/OrderDetailRepository.java

@@ -2,12 +2,20 @@ package cn.rankin.task.repository;
 
 import cn.rankin.common.utils.jpa.BasicJpaRepository;
 import cn.rankin.data.api.trade.entity.OrderDetail;
+import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
 
 import java.util.List;
 
 public interface OrderDetailRepository extends BasicJpaRepository<OrderDetail, String> {
 
-    @Query(value = "select * from t_order_detail o where (o.order_status = 5 and o.status = 0 and o.type = 0) or (o.order_status = 7 and o.status = 0 and o.type = 1) limit ?1", nativeQuery = true)
+    @Query(value = "select * from t_order_detail o where (o.order_status = 5 and o.status = 0 and o.type = 0) or (o.order_status = 7 and o.status = 0 and o.type = 1) order by o.order_id limit ?1", nativeQuery = true)
     List<OrderDetail> findForCompleteList(Integer limit);
+
+    @Query(value = "select o from OrderDetail o where o.orderId in (?1) and o.status = 0")
+    List<OrderDetail> findByOrderIds(List<String> orderIdList);
+
+    @Modifying
+    @Query(value = "update t_order_detail o set o.order_status = 4 where (o.id = ?1 and o.status = 0 and o.order_status = 7 and o.type = 1) or (o.order_status = 5 and o.type = 0 and o.id = ?1 and o.status = 0)", nativeQuery = true)
+    Integer complete(String detailId);
 }

+ 1 - 1
rankin-task/src/main/java/cn/rankin/task/repository/ProductSoldSnapshotRepository.java

@@ -3,5 +3,5 @@ package cn.rankin.task.repository;
 import cn.rankin.common.utils.jpa.BasicJpaRepository;
 import cn.rankin.data.api.trade.entity.OrderProductSnapshot;
 
-public interface ProductSoldSnapshotRepository extends BasicJpaRepository<OrderProductSnapshot, String> {
+public interface OrderProductSnapshotRepository extends BasicJpaRepository<OrderProductSnapshot, String> {
 }

+ 8 - 0
rankin-task/src/main/java/cn/rankin/task/repository/OrderRepository.java

@@ -12,6 +12,9 @@ public interface OrderRepository extends BasicJpaRepository<Order, String> {
     @Query(value = "select * from t_order o where o.order_status = 1 and o.split_status = 0 and o.status = 0 limit ?1", nativeQuery = true)
     List<Order> findSplitOrders(Integer limit);
 
+    @Query(value = "select * from t_order o where o.order_status != 4 and o.status = 0 and o.split_status != 0 limit ?1", nativeQuery = true)
+    List<Order> findCompleteOrders(Integer limit);
+
     // 已拆分
     @Modifying
     @Query(value = "update Order o set o.splitStatus = 2 where o.splitStatus = 0 and o.orderStatus = 1 and o.status = 0 and o.id = ?1")
@@ -21,4 +24,9 @@ public interface OrderRepository extends BasicJpaRepository<Order, String> {
     @Modifying
     @Query(value = "update Order o set o.splitStatus = 1 where o.splitStatus = 0 and o.orderStatus = 1 and o.status = 0 and o.id = ?1")
     Integer process(String orderId);
+
+    // 标记订单完成
+    @Modifying
+    @Query(value = "update Order o set o.orderStatus = 4 where o.orderStatus = 1 and o.status = 0 and o.id in (?1)")
+    Integer complete(List<String> orderIdList);
 }

+ 13 - 2
rankin-task/src/main/java/cn/rankin/task/service/AuthService.java

@@ -5,20 +5,31 @@ import cn.rankin.task.code.TaskAPICode;
 import cn.rankin.data.api.auth.dto.AuthDTO;
 import org.springframework.cloud.netflix.feign.FeignClient;
 import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 
+import java.util.List;
+
 @FeignClient(name = "auth-service", url = "${remote.auth.url}", fallback = AuthService.AuthServiceHystrix.class)
 public interface AuthService {
 
+    @RequestMapping(value = "/acenter/v1/auth/list", method = RequestMethod.POST)
+    APIResult add(@RequestBody List<AuthDTO> authList);
+
     @RequestMapping(value = "/acenter/v1/auth", method = RequestMethod.POST)
-    APIResult add(AuthDTO authDTO);
+    APIResult add(@RequestBody AuthDTO authDTO);
 
     @Component
     class AuthServiceHystrix implements AuthService {
 
         @Override
-        public APIResult add(AuthDTO authDTO) {
+        public APIResult add(List<AuthDTO> authList) {
+            return APIResult.error(TaskAPICode.SERVER_ERROR);
+        }
+
+        @Override
+        public APIResult add (AuthDTO authDTO) {
             return APIResult.error(TaskAPICode.SERVER_ERROR);
         }
     }

+ 70 - 6
rankin-task/src/main/java/cn/rankin/task/service/OrderService.java

@@ -1,22 +1,23 @@
 package cn.rankin.task.service;
 
+import cn.rankin.common.utils.enums.BaseStatusEnum;
 import cn.rankin.common.utils.enums.OrderDetailStatusEnum;
 import cn.rankin.data.api.trade.entity.Order;
 import cn.rankin.data.api.trade.entity.OrderDetail;
 import cn.rankin.data.api.trade.entity.OrderGoods;
+import cn.rankin.data.api.trade.entity.OrderProductSnapshot;
 import cn.rankin.task.repository.OrderDetailRepository;
 import cn.rankin.task.repository.OrderGoodsRepository;
+import cn.rankin.task.repository.OrderProductSnapshotRepository;
 import cn.rankin.task.repository.OrderRepository;
+import com.alibaba.fastjson.JSON;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 @Slf4j
 @Service
@@ -31,6 +32,44 @@ public class OrderService {
     @Autowired
     private OrderGoodsRepository orderGoodsRepository;
 
+    @Autowired
+    private OrderProductSnapshotRepository orderProductSnapshotRepository;
+
+    public List<Order> findOrderForCompleteList(Integer limit) {
+        List<Order> orderList = orderRepository.findCompleteOrders(limit);
+        if (orderList.size() == 0) {
+            return orderList;
+        }
+        setOrderGoods(orderList);
+        return orderList;
+    }
+
+    public List<String> findCompleteOrderFromOrderDetail(List<String> orderIdList) {
+        List<OrderDetail> orderDetailList = orderDetailRepository.findByOrderIds(orderIdList);
+        Set<String> notCompleteOrderIdSet = new HashSet<>();
+        for (OrderDetail orderDetail : orderDetailList) {
+            String orderId = orderDetail.getOrderId();
+            OrderDetailStatusEnum orderStatus = orderDetail.getOrderStatus();
+            BaseStatusEnum status = orderDetail.getStatus();
+            if (!status.equals(BaseStatusEnum.NORMAL)) {
+                continue;
+            }
+            if (!orderStatus.equals(OrderDetailStatusEnum.COMPLETE)) {
+                notCompleteOrderIdSet.add(orderId);
+            }
+        }
+
+        List<String> completeOrderIdList = new ArrayList<>();
+        for (String orderId : orderIdList) {
+            if (notCompleteOrderIdSet.contains(orderId)) {
+                continue;
+            }
+            completeOrderIdList.add(orderId);
+        }
+
+        return completeOrderIdList;
+    }
+
     public List<OrderDetail> findOrderDetailForCompleteList(Integer limit) {
         List<OrderDetail> orderDetailList = orderDetailRepository.findForCompleteList(limit);
         if (CollectionUtils.isEmpty(orderDetailList)) {
@@ -67,7 +106,11 @@ public class OrderService {
         if (CollectionUtils.isEmpty(orderList)) {
             return orderList;
         }
+        setOrderGoods(orderList);
+        return orderList;
+    }
 
+    public void setOrderGoods(List<Order> orderList) {
         List<String> orderIdList = new ArrayList<>();
         for (Order order : orderList) {
             orderIdList.add(order.getId());
@@ -92,8 +135,6 @@ public class OrderService {
             List<OrderGoods> tmpList = orderGoodsMap.get(orderId);
             order.setGoods(tmpList);
         }
-
-        return orderList;
     }
 
     @Transactional
@@ -126,5 +167,28 @@ public class OrderService {
         }
         return Boolean.TRUE;
     }
+
+    @Transactional
+    public Boolean completeDetail(String detailId) {
+        Integer count = orderDetailRepository.complete(detailId);
+        return count > 0;
+    }
+
+    @Transactional
+    public Boolean completeOrder(List<String> orderIdList) {
+        Integer count = orderRepository.complete(orderIdList);
+        if (count == orderIdList.size()) {
+            log.error("更新总订单完成状态全部成功, orderIdList={}", JSON.toJSONString(orderIdList));
+            return Boolean.TRUE;
+        }
+
+        log.error("部分订单更新完成状态失败, orderIdList={}", JSON.toJSONString(orderIdList));
+        return Boolean.FALSE;
+    }
+
+    @Transactional
+    public void insertSnapshots(List<OrderProductSnapshot> snapshotList) {
+        orderProductSnapshotRepository.save(snapshotList);
+    }
 }
 

+ 9 - 0
rankin-task/src/main/java/cn/rankin/task/service/ProductService.java

@@ -5,6 +5,7 @@ import cn.rankin.data.api.product.entity.Goods;
 import cn.rankin.data.api.product.entity.Package;
 import cn.rankin.data.api.product.entity.Product;
 import cn.rankin.task.code.TaskAPICode;
+import javafx.concurrent.Task;
 import org.springframework.cloud.netflix.feign.FeignClient;
 import org.springframework.stereotype.Component;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -26,6 +27,9 @@ public interface ProductService {
     @RequestMapping(value = "/goods/ids", method = RequestMethod.GET)
     APIResult<List<Goods>> findGoodsByIds(@RequestParam("id") List<String> ids);
 
+    @RequestMapping(value = "goods/package/{pkgId}", method = RequestMethod.GET)
+    APIResult<List<Goods>> findPackageGoods(@PathVariable("pkgId") String pkgId, @RequestParam("merchantId") String merchantId);
+
     @Component
     class ProductServiceHystrix implements ProductService {
 
@@ -43,5 +47,10 @@ public interface ProductService {
         public APIResult findGoodsByIds(List<String> ids) {
             return APIResult.error(TaskAPICode.SERVER_ERROR);
         }
+
+        @Override
+        public APIResult findPackageGoods(String pkgId, String merchantId) {
+            return APIResult.error(TaskAPICode.SERVER_ERROR);
+        }
     }
 }

+ 9 - 0
rankin-task/src/main/java/cn/rankin/task/service/UserService.java

@@ -1,6 +1,7 @@
 package cn.rankin.task.service;
 
 import cn.rankin.common.utils.api.model.APIResult;
+import cn.rankin.data.api.user.entity.Merchant;
 import cn.rankin.data.api.user.vo.CampusVo;
 import cn.rankin.data.api.user.vo.TerminalUserVo;
 import cn.rankin.task.code.TaskAPICode;
@@ -22,6 +23,9 @@ public interface UserService {
     @RequestMapping(value = "/campus/ids", method = RequestMethod.GET)
     APIResult<Map<String, CampusVo>> findCampusByIds(@RequestParam("id") List<String> campusIdList);
 
+    @RequestMapping(value = "/merchant/ids", method = RequestMethod.GET)
+    APIResult<Map<String, Merchant>> findMerchantByIds(@RequestParam("id") List<String> merchantIds);
+
     @Component
     class UserServiceHystrix implements UserService {
 
@@ -34,5 +38,10 @@ public interface UserService {
         public APIResult findCampusByIds(List<String> campusIdList) {
             return APIResult.error(TaskAPICode.SERVER_ERROR);
         }
+
+        @Override
+        public APIResult findMerchantByIds(List<String> merchantIds) {
+            return APIResult.error(TaskAPICode.SERVER_ERROR);
+        }
     }
 }

+ 24 - 69
rankin-task/src/main/java/cn/rankin/task/task/order/OrderCompleteTask.java

@@ -1,8 +1,8 @@
 package cn.rankin.task.task.order;
 
 import cn.rankin.common.utils.api.model.APIResult;
-import cn.rankin.common.utils.enums.OrderDetailTypeEnum;
 import cn.rankin.common.utils.enums.ProductTypeEnum;
+import cn.rankin.data.api.trade.entity.Order;
 import cn.rankin.data.api.trade.entity.OrderDetail;
 import cn.rankin.data.api.trade.entity.OrderGoods;
 import cn.rankin.data.api.trade.entity.OrderProductSnapshot;
@@ -15,7 +15,9 @@ import com.alibaba.fastjson.JSON;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
 import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -25,86 +27,39 @@ import java.util.Map;
 @Component
 public class OrderCompleteTask {
 
-    public final static long ONE_MINUTE = 10 * 1000;
+    public final static long INTERVAL = 10 * 1000;
 
     public final static Integer SIZE = 100;
 
     @Autowired
-    private UserService userService;
-
-    @Autowired
     private ProductService productService;
 
     @Autowired
     private OrderService orderService;
 
-    @Scheduled(fixedDelay = ONE_MINUTE)
-    public void run() {
-        List<OrderDetail> orderDetailList = orderService.findOrderDetailForCompleteList(SIZE);
-        log.info(JSON.toJSONString(orderDetailList));
-        for (OrderDetail orderDetail : orderDetailList) {
-            OrderDetailTypeEnum type = orderDetail.getType();
-            if (type.equals(OrderDetailTypeEnum.VIRTUAL)) {
-                // 要进行鉴权记录插入
-
-            }else {
-                // 直接标记完成即可
-
-            }
-        }
-
-    }
-
-    public List<OrderProductSnapshot> toSnaptshots(OrderDetail order, TerminalUserVo terminalUserVo, CampusVo campusVo) {
-        List<OrderProductSnapshot> snapshotList = new ArrayList<>();
-        String orderId = order.getId();
-        String userId = order.getUid();
-        String userName = terminalUserVo.getName();
-        String userCode = terminalUserVo.getCode();
-        String campusId = campusVo.getId();
-        String campusCode = campusVo.getCode();
-        String campusName = campusVo.getName();
+    @Autowired
+    private UserService userService;
 
-        List<String> goodsIdList = new ArrayList<>();
-        List<String> productIdList = new ArrayList<>();
-        List<OrderGoods> orderGoodsList = order.getGoods();
+    @Scheduled(fixedDelay = INTERVAL)
+    public void run() {
+        log.info("{} start", this.getClass().getName());
 
-        for (OrderGoods orderGoods : orderGoodsList) {
-            ProductTypeEnum type = orderGoods.getType();
-            String goodsId = orderGoods.getGoodsId();
-            String productId = orderGoods.getPid();
-            if (!goodsIdList.contains(goodsId)) {
-                goodsIdList.add(goodsId);
-            }
-            if(!productIdList.contains(productId)) {
-                productIdList.add(productId);
-            }
-            if (type.equals(ProductTypeEnum.PACKAGE)) {
-            }
+        List<Order> orderList = orderService.findOrderForCompleteList(SIZE);
+        if (orderList.size() == 0) {
+            log.info("load order for complete empty");
+            return;
         }
-        return null;
-
-    }
-
-    public List<TerminalUserVo> loadUser(List<String> userIdList) {
-        APIResult<List<TerminalUserVo>> apiResult = userService.findUserByIds(userIdList);
-        if (!apiResult.getSuccess()) {
-            log.error("load user error, {}", apiResult.getMessage());
-            return null;
+        List<String> orderIdList = new ArrayList<>();
+        orderList.forEach(order -> orderIdList.add(order.getId()));
+
+        List<String> completeOrderIdList = orderService.findCompleteOrderFromOrderDetail(orderIdList);
+        if (!CollectionUtils.isEmpty(completeOrderIdList)) {
+            log.info("order complete, orderIdList={}", JSON.toJSONString(completeOrderIdList));
+            orderService.completeOrder(completeOrderIdList);
+        }else {
+            log.info("no complete order");
         }
 
-        List<TerminalUserVo> terminalUserVoList = apiResult.getData();
-        return terminalUserVoList;
+        log.info("{} complete", this.getClass().getName());
     }
-
-    public Map<String, CampusVo> loadCampus(List<String> campusIdList) {
-        APIResult<Map<String, CampusVo>> apiResult = userService.findCampusByIds(campusIdList);
-        if (!apiResult.getSuccess()) {
-            log.error("load campus error, {}", apiResult.getMessage());
-            return null;
-        }
-        return apiResult.getData();
-    }
-
-}
-
+}

+ 492 - 0
rankin-task/src/main/java/cn/rankin/task/task/order/OrderDetailCompleteTask.java

@@ -0,0 +1,492 @@
+package cn.rankin.task.task.order;
+
+import cn.rankin.common.utils.api.model.APIResult;
+import cn.rankin.common.utils.constant.Constant;
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.OrderDetailTypeEnum;
+import cn.rankin.common.utils.enums.ProductTypeEnum;
+import cn.rankin.data.api.auth.dto.AuthDTO;
+import cn.rankin.data.api.product.entity.Goods;
+import cn.rankin.data.api.product.entity.Product;
+import cn.rankin.data.api.trade.entity.OrderDetail;
+import cn.rankin.data.api.trade.entity.OrderGoods;
+import cn.rankin.data.api.trade.entity.OrderProductSnapshot;
+import cn.rankin.data.api.user.entity.Merchant;
+import cn.rankin.data.api.user.vo.CampusVo;
+import cn.rankin.data.api.user.vo.TerminalUserVo;
+import cn.rankin.task.service.AuthService;
+import cn.rankin.task.service.OrderService;
+import cn.rankin.task.service.ProductService;
+import cn.rankin.task.service.UserService;
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Component
+public class OrderDetailCompleteTask {
+
+    public final static long INTERVAL = 10 * 1000;
+
+    public final static Integer SIZE = 100;
+
+    @Autowired
+    private UserService userService;
+
+    @Autowired
+    private ProductService productService;
+
+    @Autowired
+    private OrderService orderService;
+
+    @Autowired
+    private AuthService authService;
+
+    @Scheduled(fixedDelay = INTERVAL)
+    public void run() {
+        log.info("{} start", this.getClass().getName());
+
+        List<OrderDetail> orderDetailList = orderService.findOrderDetailForCompleteList(SIZE);
+        if (orderDetailList.size() == 0) {
+            log.info("load detail order for complete is empty");
+            return;
+        }
+
+        log.info("load detail order for complete num={}", orderDetailList.size());
+
+        // 获取所有goodsId and userId
+        List<String> goodsIdList = new ArrayList<>();
+        List<String> userIdList = new ArrayList<>();
+        for (OrderDetail orderDetail : orderDetailList) {
+            String userId = orderDetail.getUid();
+            if (!userIdList.contains(userId)) {
+                userIdList.add(userId);
+            }
+            List<OrderGoods> orderGoodsList = orderDetail.getGoods();
+            for (OrderGoods orderGoods : orderGoodsList) {
+                String goodsId = orderGoods.getGoodsId();
+                if (!goodsIdList.contains(goodsId)) {
+                    goodsIdList.add(orderGoods.getGoodsId());
+                }
+            }
+        }
+
+        // 获取所有商品信息
+        List<Goods> goodsList = this.loadGoods(goodsIdList);
+        if (CollectionUtils.isEmpty(goodsList)) {
+            log.error("load total goods info error");
+            return;
+        }
+
+        Map<String, Goods> goodsMap = new HashMap<>();
+        for (Goods goods : goodsList) {
+            String goodsId = goods.getId();
+            goodsMap.put(goodsId, goods);
+        }
+
+        // 获取用户信息
+        List<TerminalUserVo> terminalUserVoList = this.loadUsers(userIdList);
+        if (CollectionUtils.isEmpty(terminalUserVoList)) {
+            log.error("load user info error");
+            return;
+        }
+
+        List<String> campusIdList = new ArrayList<>();
+        Map<String, TerminalUserVo> terminalUserVoMap = new HashMap<>();
+        for (TerminalUserVo terminalUserVo : terminalUserVoList) {
+            String campusId = terminalUserVo.getCampusId();
+            if (!campusIdList.contains(campusId)) {
+                campusIdList.add(campusId);
+            }
+            terminalUserVoMap.put(terminalUserVo.getId(), terminalUserVo);
+        }
+
+        // 获取校区信息
+        Map<String, CampusVo> campusVoMap = this.loadCampus(campusIdList);
+        if (CollectionUtils.isEmpty(campusVoMap)) {
+            log.error("load campus info error");
+            return;
+        }
+
+        for (OrderDetail orderDetail : orderDetailList) {
+            String detailId = orderDetail.getId();
+            OrderDetailTypeEnum type = orderDetail.getType();
+
+            // 更新状态
+            Boolean success = orderService.completeDetail(detailId);
+            if (!success) {
+                log.error("分拆订单完成状态标记失败, detailId={}", detailId);
+                continue;
+            }
+
+            List<AuthDTO> authList = new ArrayList<>();
+            if (type.equals(OrderDetailTypeEnum.VIRTUAL)) {
+                // 要进行鉴权记录插入, 课程包按包级别插入, 不分解
+                String uid = orderDetail.getUid();
+                List<OrderGoods> orderGoodsList = orderDetail.getGoods();
+                for (OrderGoods orderGoods : orderGoodsList) {
+                    String goodsId = orderGoods.getGoodsId();
+                    Goods goods = goodsMap.get(goodsId);
+                    if (goods == null) {
+                        log.error("goods not found, detailId={}, goodsId={}", detailId, goodsId);
+                        continue;
+                    }
+                    AuthDTO authDTO = new AuthDTO();
+                    authDTO.setUid(uid);
+                    authDTO.setPid(orderGoods.getPid());
+                    // 要乘数量
+                    authDTO.setAddDays(goods.getDuration() * orderGoods.getQuantity());
+                    authDTO.setType(Constant.ProductType.COURSE);
+                    authDTO.setBizCode(Constant.BIZ_CODE);
+                    authDTO.setTitle(String.format("%s_%s", detailId, goodsId));
+                    authList.add(authDTO);
+                }
+            }
+
+            // 加入鉴权记录
+            if (authList.size() > 0) {
+                for (AuthDTO authDTO : authList) {
+                    log.info(JSON.toJSONString(authDTO));
+                    APIResult authResult = authService.add(authDTO);
+                    if (!authResult.getSuccess()) {
+                        log.error("add auth list error, detailId={}", detailId);
+                    } else {
+                        log.info("add auth list success, detailId={}", detailId);
+                    }
+                }
+            }
+
+            // 放入交易快照
+            String userId = orderDetail.getUid();
+            TerminalUserVo terminalUserVo = terminalUserVoMap.get(userId);
+            if (terminalUserVo == null) {
+                log.error("userInfo is null, detailId={}, userId={}", detailId, userId);
+                continue;
+            }
+
+            String campusId = terminalUserVo.getCampusId();
+            CampusVo campusVo = campusVoMap.get(campusId);
+            if (campusVo == null) {
+                log.error("campus info is null, detailId={}, userId={}", detailId, campusId);
+                continue;
+            }
+            List<OrderProductSnapshot> snapshotList = this.toSnaptshots(orderDetail, terminalUserVo, campusVo, goodsList);
+
+            List<OrderGoods> orderGoodsList = orderDetail.getGoods();
+            for (OrderGoods orderGoods : orderGoodsList) {
+                String goodsId = orderGoods.getGoodsId();
+                ProductTypeEnum productType = orderGoods.getType();
+                if (productType.equals(ProductTypeEnum.PACKAGE)) {
+                    Goods packageGoods = goodsMap.get(goodsId);
+                    if (packageGoods == null) {
+                        log.error("detail order goods is null, detailId={}, goodsId={}", detailId, goodsId);
+                        continue;
+                    }
+                    List<OrderProductSnapshot> packageSnapshotList = this.toSnaptshots(orderGoods, terminalUserVo, campusVo, packageGoods);
+                    snapshotList.addAll(packageSnapshotList);
+                }
+            }
+
+            orderService.insertSnapshots(snapshotList);
+        }
+
+    }
+
+    public List<OrderProductSnapshot> toSnaptshots(OrderDetail detailOrder, TerminalUserVo terminalUserVo, CampusVo campusVo,
+                                                   List<Goods> goodsList) {
+        List<OrderProductSnapshot> snapshotList = new ArrayList<>();
+        String orderId = detailOrder.getOrderId();
+        String merchantId = campusVo.getMerchantId();
+        String detailId = detailOrder.getId();
+        String userId = detailOrder.getUid();
+        String userName = terminalUserVo.getName();
+        String userCode = terminalUserVo.getCode();
+        String campusId = campusVo.getId();
+        String campusCode = campusVo.getCode();
+        String campusName = campusVo.getName();
+
+        List<String> productIdList = new ArrayList<>();
+        List<OrderGoods> orderGoodsList = detailOrder.getGoods();
+
+        for (OrderGoods orderGoods : orderGoodsList) {
+            String productId = orderGoods.getPid();
+            if (!productIdList.contains(productId)) {
+                productIdList.add(productId);
+            }
+        }
+
+        Map<String, Goods> goodsMap = new HashMap<>();
+        goodsList.forEach(goods -> goodsMap.put(goods.getId(), goods));
+
+        List<String> merchantIdList = new ArrayList<>();
+        for (Goods goods : goodsList) {
+            String cpId = goods.getCpId();
+            if (!merchantIdList.contains(cpId)) {
+                merchantIdList.add(cpId);
+            }
+        }
+        merchantIdList.add(merchantId);
+
+        Map<String, Merchant> merchantMap = this.loadMerchants(merchantIdList);
+        if (CollectionUtils.isEmpty(merchantMap)) {
+            log.error("load merchant info error, detailId={}", detailId);
+        }
+        Merchant merchant = merchantMap.get(merchantId);
+        String merchantName = merchant == null ? "" : merchant.getName();
+
+        Map<String, Product> productMap = this.loadProducts(productIdList);
+        if (CollectionUtils.isEmpty(productMap)) {
+            log.error("load product info error, detailId={}", detailId);
+        }
+
+        for (OrderGoods orderGoods : orderGoodsList) {
+            String goodsId = orderGoods.getGoodsId();
+            String productId = orderGoods.getPid();
+            Integer quantity = orderGoods.getQuantity();
+            Goods goods = goodsMap.get(goodsId);
+            Product product = productMap.get(productId);
+
+            if (goods == null || product == null) {
+                log.error("goods is null or product is null, detailId={}, goodsId={}", detailId, goodsId);
+                continue;
+            }
+
+            OrderProductSnapshot snapshot = new OrderProductSnapshot();
+            snapshot.setUid(userId);
+            snapshot.setUserCode(userCode);
+            snapshot.setUserName(userName);
+
+            snapshot.setCampusId(campusId);
+            snapshot.setCampusCode(campusCode);
+            snapshot.setCampusName(campusName);
+
+            snapshot.setOrderId(orderId);
+            snapshot.setDetailId(detailId);
+
+            snapshot.setPid(product.getPid());
+            snapshot.setProductCode(product.getCode());
+            snapshot.setProductName(product.getName());
+            snapshot.setProductType(product.getType());
+
+            snapshot.setMerchantId(merchantId);
+            snapshot.setMerchantName(merchantName);
+
+            snapshot.setGoodsId(goodsId);
+            snapshot.setDuration(goods.getDuration());
+            snapshot.setCpPrice(goods.getCpPrice());
+            snapshot.setTerminalPrice(goods.getTerminalPrice());
+            snapshot.setMerchantPrice(goods.getMerchantPrice());
+            snapshot.setChargeUnit(goods.getChargeUnit());
+            snapshot.setQuantity(quantity);
+            snapshot.setStatus(BaseStatusEnum.NORMAL);
+
+            String cpId = product.getCpId();
+            snapshot.setCpId(cpId);
+            Merchant cpMerchant = merchantMap.get(cpId);
+            String cpName = cpMerchant == null ? "" : cpMerchant.getName();
+            snapshot.setCpName(cpName);
+
+            snapshotList.add(snapshot);
+        }
+
+        return snapshotList;
+    }
+
+
+    public List<OrderProductSnapshot> toSnaptshots(OrderGoods orderGoods, TerminalUserVo terminalUserVo, CampusVo campusVo,
+                                                   Goods packageGoods) {
+        List<OrderProductSnapshot> snapshotList = new ArrayList<>();
+        String orderId = orderGoods.getOrderId();
+        String pkgId = orderGoods.getPid();
+        String merchantId = campusVo.getMerchantId();
+        String detailId = orderGoods.getId();
+        String userId = terminalUserVo.getId();
+        String userName = terminalUserVo.getName();
+        String userCode = terminalUserVo.getCode();
+        String campusId = campusVo.getId();
+        String campusCode = campusVo.getCode();
+        String campusName = campusVo.getName();
+        Integer quantity = orderGoods.getQuantity();
+        Integer duration = packageGoods.getDuration();
+
+        List<Goods> goodsList = this.loadPackageGoods(pkgId, merchantId);
+
+        List<String> productIdList = new ArrayList<>();
+        Map<String, Goods> goodsMap = new HashMap<>();
+        List<String> merchantIdList = new ArrayList<>();
+
+        for (Goods goods : goodsList) {
+            String cpId = goods.getCpId();
+            if (!merchantIdList.contains(cpId)) {
+                merchantIdList.add(cpId);
+            }
+            String productId = goods.getPid();
+            if (!productIdList.contains(productId)) {
+                productIdList.add(productId);
+            }
+            String goodsId = goods.getId();
+            goodsMap.put(goodsId, goods);
+        }
+
+        merchantIdList.add(merchantId);
+
+        Map<String, Merchant> merchantMap = this.loadMerchants(merchantIdList);
+        if (CollectionUtils.isEmpty(merchantMap)) {
+            log.error("load merchant info error, detailId={}", detailId);
+        }
+        Merchant merchant = merchantMap.get(merchantId);
+        String merchantName = merchant == null ? "" : merchant.getName();
+
+        Map<String, Product> productMap = this.loadProducts(productIdList);
+        if (CollectionUtils.isEmpty(productMap)) {
+            log.error("load product info error, detailId={}", detailId);
+        }
+
+        for (Goods goods : goodsList) {
+            ProductTypeEnum productType = goods.getType();
+            if (productType.equals(ProductTypeEnum.SUPPORT)) {
+                continue;
+            }
+
+            String goodsId = goods.getId();
+            String productId = goods.getPid();
+            Product product = productMap.get(productId);
+
+            if (product == null) {
+                log.error("product is null, detailId={}, goodsId={}", detailId, goodsId);
+                continue;
+            }
+
+            OrderProductSnapshot snapshot = new OrderProductSnapshot();
+            snapshot.setPkgId(pkgId);
+
+            snapshot.setUid(userId);
+            snapshot.setUserCode(userCode);
+            snapshot.setUserName(userName);
+
+            snapshot.setCampusId(campusId);
+            snapshot.setCampusCode(campusCode);
+            snapshot.setCampusName(campusName);
+
+            snapshot.setOrderId(orderId);
+            snapshot.setDetailId(detailId);
+
+            snapshot.setPid(productId);
+            snapshot.setProductCode(product.getCode());
+            snapshot.setProductName(product.getName());
+            snapshot.setProductType(product.getType());
+
+            snapshot.setMerchantId(merchantId);
+            snapshot.setMerchantName(merchantName);
+
+            snapshot.setGoodsId(goodsId);
+            snapshot.setDuration(duration);
+            snapshot.setCpPrice(goods.getCpPrice());
+            snapshot.setTerminalPrice(goods.getTerminalPrice());
+            snapshot.setMerchantPrice(goods.getMerchantPrice());
+            snapshot.setChargeUnit(goods.getChargeUnit());
+            snapshot.setQuantity(quantity);
+            snapshot.setStatus(BaseStatusEnum.NORMAL);
+
+            String cpId = product.getCpId();
+            snapshot.setCpId(cpId);
+            Merchant cpMerchant = merchantMap.get(cpId);
+            String cpName = cpMerchant == null ? "" : cpMerchant.getName();
+            snapshot.setCpName(cpName);
+
+            snapshotList.add(snapshot);
+        }
+
+        return snapshotList;
+    }
+
+    public Map<String, Merchant> loadMerchants(List<String> merchantIdList) {
+        APIResult<Map<String, Merchant>> apiResult = userService.findMerchantByIds(merchantIdList);
+        if (!apiResult.getSuccess()) {
+            log.error("load merchant error, retry");
+            apiResult = userService.findMerchantByIds(merchantIdList);
+        }
+        return apiResult.getData();
+    }
+
+    public List<TerminalUserVo> loadUsers(List<String> userIdList) {
+        APIResult<List<TerminalUserVo>> apiResult = userService.findUserByIds(userIdList);
+        if (!apiResult.getSuccess()) {
+            log.error("load user error, {}", apiResult.getMessage());
+            return null;
+        }
+
+        List<TerminalUserVo> terminalUserVoList = apiResult.getData();
+        return terminalUserVoList;
+    }
+
+    public Map<String, CampusVo> loadCampus(List<String> campusIdList) {
+        APIResult<Map<String, CampusVo>> apiResult = userService.findCampusByIds(campusIdList);
+        if (!apiResult.getSuccess()) {
+            log.error("load campus error, {}", apiResult.getMessage());
+            return null;
+        }
+        return apiResult.getData();
+    }
+
+    public List<Goods> loadPackageGoods(String pkgId, String merchantId) {
+        List<Goods> goodsList = null;
+        int count = 0;
+        while (count < 2) {
+            APIResult<List<Goods>> apiResult = productService.findPackageGoods(pkgId, merchantId);
+            if (apiResult.getSuccess()) {
+                goodsList = apiResult.getData();
+                break;
+            }
+            count ++;
+            log.error("load package goods error(times={}), {}", count, apiResult.getMessage());
+        }
+        return goodsList;
+    }
+
+    public List<Goods> loadGoods(List<String> goodsIdList) {
+        List<Goods> goodsList = null;
+        int count = 0;
+        while (count < 2) {
+            APIResult<List<Goods>> apiResult = productService.findGoodsByIds(goodsIdList);
+            if (apiResult.getSuccess()) {
+                goodsList = apiResult.getData();
+                break;
+            }
+            count ++;
+            log.error("load goods by ids error(times={}), {}", count, apiResult.getMessage());
+        }
+
+        return goodsList;
+    }
+
+    public Map<String, Product> loadProducts(List<String> productIdList) {
+        APIResult<List<Product>> apiResult = productService.findProductByIds(productIdList);
+        if (!apiResult.getSuccess()) {
+            log.error("load products error, {}", apiResult.getMessage());
+            apiResult = productService.findProductByIds(productIdList);
+        }
+
+        List<Product> productList = apiResult.getData();
+        if (CollectionUtils.isEmpty(productList)) {
+            return new HashMap<>();
+        }
+
+        Map<String, Product> productMap = new HashMap<>();
+        for (Product product : productList) {
+            productMap.put(product.getPid(), product);
+
+        }
+
+        return productMap;
+    }
+}
+

+ 3 - 2
rankin-task/src/main/java/cn/rankin/task/task/order/OrderSplitTask.java

@@ -29,7 +29,7 @@ import java.util.Map;
 @Component
 public class OrderSplitTask {
 
-    public final static long ONE_MINUTE = 60 * 1000;
+    public final static long INTERVAL = 60 * 1000;
 
     public final static Integer SIZE = 100;
 
@@ -39,8 +39,9 @@ public class OrderSplitTask {
     @Autowired
     private OrderService orderService;
 
-    @Scheduled(fixedDelay = ONE_MINUTE)
+    @Scheduled(fixedDelay = INTERVAL)
     public void run() {
+        log.info("{} start", this.getClass().getName());
         // 查询订单
         List<Order> orderList = orderService.findOrderSplitList(SIZE);
         if (CollectionUtils.isEmpty(orderList)) {

+ 4 - 0
rankin-task/src/main/resources/bootstrap.yml

@@ -15,3 +15,7 @@ feign:
 
 server:
   port: 10100
+
+#logging:
+#  level:
+#    root: debug