Forráskód Böngészése

商品模块功能

Bob 5 hónapja
szülő
commit
53f0cb96b7
28 módosított fájl, 710 hozzáadás és 10 törlés
  1. 9 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/feign/OrderApi.java
  2. 5 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/feign/hystrix/OrderHystrix.java
  3. 1 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/OrdersVO.java
  4. 59 0
      pdf-office-api/pdf-office-api-product/src/main/java/cn/kdan/cloud/pdf/office/api/product/vo/ListingProductVO.java
  5. 44 0
      pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/enums/product/ProductEducationPriceEnum.java
  6. 3 3
      pdf-office-generate/src/main/resources/application.yml
  7. 5 0
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/controller/OrderController.java
  8. 2 0
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/entity/Order.java
  9. 6 3
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/OrderServiceImpl.java
  10. 1 0
      pdf-office-payment/src/main/resources/mapper/OrderMapper.xml
  11. 6 0
      pdf-office-product/pom.xml
  12. 41 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/controller/ProductController.java
  13. 32 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/entity/EduEmails.java
  14. 53 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/entity/Prize.java
  15. 31 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/entity/Product.java
  16. 8 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/error/ErrorMessage.java
  17. 12 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/mapper/EduEmailsMapper.java
  18. 11 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/mapper/PrizeMapper.java
  19. 3 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/mapper/ProductMapper.java
  20. 20 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/EduEmailsService.java
  21. 19 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/PrizeService.java
  22. 18 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/ProductService.java
  23. 27 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/impl/EduEmailsServiceImpl.java
  24. 23 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/impl/PrizeServiceImpl.java
  25. 213 4
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/impl/ProductServiceImpl.java
  26. 19 0
      pdf-office-product/src/main/resources/mapper/EduEmailsMapper.xml
  27. 18 0
      pdf-office-product/src/main/resources/mapper/PrizeMapper.xml
  28. 21 0
      pdf-office-product/src/main/resources/mapper/ProductMapper.xml

+ 9 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/feign/OrderApi.java

@@ -122,4 +122,13 @@ public interface OrderApi {
     @PostMapping("/cancelSubscription")
     ResultMap<Void> cancelSubscription(@Validated @RequestBody CancelSubscriptionDTO cancelSubscription);
 
+    /**
+     * 通过用户id获取订单信息
+     *
+     * @param userId 用户id
+     * @return Orders
+     */
+    @GetMapping("/getOrderByUserId")
+    ResultMap<List<OrdersVO>> getOrderByUserId(@Validated @NotNull(message = "userId不能为空")
+                                                @RequestParam("userId") String userId);
 }

+ 5 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/feign/hystrix/OrderHystrix.java

@@ -72,4 +72,9 @@ public class OrderHystrix implements OrderApi {
     public ResultMap<Void> cancelSubscription(CancelSubscriptionDTO cancelSubscription) {
         return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
     }
+
+    @Override
+    public ResultMap<List<OrdersVO>> getOrderByUserId(String userId) {
+        return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
+    }
 }

+ 1 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/OrdersVO.java

@@ -97,4 +97,5 @@ public class OrdersVO implements Serializable {
 
     private String email;
 
+    private Integer isEducation;
 }

+ 59 - 0
pdf-office-api/pdf-office-api-product/src/main/java/cn/kdan/cloud/pdf/office/api/product/vo/ListingProductVO.java

@@ -0,0 +1,59 @@
+package cn.kdan.cloud.pdf.office.api.product.vo;
+
+import lombok.Data;
+import lombok.ToString;
+
+import java.math.BigDecimal;
+
+/**
+ * @author ComPDFKit-Bob 2024-10-15
+ */
+@Data
+@ToString
+public class ListingProductVO {
+
+    /**
+     * id
+     */
+    private String id;
+    /**
+     * 产品/计划名称
+     */
+    private String productName;
+    /**
+     * 价格
+     */
+    private BigDecimal price;
+    /**
+     *
+     */
+    private Integer maxDeviceNum;
+    /**
+     * 教育优惠价格
+     */
+    private BigDecimal displayPrice;
+    /**
+     * 买断升级订阅价格
+     */
+    private BigDecimal upgradePrice;
+    /**
+     * 3高级2标准1免费
+     */
+    private String levels;
+    /**
+     * 产品支持平台
+     */
+    private String platforms;
+    /**
+     * 所属业务线id (1pdf产品线2compdfkit产品线)
+     */
+    private Integer productLineId;
+    /**
+     * 付费模式(1自动续订 2单次付费)
+     */
+    private Integer paymentModel;
+    /**
+     * 订阅周期:1、月(30天);2、季(90天);3、半年(183天);4、年(365天)
+     */
+    private Integer cycle;
+}

+ 44 - 0
pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/enums/product/ProductEducationPriceEnum.java

@@ -0,0 +1,44 @@
+package cn.kdan.cloud.pdf.office.common.enums.product;
+
+import java.math.BigDecimal;
+
+public enum ProductEducationPriceEnum {
+
+    VIP("全平台标准版年订阅", new BigDecimal("79.99"), new BigDecimal("39.99")),
+    SVIP("全平台高级版年订阅", new BigDecimal("99.99"), new BigDecimal("49.99")),
+    PERMANENT("MAC&Windows双平台高级版永久", new BigDecimal("119.99"), new BigDecimal("59.99")),
+    ;
+
+    private final String product;
+    private final BigDecimal price;
+    // 教育版价格
+    private final BigDecimal displayPrice;
+
+    ProductEducationPriceEnum(String product, BigDecimal price, BigDecimal displayPrice) {
+        this.product = product;
+        this.price = price;
+        this.displayPrice = displayPrice;
+    }
+
+    public String getProduct() {
+        return product;
+    }
+
+    public BigDecimal getPrice() {
+        return price;
+    }
+
+    public BigDecimal getDisplayPrice() {
+        return displayPrice;
+    }
+
+    //    getbyprice
+    public static ProductEducationPriceEnum getByPrice(BigDecimal price) {
+        for (ProductEducationPriceEnum productEducationPriceEnum : ProductEducationPriceEnum.values()) {
+            if (productEducationPriceEnum.getPrice().compareTo(price) == 0) {
+                return productEducationPriceEnum;
+            }
+        }
+        return null;
+    }
+}

+ 3 - 3
pdf-office-generate/src/main/resources/application.yml

@@ -8,9 +8,9 @@ spring:
     static-locations: classpath:/views/
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://${DB_URL:124.223.7.184:33056/information_schema}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
-    username: ${DB_USERNAME:root}
-    password: ${DB_PASSWORD:root123}
+    url: jdbc:mysql://${DB_URL:101.132.103.13:33056/information_schema}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
+    username: ${DB_USERNAME:deployer}
+    password: ${DB_PASSWORD:deployer@123!}
     hikari:
       # 最小空闲连接,默认值10
       minimum-idle: 10

+ 5 - 0
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/controller/OrderController.java

@@ -167,4 +167,9 @@ public class OrderController {
         return ResultMap.success();
     }
 
+    @GetMapping("/getOrderByUserId")
+    ResultMap<List<OrdersVO>> getOrderByUserId(@Validated @NotNull(message = "userId不能为空")
+                                               @RequestParam("userId") String userId) {
+        return ResultMap.success(ordersService.getOrderByUserId(userId, null));
+    }
 }

+ 2 - 0
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/entity/Order.java

@@ -98,4 +98,6 @@ public class Order extends BaseEntity{
     private Date payDate;
 
     private String email;
+
+    private Integer isEducation;
 }

+ 6 - 3
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/OrderServiceImpl.java

@@ -351,9 +351,12 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 
     @Override
     public List<OrdersVO> getOrderByUserId(String userId,String appId) {
-        return this.baseMapper.selectList(new LambdaQueryWrapper<Order>()
-                .eq(Order::getUserId, userId).eq(Order::getAppId, appId)
-                .orderByDesc(Order::getCreatedAt))
+        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
+        orderLambdaQueryWrapper.eq(Order::getUserId, userId).orderByDesc(Order::getCreatedAt);
+        if (StringUtils.isNotEmpty(appId)) {
+            orderLambdaQueryWrapper.eq(Order::getAppId, appId);
+        }
+        return this.baseMapper.selectList(orderLambdaQueryWrapper)
                 .stream().map(order -> {
                     OrdersVO ordersVO = new OrdersVO();
                     BeanUtils.copyProperties(order, ordersVO);

+ 1 - 0
pdf-office-payment/src/main/resources/mapper/OrderMapper.xml

@@ -23,6 +23,7 @@
         <result property="isVpp" column="is_vpp" />
         <result property="type" column="type" />
         <result property="detailType" column="detail_type" />
+        <result property="isEducation" column="is_education" />
     </resultMap>
 
     <select id="selectOrdersByTradeNo" resultType="cn.kdan.cloud.pdf.office.api.payment.vo.OrdersVO">

+ 6 - 0
pdf-office-product/pom.xml

@@ -107,6 +107,12 @@
                 </exclusion>
             </exclusions>
         </dependency>
+        <dependency>
+            <groupId>cn.kdan.pdf.office</groupId>
+            <artifactId>pdf-office-api-payment</artifactId>
+            <version>0.0.1</version>
+            <scope>compile</scope>
+        </dependency>
 
     </dependencies>
 

+ 41 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/controller/ProductController.java

@@ -1,6 +1,7 @@
 package cn.kdan.cloud.pdf.office.product.controller;
 
 import cn.kdan.cloud.pdf.office.api.product.dto.ProductListDTO;
+import cn.kdan.cloud.pdf.office.api.product.vo.ListingProductVO;
 import cn.kdan.cloud.pdf.office.api.product.vo.ProductPriceVo;
 import cn.kdan.cloud.pdf.office.api.product.vo.ProductVO;
 import cn.kdan.cloud.pdf.office.common.exception.BackendRuntimeException;
@@ -16,7 +17,9 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author ComPDFKit-WPH 2023/2/1
@@ -94,4 +97,42 @@ public class ProductController {
         return ResultMap.success(productService.getProductByThirdPayId(thirdPayId));
     }
 
+    /**
+     * 获取上架产品,返回前端购买
+     * @param isEducation
+     * @param platformId 1 官网,2 dmg,3 Mac store免费版,4e xe,5 Mac store付费版,6i OS免费版,7 iOS付费版,8 Android
+     */
+    @GetMapping("/getListingProducts")
+    public ResultMap<List<ListingProductVO>> getListingProducts(@Validated @NotNull(message = "是否教育优惠不能为空") @RequestParam("isEducation") Integer isEducation,
+                                                                @Validated @NotNull(message = "平台id不能为空") @RequestParam("platformId") String platformId){
+        return ResultMap.success(productService.getListingProducts(isEducation, platformId));
+    }
+
+    /**
+     * 获取购买商品价格,验证用户教育购买权限
+     */
+    @GetMapping("/getProductPriceForBuy")
+    public ResultMap<ListingProductVO> getProductPriceForBuy(@Validated @NotNull(message = "产品id不能为空") @RequestParam("productId") String productId,
+                                                           @Validated @NotNull(message = "用户id不能为空") @RequestParam("userId") String userId,
+                                                           @Validated @NotNull(message = "是否教育优惠不能为空") @RequestParam("isEducation") Integer isEducation) {
+        return ResultMap.success(productService.getProductPriceForBuy(productId,userId, isEducation));
+    }
+
+    /**
+     * 获取批量购买价格
+     */
+    @GetMapping("/getBatchProductPrice")
+    public ResultMap<List<Map<Integer, BigDecimal>>> getBatchProductPrice() {
+        return ResultMap.success(productService.getBatchProductPrice());
+    }
+
+    /**
+     * 验证优惠券、奖品是否可用,返回优惠后价格
+     */
+    @GetMapping("/checkCoupon")
+    public ResultMap<ListingProductVO> checkCoupon(@Validated @NotNull(message = "产品id不能为空") @RequestParam("productId") String productId,
+                                                 @NotNull(message = "用户id不能为空") @RequestParam("userId") String userId,
+                                                 @NotNull(message = "券码不能为空") @RequestParam("code") String code) {
+        return ResultMap.success(productService.checkCoupon(productId,userId, code));
+    }
 }

+ 32 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/entity/EduEmails.java

@@ -0,0 +1,32 @@
+package cn.kdan.cloud.pdf.office.product.entity;
+
+import cn.kdan.cloud.pdf.office.common.base.BaseEntity;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author ComPDFKit-Bob 2024-10-16
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("edu_emails")
+public class EduEmails extends BaseEntity{
+
+    /**
+     * 域名或邮箱
+     */
+    private String email;
+    /**
+     * 0:域名模式, 1:单个邮箱
+     */
+    private Integer emailType;
+    /**
+     * 
+     */
+    @TableId(type = IdType.ASSIGN_UUID)
+    private Integer id;
+
+}

+ 53 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/entity/Prize.java

@@ -0,0 +1,53 @@
+package cn.kdan.cloud.pdf.office.product.entity;
+
+import cn.kdan.cloud.pdf.office.common.base.BaseEntity;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+
+/**
+ * @author ComPDFKit-WPH 2024-10-16
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("prize")
+public class Prize extends BaseEntity{
+
+    /**
+     * 优惠金额/兑换详情
+     */
+    private String amount;
+    /**
+     * 券码
+     */
+    private String code;
+    /**
+     * 有效结束日期
+     */
+    private Date endDate;
+    /**
+     *
+     */
+    @TableId(type = IdType.ASSIGN_UUID)
+    private String id;
+    /**
+     * 可用商品
+     */
+    private String productId;
+    /**
+     * 有效开始日期
+     */
+    private Date startDate;
+    /**
+     * 1优惠券2兑换券
+     */
+    private Integer type;
+    /**
+     * 用户
+     */
+    private String userId;
+
+}

+ 31 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/entity/Product.java

@@ -94,4 +94,35 @@ public class Product extends BaseEntity{
      */
     private Integer type;
 
+    /**
+     * 所属业务线id (1pdf产品线2compdfkit产品线)
+     */
+    private Integer productLineId;
+
+    /**
+     * 付费模式(1自动续订 2单次付费)
+     */
+    private Integer paymentModel;
+
+    /**
+     * 订阅周期:1、月(30天);2、季(90天);3、半年(183天);4、年(365天)
+     */
+    private Integer cycle;
+
+    /**
+     * 点数
+     */
+    private String points;
+
+    /**
+     * 部署方式(1私有化 2API 3SDK)
+     */
+    private Integer deployment;
+
+    /**
+     *  0不可用/待上架 1可用/上架中 2不可用/已下架
+     */
+    private Integer validFlag;
+
+
 }

+ 8 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/error/ErrorMessage.java

@@ -9,4 +9,12 @@ public interface ErrorMessage {
 
     String NO_CURRENT_ACTIVITY = "没有当前活动类型信息";
     String USER_IS_NOT_NEW_USER = "用户不是新用户";
+    String USER_IS_NOT_EDUCATION_USER = "用户不是教育用户";
+    String USER_HAS_EDUCATION = "用户近一年有教育购买订单";
+    String USER_CANNOT_BUY_PREMIUM  = "用户已有标准版订阅,无法购买高级版";
+    String USER_CANNOT_BUY_VIP  = "用户已有高级版订阅,无法购买标准版";
+    String USER_CANNOT_UPGRADE_VIP  = "买断用户无法升级为标准版";
+    String COUPON_NOT_EXISTS = "优惠券不存在";
+    String COUPON_TYPE_ERROR = "优惠券类型错误";
+    String COUPON_PRODUCT_ERROR = "优惠券产品错误";
 }

+ 12 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/mapper/EduEmailsMapper.java

@@ -0,0 +1,12 @@
+package cn.kdan.cloud.pdf.office.product.mapper;
+
+import cn.kdan.cloud.pdf.office.product.entity.EduEmails;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * @author ComPDFKit-WPH 2024-10-16
+ */
+public interface EduEmailsMapper extends BaseMapper<EduEmails> {
+
+    int checkEmail(String email);
+}

+ 11 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/mapper/PrizeMapper.java

@@ -0,0 +1,11 @@
+package cn.kdan.cloud.pdf.office.product.mapper;
+
+import cn.kdan.cloud.pdf.office.product.entity.Prize;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * @author ComPDFKit-WPH 2024-10-16
+ */
+public interface PrizeMapper extends BaseMapper<Prize> {
+
+}

+ 3 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/mapper/ProductMapper.java

@@ -1,5 +1,6 @@
 package cn.kdan.cloud.pdf.office.product.mapper;
 
+import cn.kdan.cloud.pdf.office.api.product.vo.ListingProductVO;
 import cn.kdan.cloud.pdf.office.api.product.vo.ProductVO;
 import cn.kdan.cloud.pdf.office.product.entity.Product;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -15,4 +16,6 @@ public interface ProductMapper extends BaseMapper<Product> {
     List<ProductVO> selectNewUserProductByAppId(@Param("appId") String appId);
 
     ProductVO getProductByThirdPayId(@Param("thirdPayId") String thirdPayId);
+
+    List<ListingProductVO> getListingProducts(String platformId, List<String> productIds);
 }

+ 20 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/EduEmailsService.java

@@ -0,0 +1,20 @@
+package cn.kdan.cloud.pdf.office.product.service;
+
+import cn.kdan.cloud.pdf.office.product.entity.EduEmails;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ * @author ComPDFKit-WPH 2024-10-16
+ */
+public interface EduEmailsService extends IService<EduEmails> {
+
+    /**
+     * 列表查询
+     * @param query 查询参数
+     * @return 列表数据
+     */
+    IPage<EduEmails> page(EduEmails query);
+
+    Integer checkEmail(String email);
+}

+ 19 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/PrizeService.java

@@ -0,0 +1,19 @@
+package cn.kdan.cloud.pdf.office.product.service;
+
+import cn.kdan.cloud.pdf.office.product.entity.Prize;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ * @author ComPDFKit-WPH 2024-10-16
+ */
+public interface PrizeService extends IService<Prize> {
+
+    /**
+     * 列表查询
+     * @param query 查询参数
+     * @return 列表数据
+     */
+    IPage<Prize> page(Prize query);
+
+}

+ 18 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/ProductService.java

@@ -1,13 +1,19 @@
 package cn.kdan.cloud.pdf.office.product.service;
 
 import cn.kdan.cloud.pdf.office.api.product.dto.ProductListDTO;
+import cn.kdan.cloud.pdf.office.api.product.vo.ListingProductVO;
 import cn.kdan.cloud.pdf.office.api.product.vo.ProductPriceVo;
 import cn.kdan.cloud.pdf.office.api.product.vo.ProductVO;
 import cn.kdan.cloud.pdf.office.product.entity.Product;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestParam;
 
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author ComPDFKit-WPH 2023-01-28
@@ -58,4 +64,16 @@ public interface ProductService extends IService<Product> {
     ProductVO getProductForPay(String productId, Integer payment, Integer isDiscount);
 
     ProductVO getProductByThirdPayId(String thirdPayId);
+
+    List<ListingProductVO> getListingProducts(Integer isEducation, String platformId);
+
+    ListingProductVO getProductPriceForBuy(String productId, String userId, Integer isEducation);
+
+    /**
+     * 批量获取产品价格
+     * @return
+     */
+    List<Map<Integer, BigDecimal>> getBatchProductPrice();
+
+    ListingProductVO checkCoupon(String productId, String userId, String code);
 }

+ 27 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/impl/EduEmailsServiceImpl.java

@@ -0,0 +1,27 @@
+package cn.kdan.cloud.pdf.office.product.service.impl;
+
+import cn.kdan.cloud.pdf.office.product.entity.EduEmails;
+import cn.kdan.cloud.pdf.office.product.mapper.EduEmailsMapper;
+import cn.kdan.cloud.pdf.office.product.service.EduEmailsService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author ComPDFKit-WPH 2024-10-16
+ */
+@Service
+public class EduEmailsServiceImpl extends ServiceImpl<EduEmailsMapper, EduEmails> implements EduEmailsService {
+
+    @Override
+    public IPage<EduEmails> page(EduEmails query) {
+        return this.page(new Page<>(query.getPage(), query.getSize()), Wrappers.query(query));
+    }
+
+    @Override
+    public Integer checkEmail(String email) {
+        return this.baseMapper.checkEmail(email);
+    }
+}

+ 23 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/impl/PrizeServiceImpl.java

@@ -0,0 +1,23 @@
+package cn.kdan.cloud.pdf.office.product.service.impl;
+
+import cn.kdan.cloud.pdf.office.product.entity.Prize;
+import cn.kdan.cloud.pdf.office.product.mapper.PrizeMapper;
+import cn.kdan.cloud.pdf.office.product.service.PrizeService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author ComPDFKit-WPH 2024-10-16
+ */
+@Service
+public class PrizeServiceImpl extends ServiceImpl<PrizeMapper, Prize> implements PrizeService {
+
+    @Override
+    public IPage<Prize> page(Prize query) {
+        return this.page(new Page<>(query.getPage(), query.getSize()), Wrappers.query(query));
+    }
+
+}

+ 213 - 4
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/impl/ProductServiceImpl.java

@@ -2,7 +2,12 @@ package cn.kdan.cloud.pdf.office.product.service.impl;
 
 import cn.kdan.cloud.pdf.office.api.account.feign.UserApi;
 import cn.kdan.cloud.pdf.office.api.account.utils.SubscriptionUtil;
+import cn.kdan.cloud.pdf.office.api.payment.feign.OrderApi;
+import cn.kdan.cloud.pdf.office.api.payment.vo.OrdersVO;
+import cn.kdan.cloud.pdf.office.api.product.vo.ListingProductVO;
 import cn.kdan.cloud.pdf.office.common.enums.ExceptionEnum;
+import cn.kdan.cloud.pdf.office.common.enums.product.ProductEducationPriceEnum;
+import cn.kdan.cloud.pdf.office.common.pojo.ResultMap;
 import cn.kdan.cloud.pdf.office.common.vo.UserSubscriptionInfoVO;
 import cn.kdan.cloud.pdf.office.api.product.dto.ProductListDTO;
 import cn.kdan.cloud.pdf.office.api.product.vo.ActivityInfoVO;
@@ -10,15 +15,16 @@ import cn.kdan.cloud.pdf.office.api.product.vo.ProductPriceVo;
 import cn.kdan.cloud.pdf.office.api.product.vo.ProductVO;
 import cn.kdan.cloud.pdf.office.common.exception.BackendRuntimeException;
 import cn.kdan.cloud.pdf.office.common.utils.JsonUtils;
+import cn.kdan.cloud.pdf.office.common.vo.UserVO;
+import cn.kdan.cloud.pdf.office.product.entity.Prize;
 import cn.kdan.cloud.pdf.office.product.entity.Product;
 import cn.kdan.cloud.pdf.office.product.entity.RProductPay;
 import cn.kdan.cloud.pdf.office.product.error.ErrorMessage;
 import cn.kdan.cloud.pdf.office.product.mapper.ProductMapper;
-import cn.kdan.cloud.pdf.office.product.service.ActivityInformationService;
-import cn.kdan.cloud.pdf.office.product.service.ProductService;
-import cn.kdan.cloud.pdf.office.product.service.RProductPayService;
+import cn.kdan.cloud.pdf.office.product.service.*;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -27,7 +33,10 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
-import java.util.List;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @author ComPDFKit-WPH 2023-01-28
@@ -41,9 +50,14 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
 
     private final UserApi userAPi;
 
+    private final OrderApi orderApi;
 
     private final RProductPayService rProductPayService;
 
+    private final EduEmailsService eduEmailsService;
+
+    private final PrizeService prizeService;
+
     @Override
     public IPage<ProductVO> page(ProductListDTO query) {
         Page<Product> productPage = this.page(new Page<>(query.getPage(), query.getSize()), new LambdaQueryWrapper<Product>()
@@ -133,4 +147,199 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
         return productVO;
     }
 
+    @Override
+    public List<ListingProductVO> getListingProducts(Integer isEducation, String platformId) {
+        // 获取上架中的产品
+        List<ListingProductVO> listingProducts = this.baseMapper.getListingProducts(platformId, null);
+        if (null != isEducation && isEducation == 1) {
+            // 返回原价和教育优惠价格
+            listingProducts.forEach(listingProductVO -> {
+                ProductEducationPriceEnum byPrice = ProductEducationPriceEnum.getByPrice(listingProductVO.getPrice());
+                if (null != byPrice) {
+                    listingProductVO.setDisplayPrice(byPrice.getDisplayPrice());
+                } else {
+                    log.error("产品价格设置错误,id:{}", listingProductVO.getId());
+                }
+            });
+        }
+        return listingProducts;
+    }
+
+    @Override
+    public ListingProductVO getProductPriceForBuy(String productId, String userId, Integer isEducation) {
+        // 查询购买的商品信息
+        List<ListingProductVO> productVOs = this.baseMapper.getListingProducts(null, Collections.singletonList(productId));
+        ListingProductVO listingProductVO = productVOs.get(0);
+        // 查询用户+所有订单
+        UserVO userVO = userAPi.getById(userId).getResult();
+        List<OrdersVO> orders = orderApi.getOrderByUserId(userId).getResult();
+        if (null != isEducation && isEducation == 1) {
+            // 判断用户教育优惠资格
+            // 根据用户邮箱
+            Integer checkEmail = eduEmailsService.checkEmail(userVO.getEmail());
+            if (checkEmail == 0) {
+                throw new BackendRuntimeException(ErrorMessage.USER_IS_NOT_EDUCATION_USER);
+            }
+            // 查询用户所有订单。判断近一年有没有教育优惠订单
+            if (orders.stream().anyMatch(ordersVO -> ordersVO.getIsEducation() == 1 && ordersVO.getCreatedAt().isAfter(LocalDateTime.now().minusYears(1)))) {
+                throw new BackendRuntimeException(ErrorMessage.USER_HAS_EDUCATION);
+            }
+            // 校验教育用户资格通过
+            listingProductVO.setDisplayPrice(ProductEducationPriceEnum.getByPrice(listingProductVO.getPrice()).getDisplayPrice());
+            // 没有购买过的用户直接返回
+            if (CollectionUtils.isEmpty(orders)) {
+                return listingProductVO;
+            }
+            // 获取已购买的订单商品及会员权益
+            List<String> orderProductIds = orders.stream().map(OrdersVO::getProductId).collect(Collectors.toList());
+            List<ListingProductVO> orderProducts = this.baseMapper.getListingProducts(null, orderProductIds);
+            if (CollectionUtils.isEmpty(orderProducts)) {
+                return listingProductVO;
+            }
+            // 筛选订单购买的产品中有没有vip订阅类型
+            boolean hasVip = false;
+            boolean hasSVip = false;
+            boolean hasPermanent = false;
+            for (ListingProductVO orderProduct : orderProducts) {
+                if (orderProduct.getPaymentModel() == 1) {
+                    hasPermanent = true;
+                } else {
+                    if (orderProduct.getLevels().contains("2")) {
+                        hasVip = true;
+                    } else if (orderProduct.getLevels().contains("3")) {
+                        hasSVip = true;
+                    }
+                }
+            }
+            // 购买svip,判断是否买断升级订阅(买且只买了永久版,购买高级版订阅)
+            if (listingProductVO.getLevels().contains("3")) {
+                // vip无法购买svip
+                if (hasVip) {
+                    throw new BackendRuntimeException(ErrorMessage.USER_CANNOT_BUY_PREMIUM);
+                }
+                // svip原价提前续费
+                if (hasSVip) {
+                    return listingProductVO;
+                }
+                // 买断升级订阅价格
+                if (hasPermanent) {
+                    listingProductVO.setUpgradePrice(new BigDecimal("9.99"));
+                    return listingProductVO;
+                }
+            }
+            // 购买vip
+            if (listingProductVO.getLevels().contains("2")) {
+                // vip提前续费
+                if (hasVip) {
+                    return listingProductVO;
+                }
+                // svip无法购买vip
+                if (hasSVip) {
+                    throw new BackendRuntimeException(ErrorMessage.USER_CANNOT_BUY_VIP);
+                }
+                // 买断无法购买vip
+                if (hasPermanent) {
+                    throw new BackendRuntimeException(ErrorMessage.USER_CANNOT_UPGRADE_VIP);
+                }
+            }
+            return listingProductVO;
+        } else {
+            // 没有购买过的用户直接返回
+            if (CollectionUtils.isEmpty(orders)) {
+                return listingProductVO;
+            }
+            // 获取已购买的订单商品及会员权益
+            List<String> orderProductIds = orders.stream().map(OrdersVO::getProductId).collect(Collectors.toList());
+            List<ListingProductVO> orderProducts = this.baseMapper.getListingProducts(null, orderProductIds);
+            if (CollectionUtils.isEmpty(orderProducts)) {
+                return listingProductVO;
+            }
+            // 筛选订单购买的产品中有没有vip订阅类型
+            boolean hasVip = false;
+            boolean hasSVip = false;
+            boolean hasPermanent = false;
+            for (ListingProductVO orderProduct : orderProducts) {
+                if (orderProduct.getPaymentModel() == 1) {
+                    hasPermanent = true;
+                } else {
+                    if (orderProduct.getLevels().contains("2")) {
+                        hasVip = true;
+                    } else if (orderProduct.getLevels().contains("3")) {
+                        hasSVip = true;
+                    }
+                }
+            }
+            // 购买svip,判断是否买断升级订阅(买且只买了永久版,购买高级版订阅)
+            if (listingProductVO.getLevels().contains("3")) {
+                // vip无法购买svip
+                if (hasVip) {
+                    throw new BackendRuntimeException(ErrorMessage.USER_CANNOT_BUY_PREMIUM);
+                }
+                // svip原价提前续费
+                if (hasSVip) {
+                    return listingProductVO;
+                }
+                // 买断升级订阅价格
+                if (hasPermanent) {
+                    listingProductVO.setUpgradePrice(new BigDecimal("19.99"));
+                    return listingProductVO;
+                }
+            }
+            // 购买vip
+            if (listingProductVO.getLevels().contains("2")) {
+                // vip原价提前续费
+                if (hasVip) {
+                    return listingProductVO;
+                }
+                // svip无法购买vip
+                if (hasSVip) {
+                    throw new BackendRuntimeException(ErrorMessage.USER_CANNOT_BUY_VIP);
+                }
+                // 买断无法购买vip
+                if (hasPermanent) {
+                    throw new BackendRuntimeException(ErrorMessage.USER_CANNOT_UPGRADE_VIP);
+                }
+            }
+            return listingProductVO;
+        }
+    }
+
+    /**
+     * 批量获取产品价格
+     * @return
+     */
+    @Override
+    public List<Map<Integer, BigDecimal>> getBatchProductPrice() {
+        // 2-5	10% OFF	$107.99/个
+        //6-20	20% OFF	$95.99/个
+        //21-50	30% OFF	$83.99/个
+        //50+	联系我们获取最新折扣
+        HashMap<Integer, BigDecimal> hashMap = new HashMap<>();
+        hashMap.put(1, new BigDecimal("119.99"));
+        hashMap.put(5, new BigDecimal("107.99"));
+        hashMap.put(20, new BigDecimal("95.99"));
+        hashMap.put(50, new BigDecimal("83.99"));
+        return Collections.singletonList(hashMap);
+    }
+
+    @Override
+    public ListingProductVO checkCoupon(String productId, String userId, String code) {
+        Prize prize = prizeService.getOne(new LambdaQueryWrapper<Prize>().eq(Prize::getCode, code).eq(Prize::getUserId, userId));
+        if (prize == null) {
+            log.error("优惠券不存在:{}", code);
+            throw new BackendRuntimeException(ErrorMessage.COUPON_NOT_EXISTS);
+        }
+        if (prize.getType() != 1) {
+            log.error("优惠券类型错误:{}", code);
+            throw new BackendRuntimeException(ErrorMessage.COUPON_TYPE_ERROR);
+        }
+        if (!prize.getProductId().contains(productId)) {
+            log.error("优惠券关联产品错误,productId:{}", productId);
+            throw new BackendRuntimeException(ErrorMessage.COUPON_PRODUCT_ERROR);
+        }
+        List<ListingProductVO> productVOs = this.baseMapper.getListingProducts(null, Collections.singletonList(productId));
+        ListingProductVO listingProductVO = productVOs.get(0);
+        listingProductVO.setDisplayPrice(listingProductVO.getDisplayPrice().subtract(new BigDecimal(prize.getAmount())));
+        return listingProductVO;
+    }
 }

+ 19 - 0
pdf-office-product/src/main/resources/mapper/EduEmailsMapper.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="cn.kdan.cloud.pdf.office.product.mapper.EduEmailsMapper">
+
+    <!-- 可根据自己的需求,是否要使用 -->
+    <resultMap id="EduEmailsResultMap" type="cn.kdan.cloud.pdf.office.product.entity.EduEmails">
+        <result property="email" column="email" />
+        <result property="emailType" column="email_type" />
+        <result property="id" column="id" />
+    </resultMap>
+
+    <select id="checkEmail" resultType="java.lang.Integer">
+        select count(1)
+        from edu_emails
+        where (email_type = 1 and email = #{email}) or (email_type = 0 and #{email} like concat('%',email,'%'))
+    </select>
+
+</mapper>

+ 18 - 0
pdf-office-product/src/main/resources/mapper/PrizeMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="cn.kdan.cloud.pdf.office.product.mapper.PrizeMapper">
+
+    <!-- 可根据自己的需求,是否要使用 -->
+    <resultMap id="PrizeResultMap" type="cn.kdan.cloud.pdf.office.product.entity.Prize">
+        <result property="amount" column="amount" />
+        <result property="code" column="code" />
+        <result property="endDate" column="end_date" />
+        <result property="id" column="id" />
+        <result property="productId" column="product_id" />
+        <result property="startDate" column="start_date" />
+        <result property="type" column="type" />
+        <result property="userId" column="user_id" />
+    </resultMap>
+
+</mapper>

+ 21 - 0
pdf-office-product/src/main/resources/mapper/ProductMapper.xml

@@ -39,4 +39,25 @@
         where r.third_pay_id = #{thirdPayId}
     </select>
 
+    <select id="getListingProducts" resultType="cn.kdan.cloud.pdf.office.api.product.vo.ListingProductVO">
+        select p.id, p.product_name, p.price, p.max_device_num, p.product_line_id, p.payment_model, p.cycle,
+               GROUP_CONCAT(DISTINCT(r.`level`)) AS levels,
+               GROUP_CONCAT(p2.name) AS platforms
+        from product p
+        left join r_product_right rpr ON p.id = rpr.product_id
+        left join `right` r on rpr.right_id = r.id
+        left join r_product_platform rpp ON p.id = rpp.product_id
+        left join platform p2 on rpp.platform_id = p2.id
+        where p.valid_flag = 1
+        <if test="platformId != null">
+            and p.id in (select product_id from r_product_supply_platform where platform_id = #{platformId})
+        </if>
+        <if test="productIds != null and productIds.length > 0">
+            and p.id in
+            <foreach item="item" index="index" collection="productIds" open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+        group by p.id
+    </select>
 </mapper>