Jelajahi Sumber

订单分拆初版

huodongdong 7 tahun lalu
induk
melakukan
187f7f622b
28 mengubah file dengan 471 tambahan dan 232 penghapusan
  1. 3 1
      rankin-api-web/src/main/resources/bootstrap.yml
  2. 21 0
      rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/OrderDetailStatusEnum.java
  3. 21 0
      rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/OrderSplitStatusEnum.java
  4. 2 3
      rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/OrderStatusEnum.java
  5. 3 0
      rankin-data-api/src/main/java/cn/rankin/data/api/product/entity/Goods.java
  6. 2 0
      rankin-data-api/src/main/java/cn/rankin/data/api/product/vo/GoodsVo.java
  7. 13 3
      rankin-data-api/src/main/java/cn/rankin/data/api/trade/entity/Order.java
  8. 10 2
      rankin-data-api/src/main/java/cn/rankin/data/api/trade/entity/OrderDetail.java
  9. 4 1
      rankin-data-api/src/main/java/cn/rankin/data/api/trade/entity/OrderGoods.java
  10. 6 0
      rankin-product-service/src/main/java/cn/rankin/productservice/controller/ProductController.java
  11. 1 0
      rankin-product-service/src/main/java/cn/rankin/productservice/service/GoodsService.java
  12. 4 0
      rankin-product-service/src/main/java/cn/rankin/productservice/service/ProductService.java
  13. 8 0
      rankin-task/pom.xml
  14. 4 3
      rankin-task/src/main/java/cn/rankin/task/RankinTaskApplication.java
  15. 25 0
      rankin-task/src/main/java/cn/rankin/task/configuration/PersistConfiguration.java
  16. 7 0
      rankin-task/src/main/java/cn/rankin/task/repository/OrderDetailRepository.java
  17. 21 0
      rankin-task/src/main/java/cn/rankin/task/repository/OrderGoodsRepository.java
  18. 24 0
      rankin-task/src/main/java/cn/rankin/task/repository/OrderRepository.java
  19. 7 0
      rankin-task/src/main/java/cn/rankin/task/repository/ProductSoldSnapshotRepository.java
  20. 99 0
      rankin-task/src/main/java/cn/rankin/task/service/OrderService.java
  21. 12 11
      rankin-task/src/main/java/cn/rankin/task/service/ProductService.java
  22. 0 39
      rankin-task/src/main/java/cn/rankin/task/service/TradeService.java
  23. 0 108
      rankin-task/src/main/java/cn/rankin/task/task/order/OrderCompleteTask.java
  24. 166 12
      rankin-task/src/main/java/cn/rankin/task/task/order/OrderSplitTask.java
  25. 0 8
      rankin-trade-service/src/main/java/cn/rankin/tradeservice/controller/OrderController.java
  26. 2 4
      rankin-trade-service/src/main/java/cn/rankin/tradeservice/repository/OrderRepository.java
  27. 6 36
      rankin-trade-service/src/main/java/cn/rankin/tradeservice/service/OrderService.java
  28. 0 1
      rankin-trade-service/src/test/java/cn/rankin/tradeservice/repository/OrderRepositoryTest.java

+ 3 - 1
rankin-api-web/src/main/resources/bootstrap.yml

@@ -1,3 +1,5 @@
+profile: dev
+
 spring:
   application:
     name: api-web
@@ -5,7 +7,7 @@ spring:
     config:
       uri: http://config.rankin.com:8921
       label: master
-      profile: dev
+      profile: ${profile}
 
 server:
   port: 8600

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

@@ -0,0 +1,21 @@
+package cn.rankin.common.utils.enums;
+
+public enum OrderDetailStatusEnum {
+
+    UNPAID("待支付"), PAYOK("已支付"), CANCEL("取消"), REFUND("退款"), COMPLETE("完成"), FORSEND("等待发货"), SENT("已发货"), RECEIVED("已收货");
+
+    String name;
+
+    OrderDetailStatusEnum(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return this.name;
+    }
+}

+ 21 - 0
rankin-common-utils/src/main/java/cn/rankin/common/utils/enums/OrderSplitStatusEnum.java

@@ -0,0 +1,21 @@
+package cn.rankin.common.utils.enums;
+
+public enum OrderSplitStatusEnum {
+
+    NO("未拆分"), UN("不需拆分"), YES("已拆分");
+
+    String name;
+
+    OrderSplitStatusEnum(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return this.name;
+    }
+}

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

@@ -2,10 +2,9 @@ package cn.rankin.common.utils.enums;
 
 public enum OrderStatusEnum {
 
-    UNPAID("待支付"), PAYOK("已支付"), CANCEL("取消"), REFUND("退款"), SEND("发货"),
-    RECEIVED("收货"), COMPLETE("完成");
+    UNPAID("待支付"), PAYOK("已支付"), CANCEL("取消"), REFUND("退款"), COMPLETE("完成");
 
-    String name;
+    protected String name;
 
     OrderStatusEnum(String name) {
         this.name = name;

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

@@ -48,6 +48,9 @@ public class Goods implements Serializable {
     @Column(name = "merchant_id")
     private String merchantId;
 
+    @Column(name = "cp_id")
+    private String cpId;
+
     private Integer duration;
 
     @Column(name = "charge_unit")

+ 2 - 0
rankin-data-api/src/main/java/cn/rankin/data/api/product/vo/GoodsVo.java

@@ -21,6 +21,8 @@ public class GoodsVo implements Serializable {
 
     private String merchantId;
 
+    private String cpId;
+
     private Integer duration;
 
     private String chargeUnit;

+ 13 - 3
rankin-data-api/src/main/java/cn/rankin/data/api/trade/entity/Order.java

@@ -1,5 +1,7 @@
 package cn.rankin.data.api.trade.entity;
 
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.OrderSplitStatusEnum;
 import cn.rankin.common.utils.enums.OrderStatusEnum;
 import lombok.Data;
 import lombok.ToString;
@@ -35,9 +37,6 @@ public class Order implements Serializable {
     @Column(name = "adjust_price")
     private BigDecimal adjustPrice;
 
-    @Enumerated(EnumType.ORDINAL)
-    private OrderStatusEnum status;
-
     private String note;
 
     private String address;
@@ -46,6 +45,17 @@ public class Order implements Serializable {
 
     private String name;
 
+    @Column(name = "order_status")
+    @Enumerated(EnumType.ORDINAL)
+    private OrderStatusEnum orderStatus;
+
+    @Column(name = "split_status")
+    @Enumerated(EnumType.ORDINAL)
+    private OrderSplitStatusEnum splitStatus;
+
+    @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;

+ 10 - 2
rankin-data-api/src/main/java/cn/rankin/data/api/trade/entity/OrderDetail.java

@@ -1,6 +1,7 @@
 package cn.rankin.data.api.trade.entity;
 
-import cn.rankin.common.utils.enums.OrderStatusEnum;
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.OrderDetailStatusEnum;
 import lombok.Data;
 import lombok.ToString;
 import org.hibernate.annotations.DynamicInsert;
@@ -38,8 +39,12 @@ public class OrderDetail implements Serializable {
     @Column(name = "adjust_price")
     private BigDecimal adjustPrice;
 
+    @Column(name = "order_status")
     @Enumerated(EnumType.ORDINAL)
-    private OrderStatusEnum status;
+    private OrderDetailStatusEnum orderStatus;
+
+    @Enumerated(EnumType.ORDINAL)
+    private BaseStatusEnum status;
 
     private String note;
 
@@ -52,6 +57,9 @@ public class OrderDetail implements Serializable {
     @Column(name = "track_no")
     private String trackNo;
 
+    @Column(name = "cp_id")
+    private String cpId;
+
     @Column(name = "gmt_created", updatable = false, insertable = false, columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP")
     @Temporal(TemporalType.TIMESTAMP)
     private Date gmtCreated;

+ 4 - 1
rankin-data-api/src/main/java/cn/rankin/data/api/trade/entity/OrderGoods.java

@@ -13,7 +13,7 @@ import java.util.Date;
 @Data
 @ToString
 @Entity
-@Table(name = "t_order_goods")
+@Table(name = "t_order_goods_relation")
 @DynamicInsert
 @DynamicUpdate
 public class OrderGoods implements Serializable {
@@ -34,6 +34,9 @@ public class OrderGoods implements Serializable {
     @Enumerated(EnumType.ORDINAL)
     private ProductTypeEnum type;
 
+    @Column(name = "detail_id")
+    private String detailId;
+
     @Column(name = "gmt_created", updatable = false, insertable = false, columnDefinition = "timestamp NULL DEFAULT CURRENT_TIMESTAMP")
     @Temporal(TemporalType.TIMESTAMP)
     private Date gmtCreated;

+ 6 - 0
rankin-product-service/src/main/java/cn/rankin/productservice/controller/ProductController.java

@@ -12,6 +12,7 @@ import cn.rankin.data.api.product.entity.Package;
 import cn.rankin.data.api.product.entity.Product;
 import cn.rankin.data.api.product.entity.Support;
 import cn.rankin.productservice.service.ProductService;
+import com.sun.xml.internal.bind.v2.runtime.reflect.Lister;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -84,6 +85,11 @@ public class ProductController {
         return productService.create(packageDTO);
     }
 
+    @RequestMapping(value = "/package/{productId}", method = RequestMethod.GET)
+    public APIResult<Package> getPackage(@PathVariable("productId") String productId) {
+        return productService.getPackage(productId);
+    }
+
     @RequestMapping(value = "/{productId}", method = RequestMethod.DELETE)
     public APIResult delete(@PathVariable("productId") String productId) {
         return productService.delete(productId);

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

@@ -44,6 +44,7 @@ public class GoodsService {
         }
 
         Goods goods = convert(goodsDTO);
+        goods.setCpId(product.getCpId());
         Goods result = goodsRepository.save(goods);
         return APIResult.ok(result);
     }

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

@@ -75,6 +75,10 @@ public class ProductService {
         return APIResult.error(ProductServiceAPICode.NOT_EXISTS);
     }
 
+    public APIResult<Package> getPackage(String productId) {
+        return packageService.getPackage(productId);
+    }
+
     @Transactional
     public APIResult delete(String productId) {
         Product product = productRepository.findByPid(productId);

+ 8 - 0
rankin-task/pom.xml

@@ -43,6 +43,14 @@
 			<artifactId>spring-boot-starter-web</artifactId>
 		</dependency>
         <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
             <version>1.16.16</version>

+ 4 - 3
rankin-task/src/main/java/cn/rankin/task/RankinTaskApplication.java

@@ -1,17 +1,18 @@
 package cn.rankin.task;
 
+import cn.rankin.common.utils.jpa.SimpleJpaRepository;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.cloud.netflix.feign.EnableFeignClients;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 import org.springframework.scheduling.annotation.EnableScheduling;
 
 @EnableFeignClients
 @EnableDiscoveryClient
 @EnableScheduling
-@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
+@SpringBootApplication
+@EnableJpaRepositories(repositoryBaseClass = SimpleJpaRepository.class)
 public class RankinTaskApplication {
 
 	public static void main(String[] args) {

+ 25 - 0
rankin-task/src/main/java/cn/rankin/task/configuration/PersistConfiguration.java

@@ -0,0 +1,25 @@
+package cn.rankin.task.configuration;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.EnvironmentAware;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+
+@Configuration
+@EntityScan(basePackages={"cn.rankin.data.api.trade"})
+public class PersistConfiguration implements EnvironmentAware {
+	
+	// 日志记录器
+	private static final Logger logger = LoggerFactory.getLogger(PersistConfiguration.class);
+	
+	// 应用环境信息
+	private Environment environment;
+
+	@Override
+	public void setEnvironment(Environment environment) {
+		this.environment = environment;
+	}
+}

+ 7 - 0
rankin-task/src/main/java/cn/rankin/task/repository/OrderDetailRepository.java

@@ -0,0 +1,7 @@
+package cn.rankin.task.repository;
+
+import cn.rankin.common.utils.jpa.BasicJpaRepository;
+import cn.rankin.data.api.trade.entity.OrderDetail;
+
+public interface OrderDetailRepository extends BasicJpaRepository<OrderDetail, String> {
+}

+ 21 - 0
rankin-task/src/main/java/cn/rankin/task/repository/OrderGoodsRepository.java

@@ -0,0 +1,21 @@
+package cn.rankin.task.repository;
+
+import cn.rankin.common.utils.jpa.BasicJpaRepository;
+import cn.rankin.data.api.trade.entity.OrderGoods;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+import java.util.List;
+
+public interface OrderGoodsRepository extends BasicJpaRepository<OrderGoods, String> {
+
+    List<OrderGoods> findByOrderId(String orderId);
+
+    @Query(value = "select g from OrderGoods g where g.orderId in (?1)")
+    List<OrderGoods> findByOrderIds(List<String> orderIds);
+
+    @Modifying(clearAutomatically = true)
+    @Query(value = "update OrderGoods r set r.detailId = :detailId where r.orderId = :orderId and r.goodsId in (:ids)")
+    Integer setDetailId(@Param("detailId") String detailId, @Param("orderId") String orderId, @Param("ids") List<String> ids);
+}

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

@@ -0,0 +1,24 @@
+package cn.rankin.task.repository;
+
+import cn.rankin.common.utils.jpa.BasicJpaRepository;
+import cn.rankin.data.api.trade.entity.Order;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import java.util.List;
+
+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);
+
+    // 已拆分
+    @Modifying(clearAutomatically = true)
+    @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")
+    Integer split(String orderId);
+
+    // 不需要拆分,但也要处理
+    @Modifying(clearAutomatically = true)
+    @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);
+}

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

@@ -0,0 +1,7 @@
+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> {
+}

+ 99 - 0
rankin-task/src/main/java/cn/rankin/task/service/OrderService.java

@@ -0,0 +1,99 @@
+package cn.rankin.task.service;
+
+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.task.repository.OrderDetailRepository;
+import cn.rankin.task.repository.OrderGoodsRepository;
+import cn.rankin.task.repository.OrderRepository;
+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;
+
+@Slf4j
+@Service
+public class OrderService {
+
+    @Autowired
+    private OrderRepository orderRepository;
+
+    @Autowired
+    private OrderDetailRepository orderDetailRepository;
+
+    @Autowired
+    private OrderGoodsRepository orderGoodsRepository;
+
+    public List<Order> findSplitList(Integer limit) {
+        List<Order> orderList = orderRepository.findSplitOrders(limit);
+        if (CollectionUtils.isEmpty(orderList)) {
+            return orderList;
+        }
+
+        List<String> orderIdList = new ArrayList<>();
+        for (Order order : orderList) {
+            orderIdList.add(order.getId());
+        }
+
+        List<OrderGoods> orderGoodsList = orderGoodsRepository.findByOrderIds(orderIdList);
+        Map<String, List<OrderGoods>> orderGoodsMap = new HashMap<>();
+        for (OrderGoods orderGoods : orderGoodsList) {
+            String orderId = orderGoods.getOrderId();
+            if (!orderGoodsMap.containsKey(orderId)) {
+                List<OrderGoods> tmpList = new ArrayList<>();
+                tmpList.add(orderGoods);
+                orderGoodsMap.put(orderId, tmpList);
+            }else {
+                List<OrderGoods> tmpList = orderGoodsMap.get(orderId);
+                tmpList.add(orderGoods);
+            }
+        }
+
+        for (Order order : orderList) {
+            String orderId = order.getId();
+            List<OrderGoods> tmpList = orderGoodsMap.get(orderId);
+            order.setGoods(tmpList);
+        }
+
+        return orderList;
+    }
+
+    @Transactional
+    public Boolean split(String orderId, List<OrderDetail> orderDetailList) {
+        Integer count = 0;
+        if (orderDetailList.size() >= 2) {
+            count = orderRepository.split(orderId);
+        }else {
+            count = orderRepository.process(orderId);
+        }
+
+        if (count == 0) {
+            log.error("更新原订单分拆状态失败, orderId={}", orderId);
+            return Boolean.FALSE;
+        }
+
+        for (OrderDetail orderDetail : orderDetailList) {
+            orderDetail.setOrderStatus(OrderDetailStatusEnum.FORSEND);
+            OrderDetail one = orderDetailRepository.save(orderDetail);
+            String detailId = one.getId();
+            List<String> goodsIdList = new ArrayList<>();
+            List<OrderGoods> orderGoodsList = orderDetail.getGoods();
+            for (OrderGoods orderGoods : orderGoodsList) {
+                goodsIdList.add(orderGoods.getGoodsId());
+            }
+            Integer rowcount = orderGoodsRepository.setDetailId(detailId, orderId, goodsIdList);
+            if (rowcount > 0) {
+                log.info("orderId={}, 已成功分拆一单, detailId={}", orderId, detailId);
+            }
+        }
+        return Boolean.TRUE;
+    }
+}
+

+ 12 - 11
rankin-task/src/main/java/cn/rankin/task/service/ProductService.java

@@ -1,8 +1,9 @@
 package cn.rankin.task.service;
 
 import cn.rankin.common.utils.api.model.APIResult;
-import cn.rankin.data.api.product.vo.GoodsVo;
-import cn.rankin.data.api.product.vo.ProductVo;
+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 org.springframework.cloud.netflix.feign.FeignClient;
 import org.springframework.stereotype.Component;
@@ -13,33 +14,33 @@ import org.springframework.web.bind.annotation.RequestParam;
 
 import java.util.List;
 
-@FeignClient(name = "${service.product.name}")
+@FeignClient(name = "service.name.product", fallback = ProductService.ProductServiceHystrix.class)
 public interface ProductService {
 
-    @RequestMapping(value = "/goods/ids", method = RequestMethod.GET)
-    APIResult<List<GoodsVo>> findGoodsByIds(@RequestParam("id") List<String> goodsIdList);
+    @RequestMapping(value = "/product/package/{pkgId}", method = RequestMethod.GET)
+    APIResult<Package> getPackage(@PathVariable("pkgId") String pkgId);
 
     @RequestMapping(value = "/product/ids", method = RequestMethod.GET)
-    APIResult<List<ProductVo>> findProductByIds(@RequestParam("id") List<String> pidList);
+    APIResult<List<Product>> findProductByIds(@RequestParam("id") List<String> ids);
 
-    @RequestMapping(value = "/product/{productId}", method = RequestMethod.GET)
-    APIResult findProductById(@PathVariable("productId") String productId);
+    @RequestMapping(value = "/goods/ids", method = RequestMethod.GET)
+    APIResult<List<Goods>> findGoodsByIds(@RequestParam("id") List<String> ids);
 
     @Component
     class ProductServiceHystrix implements ProductService {
 
         @Override
-        public APIResult findGoodsByIds(List<String> goodsIdList) {
+        public APIResult getPackage(String pkgId) {
             return APIResult.error(TaskAPICode.SERVER_ERROR);
         }
 
         @Override
-        public APIResult findProductByIds(List<String> pidList) {
+        public APIResult findProductByIds(List<String> ids) {
             return APIResult.error(TaskAPICode.SERVER_ERROR);
         }
 
         @Override
-        public APIResult findProductById(String productId) {
+        public APIResult findGoodsByIds(List<String> ids) {
             return APIResult.error(TaskAPICode.SERVER_ERROR);
         }
     }

+ 0 - 39
rankin-task/src/main/java/cn/rankin/task/service/TradeService.java

@@ -1,39 +0,0 @@
-package cn.rankin.task.service;
-
-import cn.rankin.common.utils.api.model.APIResult;
-import cn.rankin.data.api.trade.entity.Order;
-import cn.rankin.task.code.TaskAPICode;
-import org.springframework.cloud.netflix.feign.FeignClient;
-import org.springframework.stereotype.Component;
-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.RequestParam;
-
-import java.util.List;
-
-@FeignClient(name = "${service.trade.name}", fallback = TradeService.TradeServiceHystrix.class)
-public interface TradeService {
-
-    @RequestMapping(value = "/order/pay/list", method = RequestMethod.GET)
-    APIResult<List<Order>> findPayList(@RequestParam("limit") Integer limit);
-
-    @RequestMapping(value = "/order/pay/{orderId}", method = RequestMethod.POST)
-    APIResult<Boolean> complete(@PathVariable("orderId") String orderId);
-
-    @Component
-    class TradeServiceHystrix implements TradeService {
-
-        @Override
-        public APIResult findPayList(Integer limit) {
-            return APIResult.error(TaskAPICode.SERVER_ERROR);
-        }
-
-        @Override
-        public APIResult complete(String orderId) {
-            return APIResult.error(TaskAPICode.SERVER_ERROR);
-        }
-
-    }
-}
-

+ 0 - 108
rankin-task/src/main/java/cn/rankin/task/task/order/OrderCompleteTask.java

@@ -1,27 +1,18 @@
 package cn.rankin.task.task.order;
 
 import cn.rankin.common.utils.api.model.APIResult;
-import cn.rankin.common.utils.enums.OrderStatusEnum;
 import cn.rankin.common.utils.enums.ProductTypeEnum;
-import cn.rankin.data.api.product.vo.GoodsVo;
-import cn.rankin.data.api.product.vo.PackageVo;
-import cn.rankin.data.api.product.vo.ProductVo;
 import cn.rankin.data.api.trade.entity.OrderGoods;
 import cn.rankin.data.api.trade.entity.OrderProductSnapshot;
 import cn.rankin.data.api.trade.entity.Order;
 import cn.rankin.data.api.user.vo.CampusVo;
 import cn.rankin.data.api.user.vo.TerminalUserVo;
-import cn.rankin.task.service.ProductService;
-import cn.rankin.task.service.TradeService;
 import cn.rankin.task.service.UserService;
 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;
 
@@ -34,73 +25,8 @@ public class OrderCompleteTask {
     public final static Integer SIZE = 100;
 
     @Autowired
-    private TradeService tradeService;
-
-    @Autowired
     private UserService userService;
 
-    @Autowired
-    private ProductService productService;
-
-    @Scheduled(fixedDelay = ONE_MINUTE)
-    public void run() {
-        // 查询订单
-        APIResult<List<Order>> orderListResult = tradeService.findPayList(SIZE);
-        if (!orderListResult.getSuccess()) {
-            log.error("get order list error: {}", orderListResult.getMessage());
-            return;
-        }
-
-        List<Order> orderList = orderListResult.getData();
-        if (CollectionUtils.isEmpty(orderList)) {
-            log.info("order list empty, return");
-            return;
-        }
-
-        //取预加载信息所需信息
-        List<String> userIdList = new ArrayList<>();
-        for (Order order : orderList) {
-            String userId = order.getUid();
-            if (!userIdList.contains(userId)) {
-                userIdList.add(userId);
-            }
-        }
-
-        // 加载用户信息
-        List<TerminalUserVo> terminalUserVoList = loadUser(userIdList);
-        if (CollectionUtils.isEmpty(terminalUserVoList)) {
-            return;
-        }
-
-        List<String> campusIdList = new ArrayList<>();
-        Map<String, TerminalUserVo> terminalUserVoMap = new HashMap<>();
-        for (TerminalUserVo terminalUserVo : terminalUserVoList) {
-            String userId = terminalUserVo.getId();
-            String campusId = terminalUserVo.getCampusId();
-            if (!campusIdList.contains(campusId)) {
-                campusIdList.add(campusId);
-            }
-            terminalUserVoMap.put(userId, terminalUserVo);
-        }
-
-        // 加载校区信息
-        Map<String, CampusVo> campusVoMap = loadCampus(campusIdList);
-        if (CollectionUtils.isEmpty(campusVoMap)) {
-            return;
-        }
-
-        // 逐单处理
-        for (Order order : orderList) {
-            String orderId = order.getId();
-            APIResult<Boolean> orderChangeResult = tradeService.complete(orderId, OrderStatusEnum.COMPLETE);
-            if (!orderChangeResult.getSuccess()) {
-                log.error("order complete status error, orderId={}", orderId);
-                continue;
-            }
-
-
-        }
-    }
 
     public List<OrderProductSnapshot> toSnaptshots(Order order, TerminalUserVo terminalUserVo, CampusVo campusVo) {
         List<OrderProductSnapshot> snapshotList = new ArrayList<>();
@@ -127,7 +53,6 @@ public class OrderCompleteTask {
                 productIdList.add(productId);
             }
             if (type.equals(ProductTypeEnum.PACKAGE)) {
-                APIResult<PackageVo> apiResult = productService.findProductById(productId);
             }
         }
         return null;
@@ -154,38 +79,5 @@ public class OrderCompleteTask {
         return apiResult.getData();
     }
 
-    public Map<String, ProductVo> loadProduct(List<String> productIdList) {
-        APIResult<List<ProductVo>> apiResult = productService.findProductByIds(productIdList);
-        if (!apiResult.getSuccess()) {
-            log.error("load product error, {}", apiResult.getMessage());
-            return null;
-        }
-
-        List<ProductVo> productVoList = apiResult.getData();
-        Map<String, ProductVo> productVoMap = new HashMap<>();
-        for (ProductVo productVo : productVoList) {
-            String pid = productVo.getPid();
-            productVoMap.put(pid, productVo);
-        }
-
-        return productVoMap;
-    }
-
-    public Map<String, GoodsVo> loadGoods(List<String> goodsIdList) {
-        APIResult<List<GoodsVo>> apiResult = productService.findGoodsByIds(goodsIdList);
-        if (!apiResult.getSuccess()) {
-            log.error("load goods error, {}", apiResult.getMessage());
-            return null;
-        }
-
-        List<GoodsVo> goodsVoList = apiResult.getData();
-        Map<String, GoodsVo> goodsVoMap = new HashMap<>();
-        for (GoodsVo goodsVo : goodsVoList) {
-            String goodsId = goodsVo.getId();
-            goodsVoMap.put(goodsId, goodsVo);
-        }
-
-        return goodsVoMap;
-    }
 }
 

+ 166 - 12
rankin-task/src/main/java/cn/rankin/task/task/order/OrderSplitTask.java

@@ -1,47 +1,201 @@
 package cn.rankin.task.task.order;
 
 import cn.rankin.common.utils.api.model.APIResult;
+import cn.rankin.common.utils.enums.BaseStatusEnum;
+import cn.rankin.common.utils.enums.ProductTypeEnum;
+import cn.rankin.data.api.product.entity.Goods;
+import cn.rankin.data.api.product.entity.Package;
+import cn.rankin.data.api.product.vo.PackageProductVo;
 import cn.rankin.data.api.trade.entity.Order;
 import cn.rankin.data.api.trade.entity.OrderDetail;
-import cn.rankin.task.service.TradeService;
+import cn.rankin.data.api.trade.entity.OrderGoods;
+import cn.rankin.task.service.OrderService;
+import cn.rankin.task.service.ProductService;
 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.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 @Slf4j
 @Component
 public class OrderSplitTask {
 
-    public final static long ONE_MINUTE = 10 * 1000;
+    public final static long ONE_MINUTE = 60 * 1000;
 
     public final static Integer SIZE = 100;
 
     @Autowired
-    private TradeService tradeService;
+    private ProductService productService;
+
+    @Autowired
+    private OrderService orderService;
 
     @Scheduled(fixedDelay = ONE_MINUTE)
     public void run() {
-        List<Order> orderList = loadOrder(SIZE);
+        // 查询订单
+        List<Order> orderList = orderService.findSplitList(SIZE);
+        if (CollectionUtils.isEmpty(orderList)) {
+            log.info("不存在需要处理的订单");
+            return;
+        }
+
+        // 逐单处理, 如果不拆直接拿到detail即可
+        for (Order order : orderList) {
+            String orderId = order.getId();
+            List<OrderDetail> orderDetailList = splitOrder(order);
+            if (orderDetailList == null) {
+                log.error("split order process is null, orderId={}", orderId);
+                continue;
+            }
+            log.info("start split order, orderId={}", orderId);
+            Boolean result = orderService.split(orderId, orderDetailList);
+            if (result) {
+                log.info("split order success, orderId={}", orderId);
+            }else {
+                log.error("split order error, orderId={]", orderId);
+            }
+
+        }
+    }
+
+    // 开始早错数据库了啊,更改状态,保存分拆的订单
+
+    // 将一个订单分拆处理成多个
+    public List<OrderDetail> splitOrder(Order order) {
+        // 将一个订单的虚拟商品拆成一个单,其他类型商品(周边)按厂商分拆到多个单
+        OrderDetail virtualOrder = null;
+        Map<String, OrderDetail> orderDetailCpIdMap = new HashMap<>();
+
+        String orderId = order.getId();
+        List<OrderGoods> goodsList = order.getGoods();
+
+        List<String> goodsIdList = new ArrayList<>();
+        goodsList.forEach(orderGoods -> goodsIdList.add(orderGoods.getGoodsId()));
+
+        //
+        Map<String, Goods> goodsMap = this.loadGoods(goodsIdList);
+        if (goodsMap == null) {
+            return null;
+        }
 
+        for (OrderGoods orderGoods : goodsList) {
+            ProductTypeEnum type = orderGoods.getType();
+            String goodsId = orderGoods.getGoodsId();
+            Goods goods = goodsMap.get(goodsId);
+            if (goods == null) {
+                log.error("商品不存在, goodsId={}, orderId={}", goodsId, orderId);
+                continue;
+            }
+
+            OrderDetail orderDetail = null;
+            if (type.equals(ProductTypeEnum.SUPPORT)) {
+                // 周边,按cpId拆分
+                String cpId = goods.getCpId();
+                orderDetail = orderDetailCpIdMap.get(cpId);
+                if (orderDetail == null) {
+                    orderDetail = initOrderDetail(order);
+                }
+            } else if (type.equals(ProductTypeEnum.COURSE)) {
+                // 课程,虚拟商品,放到virtualOrder中
+                if (virtualOrder == null) {
+                    virtualOrder = initOrderDetail(order);
+                }
+                orderDetail = virtualOrder;
+            } else {
+                // 课程包,如果包含虚拟商品,则处理到虚拟商品, 如果是周边则不处理,因为实物已经在订单产生的时候生成了单独订单
+                String productId = goods.getPid();
+                Package pkg = loadPackage(productId);
+                if (pkg == null) {
+                    log.error("load order package not exists, packageId={}, orderId={}", productId, orderId);
+                    continue;
+                }
+                List<PackageProductVo> packageProductVoList = pkg.getProducts();
+                for (PackageProductVo packageProductVo : packageProductVoList) {
+                    ProductTypeEnum packageProductType = packageProductVo.getType();
+                    if (packageProductType.equals(ProductTypeEnum.COURSE)) {
+                        if (virtualOrder == null) {
+                            virtualOrder = initOrderDetail(order);
+                        }
+                        orderDetail = virtualOrder;
+                        break;
+                    }
+                }
+            }
+
+            // 如果可以分拆产生一个订单,或者此商品可以归到一个分拆的订单中, 则处理
+            if (orderDetail != null) {
+                List<OrderGoods> orderGoodsList = orderDetail.getGoods();
+                orderGoodsList.add(orderGoods);
+            }
+        }
+
+        List<OrderDetail> orderDetailList = new ArrayList<>();
+        for (String cpId : orderDetailCpIdMap.keySet()) {
+            OrderDetail orderDetail = orderDetailCpIdMap.get(cpId);
+            if (orderDetail != null) {
+                orderDetail.setCpId(cpId);
+                List<OrderGoods> orderGoodsList = orderDetail.getGoods();
+                if (!CollectionUtils.isEmpty(orderGoodsList)) {
+                    for (OrderGoods orderGoods : orderGoodsList) {
+                        Goods goods = goodsMap.get(orderGoods.getGoodsId());
+                        orderDetail.setOriginPrice(orderDetail.getOriginPrice().add(goods.getMerchantPrice()));
+                    }
+                }
+                orderDetailList.add(orderDetail);
+            }
+        }
+
+        if (virtualOrder != null) {
+            orderDetailList.add(virtualOrder);
+        }
+
+        return orderDetailList;
     }
 
-    // 取订单
-    public List<Order> loadOrder(Integer limit) {
-        APIResult<List<Order>> apiResult = tradeService.findPayList(limit);
+    public Package loadPackage(String pkgId) {
+        APIResult<Package> apiResult = productService.getPackage(pkgId);
         if (!apiResult.getSuccess()) {
-            log.error("load order error: %s", apiResult.getMessage());
+            log.error("load package error: {}", apiResult.getMessage());
             return null;
         }
         return apiResult.getData();
     }
 
-    // 分拆
-    public List<OrderDetail> splitOrder(List<Order> orderList) {
-        return null;
+    public Map<String, Goods> loadGoods(List<String> goodsIdList) {
+        APIResult<List<Goods>> apiResult = productService.findGoodsByIds(goodsIdList);
+        if (!apiResult.getSuccess()) {
+            log.error("load goods error: {}", apiResult.getMessage());
+            return null;
+        }
+
+        Map<String, Goods> map = new HashMap<>();
+        List<Goods> goodsList = apiResult.getData();
+        for (Goods goods : goodsList) {
+            String goodsId = goods.getId();
+            map.put(goodsId, goods);
+        }
+        return map;
     }
 
-    // 保存
+    public OrderDetail initOrderDetail(Order order) {
+        OrderDetail orderDetail = new OrderDetail();
+        orderDetail.setOrderId(order.getId());
+        orderDetail.setUid(order.getUid());
+        orderDetail.setName(order.getName());
+        orderDetail.setMobile(order.getMobile());
+        orderDetail.setAddress(order.getAddress());
+        orderDetail.setStatus(BaseStatusEnum.NORMAL);
+        orderDetail.setGoods(new ArrayList<>());
+        orderDetail.setOriginPrice(BigDecimal.ZERO);
+        orderDetail.setAdjustPrice(BigDecimal.ZERO);
+        orderDetail.setFinalPrice(BigDecimal.ZERO);
+        return orderDetail;
+    }
 }

+ 0 - 8
rankin-trade-service/src/main/java/cn/rankin/tradeservice/controller/OrderController.java

@@ -2,7 +2,6 @@ package cn.rankin.tradeservice.controller;
 
 import cn.rankin.common.utils.api.model.APIResult;
 import cn.rankin.common.utils.api.page.Page;
-import cn.rankin.common.utils.enums.OrderStatusEnum;
 import cn.rankin.data.api.trade.dto.OrderSearchDTO;
 import cn.rankin.data.api.trade.dto.UserOrderDTO;
 import cn.rankin.data.api.trade.entity.Order;
@@ -10,8 +9,6 @@ import cn.rankin.tradeservice.service.OrderService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.List;
-
 @RestController
 @RequestMapping(value = "/order")
 public class OrderController {
@@ -45,9 +42,4 @@ public class OrderController {
         return orderService.cancel(orderId);
     }
 
-    // 内部task调用
-    @RequestMapping(value = "/pay/list", method = RequestMethod.GET)
-    public APIResult<List<Order>> getPayList(@RequestParam("limit") Integer limit) {
-        return orderService.findPayList(limit);
-    }
 }

+ 2 - 4
rankin-trade-service/src/main/java/cn/rankin/tradeservice/repository/OrderRepository.java

@@ -10,13 +10,11 @@ import java.util.List;
 public interface OrderRepository extends BasicJpaRepository<Order, String> {
 
     @Modifying(clearAutomatically = true)
-    @Query(value = "update Order o set o.status = 1 where o.status = 0 and o.id = ?1")
+    @Query(value = "update Order o set o.orderStatus = 1 where o.status = 0 and o.id = ?1 and o.orderStatus = 0")
     Integer pay(String orderId);
 
     @Modifying(clearAutomatically = true)
-    @Query(value = "update Order o set o.status = 2 where o.status = 0 and o.id = ?1")
+    @Query(value = "update Order o set o.orderStatus = 2 where o.status = 0 and o.id = ?1 and o.orderStatus = 0")
     Integer cancel(String orderId);
 
-    @Query(value = "select * from user_order o where o.status in (1, 5) limit ?1", nativeQuery = true)
-    List<Order> findPayList(Integer limit);
 }

+ 6 - 36
rankin-trade-service/src/main/java/cn/rankin/tradeservice/service/OrderService.java

@@ -3,6 +3,8 @@ package cn.rankin.tradeservice.service;
 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.enums.OrderSplitStatusEnum;
 import cn.rankin.common.utils.enums.OrderStatusEnum;
 import cn.rankin.common.utils.util.JpaSortUtil;
 import cn.rankin.data.api.trade.dto.OrderSearchDTO;
@@ -56,8 +58,10 @@ public class OrderService {
     @Transactional
     public APIResult<Order> create(UserOrderDTO userOrderDTO) {
         Order order = convert(userOrderDTO);
-        order.setStatus(OrderStatusEnum.UNPAID);
-        order = orderRepository.saveAndFlush(order);
+        order.setOrderStatus(OrderStatusEnum.UNPAID);
+        order.setStatus(BaseStatusEnum.NORMAL);
+        order.setSplitStatus(OrderSplitStatusEnum.NO);
+        order = orderRepository.save(order);
         String orderId = order.getId();
         List<OrderGoodsDTO> orderGoodsDTOList = userOrderDTO.getGoods();
         orderGoodsService.createRelation(orderId, orderGoodsDTOList);
@@ -77,40 +81,6 @@ public class OrderService {
         return APIResult.ok(order);
     }
 
-    public APIResult<List<Order>> findPayList(Integer limit) {
-        List<Order> orderList = orderRepository.findPayList(limit);
-        if (CollectionUtils.isEmpty(orderList)) {
-            return APIResult.ok(orderList);
-        }
-
-        List<String> orderIdList = new ArrayList<>();
-        for (Order order : orderList) {
-            orderIdList.add(order.getId());
-        }
-
-        List<OrderGoods> orderGoodsList = orderGoodsService.findByOrderIds(orderIdList);
-        Map<String, List<OrderGoods>> orderGoodsMap = new HashMap<>();
-        for (OrderGoods orderGoods : orderGoodsList) {
-            String orderId = orderGoods.getOrderId();
-            if (!orderGoodsMap.containsKey(orderId)) {
-                List<OrderGoods> tmpList = new ArrayList<>();
-                tmpList.add(orderGoods);
-                orderGoodsMap.put(orderId, tmpList);
-            }else {
-                List<OrderGoods> tmpList = orderGoodsMap.get(orderId);
-                tmpList.add(orderGoods);
-            }
-        }
-
-        for (Order order : orderList) {
-            String orderId = order.getId();
-            List<OrderGoods> tmpList = orderGoodsMap.get(orderId);
-            order.setGoods(tmpList);
-        }
-
-        return APIResult.ok(orderList);
-    }
-
     public APIResult<Page<Order>> search(OrderSearchDTO searchDTO) {
         Specification<Order> specification = new Specification<Order>() {
             @Override

+ 0 - 1
rankin-trade-service/src/test/java/cn/rankin/tradeservice/repository/OrderRepositoryTest.java

@@ -21,7 +21,6 @@ public class OrderRepositoryTest {
 
     @Test
     public void findPayList() throws Exception {
-        List<Order> orderList = orderRepository.findPayList(10);
     }
 
 }