Преглед изворни кода

Merge branch 'goods_plus_pay'

zoujiajian пре 3 година
родитељ
комит
965cfd08e8
23 измењених фајлова са 454 додато и 12 уклоњено
  1. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsDiscountPlusPurchaseRelationMapper.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDiscountPlusPurchaseSkuRelationMapper.java
  3. 29 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDiscountPlusPurchaseRelation.java
  4. 22 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonSku.java
  5. 23 0
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDiscountPlusPurchaseSkuRelation.java
  6. 9 1
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java
  7. 2 1
      netflix-dao/src/main/java/com/cyksj/model/entity/UserTicketClearedRecord.java
  8. 6 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuInsert.java
  9. 3 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/CorpWxOrderDonView.java
  10. 6 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonBackView.java
  11. 6 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonView.java
  12. 6 0
      netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java
  13. 42 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDiscountPlusPurchaseRelationFrontView.java
  14. 10 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonFrontSkuView.java
  15. 0 1
      netflix-dao/src/main/java/com/cyksj/model/views/GroupsView.java
  16. 5 0
      netflix-dao/src/main/resources/mapper/GoodsDiscountPlusPurchaseRelationMapper.xml
  17. 4 0
      netflix-service/src/main/java/com/cyksj/service/mange/CmsGoodsDonSkuService.java
  18. 101 0
      netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsGoodsDonSkuServiceImpl.java
  19. 24 1
      netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java
  20. 91 5
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  21. 15 1
      netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java
  22. 10 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonController.java
  23. 14 2
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonSkuController.java

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GoodsDiscountPlusPurchaseRelationMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsDiscountPlusPurchaseRelation;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsDiscountPlusPurchaseRelationMapper
+ *创建者: JavaZou
+ *创建时间:2023/7/19 11:42
+ */
+public interface GoodsDiscountPlusPurchaseRelationMapper extends BaseMapper<GoodsDiscountPlusPurchaseRelation> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/OrderDiscountPlusPurchaseSkuRelationMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.OrderDiscountPlusPurchaseSkuRelation;
+
+/*
+ *项目名: netflix
+ *文件名: OrderDiscountPlusPurchaseSkuRelationMapper
+ *创建者: JavaZou
+ *创建时间:2023/7/21 9:56
+ */
+public interface OrderDiscountPlusPurchaseSkuRelationMapper extends BaseMapper<OrderDiscountPlusPurchaseSkuRelation> {
+}

+ 29 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDiscountPlusPurchaseRelation.java

@@ -0,0 +1,29 @@
+package com.cyksj.model.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsDiscountPlusPurchaseRelation
+ *创建者: JavaZou
+ *创建时间:2023/7/19 11:38
+ */
+@Getter
+@Setter
+public class GoodsDiscountPlusPurchaseRelation extends BaseEntity{
+	@JsonIgnore
+	private Long goodsId;
+
+	@JsonIgnore
+	private Long skuId;
+
+	private Long disGid;
+
+	private Long disSid;
+
+	private BigDecimal disPrice;
+}

+ 22 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonSku.java

@@ -2,12 +2,15 @@ package com.cyksj.model.entity;
 
 import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.cyksj.model.views.GoodsDiscountPlusPurchaseRelationFrontView;
 import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
 import lombok.Getter;
 import lombok.Setter;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * @author chan
@@ -100,4 +103,23 @@ public class GoodsDonSku extends BaseEntity {
     @DbField("case when spec_val like '%月%' and spec_val not like '%年%' then 0 when spec_val like '%季%' then 1 when spec_val like '%半年%' then 2 when spec_val like '%年%' then 3 else 66 end")
     @TableField(exist = false)
     private Integer orderBy;
+
+    /**
+     * 加购规格
+     */
+    @DbIgnore
+    @TableField(exist = false)
+    private List<GoodsDiscountPlusPurchaseRelation> dpSku;
+
+    /**
+     * 是否是优惠加购规格
+     */
+    private Boolean isDp;
+
+    /**
+     * 优惠加购商品规格展示
+     */
+    @DbIgnore
+    @TableField(exist = false)
+    private List<GoodsDiscountPlusPurchaseRelationFrontView> dpSkuViews;
 }

+ 23 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/OrderDiscountPlusPurchaseSkuRelation.java

@@ -0,0 +1,23 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: OrderDiscountPlusPurchaseSkuRelation
+ *创建者: JavaZou
+ *创建时间:2023/7/21 9:47
+ */
+@Getter
+@Setter
+public class OrderDiscountPlusPurchaseSkuRelation extends BaseEntity{
+	private Long orderId;
+
+	/**
+	 * 优惠加购规格id
+	 */
+	private String plusSkuIds;
+
+	private String relationIds;
+}

+ 9 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java

@@ -2,7 +2,9 @@ package com.cyksj.model.entity;
 
 import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.TableField;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
@@ -212,6 +214,12 @@ public class OrderDon extends BaseEntity implements Serializable {
     @TableField(exist = false)
     private GoodsDon.SpecialType specialType;
 
+    /**
+     * 是否优惠加购规格
+     */
+    private Boolean isDp;
+
+    private String payTitle;
 
     public enum Status {
         /**

+ 2 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/UserTicketClearedRecord.java

@@ -53,7 +53,8 @@ public class UserTicketClearedRecord extends BaseEntity{
 		new_groups_ticket("新空车队车票"),
 		disable("禁用账号分配车票"),
 		refund_balance("退款余额"),
-		abnormal("异常订单")
+		abnormal("异常订单"),
+		dp("优惠加购订单退款")
 		;
 		String desc;
 

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuInsert.java

@@ -1,5 +1,6 @@
 package com.cyksj.model.manage.request;
 
+import com.cyksj.model.entity.GoodsDiscountPlusPurchaseRelation;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -83,6 +84,11 @@ public class ReqGoodsSkuInsert {
          */
         private String benefitsList;
 
+        /**
+         * 优惠加购虚拟商品
+         */
+        private List<GoodsDiscountPlusPurchaseRelation> dpSku;
+
     }
 
 }

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/CorpWxOrderDonView.java

@@ -80,4 +80,7 @@ public class CorpWxOrderDonView {
 
 	@DbField("o.pay_time")
 	private Date payTime;
+
+	@DbField("o.pay_title")
+	private String payTitle;
 }

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonBackView.java

@@ -141,6 +141,12 @@ public class OrderDonBackView {
 	@DbField("o.pay_time")
 	private Date payTime;
 
+	@DbField("o.is_dp")
+	private Boolean isDp;
+
+	@DbField("o.pay_title")
+	private String payTitle;
+
 	@DbField("o.ex_code")
 	private String exCode;
 

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonView.java

@@ -101,6 +101,12 @@ public class OrderDonView {
     @DbField("o.pay_time")
     private Date payTime;
 
+    @DbField("o.is_dp")
+    private Boolean isDp;
+
+    @DbField("o.pay_title")
+    private String payTitle;
+
     /**
      * 收货人
      */

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java

@@ -7,6 +7,7 @@ import lombok.ToString;
 
 import javax.validation.constraints.NotNull;
 import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * @author chan
@@ -90,6 +91,11 @@ public class OrderPayRequest {
      */
     private OrderDon.Source source;
 
+    /**
+     * 优惠加购规格id
+     */
+    private List<Long> dpSkuIds;
+
     /**
      * 余额支付
      */

+ 42 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDiscountPlusPurchaseRelationFrontView.java

@@ -0,0 +1,42 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsDiscountPlusPurchaseRelationFrontView
+ *创建者: JavaZou
+ *创建时间:2023/7/19 14:08
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_discount_plus_purchase_relation gpr left join goods_don g on g.id = gpr.dis_gid" +
+		" left join goods_don_sku sku on sku.id = gpr.dis_sid",
+		where = "g.deleted is true and g.status is true and sku.status is true")
+public class GoodsDiscountPlusPurchaseRelationFrontView {
+	@DbField("gpr.sku_id")
+	private Long skuId;
+
+	@DbField("gpr.dis_gid")
+	private Long disGid;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("gpr.dis_sid")
+	private Long disSid;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("sku.price")
+	private BigDecimal oriPrice;
+
+	@DbField("gpr.dis_price")
+	private BigDecimal disPrice;
+}

+ 10 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonFrontSkuView.java

@@ -1,11 +1,13 @@
 package com.cyksj.model.views;
 
+import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.Getter;
 import lombok.Setter;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 /*
  *项目名: netflix
@@ -60,4 +62,12 @@ public class GoodsDonFrontSkuView {
 	private Integer days;
 
 	private String notifyText;
+
+	private Boolean isDp;
+
+	/**
+	 * 优惠加购商品
+	 */
+	@DbIgnore
+	private List<GoodsDiscountPlusPurchaseRelationFrontView> dpSkuViews;
 }

+ 0 - 1
netflix-dao/src/main/java/com/cyksj/model/views/GroupsView.java

@@ -60,5 +60,4 @@ public class GroupsView {
      */
     @DbIgnore
     private List<GroupsRelationView> relations;
-
 }

+ 5 - 0
netflix-dao/src/main/resources/mapper/GoodsDiscountPlusPurchaseRelationMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.cyksj.mapper.GoodsDiscountPlusPurchaseRelationMapper">
+</mapper>

+ 4 - 0
netflix-service/src/main/java/com/cyksj/service/mange/CmsGoodsDonSkuService.java

@@ -1,11 +1,15 @@
 package com.cyksj.service.mange;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.GoodsDiscountPlusPurchaseRelation;
 import com.cyksj.model.entity.GoodsDonSku;
 
+import java.util.List;
+
 /**
  * @author chan
  * @date 2022/9/27 5:43 PM
  */
 public interface CmsGoodsDonSkuService extends IService<GoodsDonSku> {
+	void handleDiscountPurchaseGoods(GoodsDonSku sku, List<GoodsDiscountPlusPurchaseRelation> discountPlusPurchaseGoods);
 }

+ 101 - 0
netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsGoodsDonSkuServiceImpl.java

@@ -1,13 +1,25 @@
 package com.cyksj.service.mange.goods;
 
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.GoodsDiscountPlusPurchaseRelationMapper;
 import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.model.entity.GoodsDiscountPlusPurchaseRelation;
 import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.service.mange.CmsGoodsDonSkuService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
 /**
  * @author chan
  * @date 2022/9/27 5:43 PM
@@ -16,4 +28,93 @@ import org.springframework.stereotype.Service;
 @RequiredArgsConstructor
 @Service
 public class CmsGoodsDonSkuServiceImpl extends ServiceImpl<GoodsDonSkuMapper,GoodsDonSku> implements CmsGoodsDonSkuService {
+	private final GoodsDiscountPlusPurchaseRelationMapper discountPlusPurchaseRelationMapper;
+
+	private final GoodsDonSkuMapper skuMapper;
+
+	@Override
+	public void handleDiscountPurchaseGoods(GoodsDonSku sku, List<GoodsDiscountPlusPurchaseRelation> discountPlusPurchaseGoods) {
+		Long skuId = sku.getId();
+		Long goodsId = sku.getGoodsId();
+		List<GoodsDiscountPlusPurchaseRelation> dbDiscountPlusGoodsList = discountPlusPurchaseRelationMapper.selectList(Wrappers.lambdaQuery(GoodsDiscountPlusPurchaseRelation.class)
+				.eq(GoodsDiscountPlusPurchaseRelation::getSkuId, skuId));
+		if (CollUtil.isEmpty(dbDiscountPlusGoodsList) && CollUtil.isNotEmpty(discountPlusPurchaseGoods)) {
+			discountPlusPurchaseGoods.forEach(discountGoods -> {
+				checkPurchaseParamsAndSaveOrUpdate(goodsId, skuId, discountGoods);
+			});
+			sku.setIsDp(true);
+			return;
+		}
+		//优惠加购为空
+		if (CollUtil.isEmpty(discountPlusPurchaseGoods)) {
+			discountPlusPurchaseRelationMapper.delete(Wrappers.lambdaQuery(GoodsDiscountPlusPurchaseRelation.class)
+					.eq(GoodsDiscountPlusPurchaseRelation::getSkuId, skuId));
+			sku.setIsDp(false);
+			return;
+		}
+
+		//新增或更新
+		sku.setIsDp(true);
+		Map<Long, GoodsDiscountPlusPurchaseRelation> skuIdMap = new ConcurrentHashMap<>();
+		discountPlusPurchaseGoods.forEach(discountGoods -> {
+			AtomicBoolean is_exist = new AtomicBoolean(false);
+			if (skuIdMap.get(discountGoods.getDisGid()) == null) {
+				skuIdMap.put(discountGoods.getDisGid(), discountGoods);
+			}
+			dbDiscountPlusGoodsList.forEach(db_exist->{
+				//存在
+				if (db_exist.getDisGid().equals(discountGoods.getDisGid())) {
+					is_exist.set(true);
+					discountGoods.setId(db_exist.getId());
+					checkPurchaseParamsAndSaveOrUpdate(goodsId, skuId, discountGoods);
+				}
+			});
+			//不存在新增
+			if (!is_exist.get()) {
+				checkPurchaseParamsAndSaveOrUpdate(goodsId, skuId, discountGoods);
+			}
+		});
+
+		//去除数据库已被删除的
+		dbDiscountPlusGoodsList.forEach(dbDiscountPlusGoods -> {
+			GoodsDiscountPlusPurchaseRelation exists = skuIdMap.get(dbDiscountPlusGoods.getDisGid());
+			//不存在
+			if (exists == null) {
+				discountPlusPurchaseRelationMapper.deleteById(dbDiscountPlusGoods.getId());
+			}
+		});
+	}
+
+	public void checkPurchaseParamsAndSaveOrUpdate(Long goodsId, Long skuId, GoodsDiscountPlusPurchaseRelation discountGoods) {
+		Long disSid = discountGoods.getDisSid();
+		if (disSid == null) {
+			throw BusinessRuntimeException.getInstance("请选择对应优惠加购规格");
+		}
+		if (skuId.equals(disSid)) {
+			return;
+		}
+		BigDecimal disPrice = discountGoods.getDisPrice();
+		GoodsDonSku sku = skuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
+				.eq(GoodsDonSku::getId, disSid).last("limit 1"));
+		if (sku == null) {
+			throw BusinessRuntimeException.getInstance("规格不存在");
+		}
+		if (!sku.getStatus()) {
+			throw BusinessRuntimeException.getInstance("{0}规格未上架", sku.getSpecVal());
+		}
+		if (disPrice == null || disPrice.compareTo(BigDecimal.ZERO) <= 0) {
+			throw BusinessRuntimeException.getInstance("请输入正确的优惠加购价格");
+		}
+		discountGoods.setGoodsId(goodsId);
+		discountGoods.setSkuId(skuId);
+		discountGoods.setDisGid(sku.getGoodsId());
+		if (discountGoods.getId() != null) {
+			discountPlusPurchaseRelationMapper.updateById(discountGoods);
+			return;
+		}
+		try {
+			discountPlusPurchaseRelationMapper.insert(discountGoods);
+		} catch (DuplicateKeyException e) {
+		}
+	}
 }

+ 24 - 1
netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java

@@ -15,7 +15,10 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
-import com.cyksj.common.util.*;
+import com.cyksj.common.util.Codec;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.common.util.Xmls;
 import com.cyksj.config.WeChatConfig;
 import com.cyksj.config.zfb.AliPayClientFactory;
 import com.cyksj.dto.RedisKey;
@@ -131,6 +134,8 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
     private final StripeService stripeService;
 
+    private final OrderDiscountPlusPurchaseSkuRelationMapper orderDiscountPlusPurchaseSkuRelationMapper;
+
     private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
     @Override
@@ -600,6 +605,24 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
                 record.setStatus(UserDistributeBusinessOrderDonRecord.Status.refund);
                 businessOrderDonRecordMapper.updateById(record);
             }
+            //是否是优惠加购关联订单
+            if (orderDon.getIsDp()) {
+                OrderDiscountPlusPurchaseSkuRelation discountPlusPurchaseSkuRelation = orderDiscountPlusPurchaseSkuRelationMapper.selectOne(Wrappers.lambdaQuery(OrderDiscountPlusPurchaseSkuRelation.class)
+                        .eq(OrderDiscountPlusPurchaseSkuRelation::getOrderId, orderDon.getId()).last("limit 1"));
+                if (discountPlusPurchaseSkuRelation != null) {
+                    String relationIdsStr = discountPlusPurchaseSkuRelation.getRelationIds();
+                    if (StrUtil.isNotBlank(relationIdsStr)) {
+                        try {
+                            List<Long> relationIds = Jsons.parseList(relationIdsStr, Long.class);
+                            List<GroupsRelation> groupsRelations = relationMapper.selectList(Wrappers.lambdaQuery(GroupsRelation.class)
+                                    .in(GroupsRelation::getId, relationIds));
+                            log.info("优惠加购订单orderId:{}退款,清除相关车票relation_ids:{}", orderDon.getId(), relationIds);
+                            groupsRelations.forEach(relation -> relationClearService.clearTicket(relation, UserTicketClearedRecord.Source.dp));
+                        } catch (Exception e) {
+                        }
+                    }
+                }
+            }
         });
     }
 

+ 91 - 5
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -87,10 +87,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
 
 import static com.cyksj.enums.GatewayApiCode.GROUP_INDEX_ALREADY_BE_USER;
 import static com.cyksj.enums.GatewayApiCode.GROUP_INDEX_NOT_FIND;
@@ -202,6 +199,10 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final OrderDonPostService orderDonPostService;
 
+	private final GoodsDiscountPlusPurchaseRelationMapper discountPlusPurchaseRelationMapper;
+
+	private final OrderDiscountPlusPurchaseSkuRelationMapper orderDiscountPlusPurchaseSkuRelationMapper;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -244,18 +245,49 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		/* 生成订单 */
 		String donNo = SEQUENCE.nextId().toString();
 		OrderDon orderDon = new OrderDon();
+		orderDon.setIsDp(false);
 		if (isNoLogin != null && isNoLogin) {
 			orderDon.setIsNoLogin(true);
 		}
 		orderDon.setOrderNo(donNo);
 		orderDon.setOpenId(payOpenId);
-		if (sku.getPrice() != null && payRequest.getDonMoney().compareTo(sku.getPrice()) < 0) {
+		if (sku.getPrice() == null || sku.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
+			throw BusinessRuntimeException.getInstance("下单商品价格异常");
+		}
+		if (payRequest.getDonMoney().compareTo(sku.getPrice()) < 0) {
 			log.info("规格:{}支付金额:{}异常,调整用户userId:{}支付金额为:{}", sku.getSpecVal(), payRequest.getDonMoney(), user.getId(), sku.getPrice());
 			payRequest.setDonMoney(sku.getPrice());
 		}
+
 		orderDon.setMoney(payRequest.getDonMoney());
 		orderDon.setRealMoney(payRequest.getDonMoney());
 
+		List<Long> dpSkuIds = payRequest.getDpSkuIds();
+		if (CollUtil.isNotEmpty(dpSkuIds)) {
+			if (dpSkuIds.size() > 1) {
+				throw BusinessRuntimeException.getInstance("暂只支持优惠加购一件商品");
+			}
+			//是否满足关联
+			List<GoodsDiscountPlusPurchaseRelation> ds_relations = discountPlusPurchaseRelationMapper.selectList(Wrappers.lambdaQuery(GoodsDiscountPlusPurchaseRelation.class)
+					.eq(GoodsDiscountPlusPurchaseRelation::getSkuId, sku.getId())
+					.in(GoodsDiscountPlusPurchaseRelation::getDisSid, dpSkuIds));
+			if (ds_relations.size() != dpSkuIds.size()) {
+				throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重新下单");
+			}
+			BigDecimal goods_discount_plus_pay = BigDecimal.ZERO;
+			List<Long> dsSkuIds = new ArrayList<>();
+			for (GoodsDiscountPlusPurchaseRelation re : ds_relations) {
+				goods_discount_plus_pay = goods_discount_plus_pay.add(re.getDisPrice());
+				dsSkuIds.add(re.getDisSid());
+			}
+			BigDecimal pay_money = sku.getPrice().add(goods_discount_plus_pay);
+			if (pay_money.compareTo(orderDon.getMoney()) > 0) {
+				orderDon.setMoney(pay_money);
+				orderDon.setRealMoney(pay_money);
+			}
+			orderDon.setIsDp(true);
+		}
+
 		//渠道链接id
 		if (payRequest.getPopularizeId() != null) {
 			orderDon.setPopularizeId(payRequest.getPopularizeId());
@@ -298,8 +330,31 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			}
 		}
 		orderDon.setPayDesc(goodsDon.getPayDesc());
+		StringBuilder payTitle = new StringBuilder();
+		payTitle.append(goodsDon.getTitle());
+		payTitle.append(sku.getSpecVal());
+		if (orderDon.getIsDp()) {
+			List<GoodsDonSkuView> dp_skuViewList = beanSearcher.searchAll(GoodsDonSkuView.class, MapUtils.builder().field(GoodsDonSkuView::getSkuId, dpSkuIds).op(Operator.InList).build());
+			if (dp_skuViewList.size() != dpSkuIds.size()) {
+				throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重新下单");
+			}
+			dp_skuViewList.forEach(dp_SkuView -> {
+				payTitle.append(" + ");
+				payTitle.append(dp_SkuView.getGoodsTitle());
+				payTitle.append(dp_SkuView.getSpecVal());
+			});
+		}
+		orderDon.setPayTitle(payTitle.toString());
 		this.saveOrUpdate(orderDon);
 
+		if (orderDon.getIsDp()) {
+			//保存订单优惠加购规格 关系
+			OrderDiscountPlusPurchaseSkuRelation orderDiscountPlusPurchaseSkuRelation = new OrderDiscountPlusPurchaseSkuRelation();
+			orderDiscountPlusPurchaseSkuRelation.setOrderId(orderDon.getId());
+			orderDiscountPlusPurchaseSkuRelation.setPlusSkuIds(dpSkuIds.toString());
+			orderDiscountPlusPurchaseSkuRelationMapper.insert(orderDiscountPlusPurchaseSkuRelation);
+		}
+
 		if (Constant.realGoodsType.contains(goodsDon.getType()) && !goodsDon.getId().equals(27l)) {
 			saveTransport(payRequest.getAddressId(), orderDon.getId());
 		}
@@ -1124,6 +1179,37 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			log.info("虚物订单orderNo:{}开始更新车票信息", order.getOrderNo());
 			//修改车位状态
 			GroupsRelation relation = groupsRelationMapper.selectById(order.getRelationId());
+			if (order.getIsDp()) {
+				//是否已经发送优惠加购车票
+				OrderDiscountPlusPurchaseSkuRelation purchaseSkuRelation = orderDiscountPlusPurchaseSkuRelationMapper.selectOne(Wrappers.lambdaQuery(OrderDiscountPlusPurchaseSkuRelation.class)
+						.eq(OrderDiscountPlusPurchaseSkuRelation::getOrderId, order.getId()));
+				if (purchaseSkuRelation != null) {
+					String plusSkuIdsStr = purchaseSkuRelation.getPlusSkuIds();
+					String relationIdsStr = purchaseSkuRelation.getRelationIds();
+					if (StrUtil.isNotEmpty(plusSkuIdsStr) && StrUtil.isEmpty(relationIdsStr)) {
+						try {
+							List<Long> plusSkuIds = Jsons.parseList(plusSkuIdsStr, Long.class);
+							//发送优惠加购 规格车票
+							List<Long> dis_relation_ids = new ArrayList<>();
+							plusSkuIds.forEach(plus_skuId -> {
+								GoodsDonSku plus_sku = goodsDonSkuMapper.selectById(plus_skuId);
+								if (plus_sku == null) {
+									log.error("订单id:{}优惠加购规格已被删除 skuId:{},车票未发送", order.getId(), plus_skuId);
+									return;
+								}
+								GroupsRelation relationNoOrder = exchangeCodeService.getRelationNoOrder(plus_sku, order.getUserId());
+								dis_relation_ids.add(relationNoOrder.getId());
+							});
+							//保存订单关联优惠加购车票
+							orderDiscountPlusPurchaseSkuRelationMapper.update(null, Wrappers.lambdaUpdate(OrderDiscountPlusPurchaseSkuRelation.class)
+									.set(OrderDiscountPlusPurchaseSkuRelation::getRelationIds, dis_relation_ids.toString())
+									.eq(OrderDiscountPlusPurchaseSkuRelation::getOrderId, order.getId())
+									.isNull(OrderDiscountPlusPurchaseSkuRelation::getRelationIds));
+						} catch (Exception e) {
+						}
+					}
+				}
+			}
 			if (order.getRelationId() != 0 && !relation.getUserId().equals(order.getUserId()) && order.getOrderType() == 1) {
 				GroupsRelation relationNoOrder = exchangeCodeService.getRelationNoOrder(sku, order.getUserId());
 				if (relationNoOrder == null) {

+ 15 - 1
netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java

@@ -180,6 +180,12 @@ public class GoodsDonController {
         list.forEach(data -> {
             data.setSpecs(beanSearcher.searchFirst(GoodsDonSpec.class, MapUtils.builder().field(GoodsDonSpec::getGoodsId, data.getId()).build()));
             data.setSkuList(beanSearcher.searchAll(GoodsDonFrontSkuView.class, MapUtils.builder().field(GoodsDonFrontSkuView::getGoodsId, data.getId()).field(GoodsDonFrontSkuView::getStatus, true).orderBy(GoodsDonFrontSkuView::getPrice).asc().build()));
+            data.getSkuList().forEach(sku -> {
+                if (sku.getIsDp()) {
+                    List<GoodsDiscountPlusPurchaseRelationFrontView> dpSkuViews = beanSearcher.searchAll(GoodsDiscountPlusPurchaseRelationFrontView.class, MapUtils.builder().field(GoodsDiscountPlusPurchaseRelationFrontView::getSkuId, sku.getId()).build());
+                    sku.setDpSkuViews(dpSkuViews);
+                }
+            });
             Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
                     .eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
             data.setSold(sold + data.getVirtualSold());
@@ -290,7 +296,15 @@ public class GoodsDonController {
         if (goodsDonSkuView != null && goodsDonSkuView.getType() == 1) {
             builder.orderBy(GoodsDonSku::getOrderBy).asc();
         }
-        views.setSkuList(beanSearcher.searchAll(GoodsDonSku.class, builder.build()));
+        List<GoodsDonSku> goodsDonSkus = beanSearcher.searchAll(GoodsDonSku.class, builder.build());
+        goodsDonSkus.forEach(sku -> {
+            if (sku.getIsDp()) {
+                sku.setDpSkuViews(beanSearcher.searchAll(GoodsDiscountPlusPurchaseRelationFrontView.class, MapUtils.builder()
+                        .field(GoodsDiscountPlusPurchaseRelationFrontView::getSkuId, sku.getId())
+                        .build()));
+            }
+        });
+        views.setSkuList(goodsDonSkus);
         return GatewayResponse.SUCCESS.newBuilder().toResult(views);
     }
 

+ 10 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonController.java

@@ -7,6 +7,7 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.GoodsDiscountPlusPurchaseRelation;
 import com.cyksj.model.entity.GoodsDon;
 import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.manage.request.ReqGoodsSpuInsert;
@@ -59,6 +60,15 @@ public class CmsGoodsDonController {
     public Result<GoodsDonViewer> getById(@PathVariable Long id) {
         GoodsDonViewer goodsDonViewer = beanSearcher.searchFirst(GoodsDonViewer.class, MapUtils.builder().field(GoodsDonViewer::getId, id).build());
         List<GoodsDonSku> goodsDonSkus = beanSearcher.searchAll(GoodsDonSku.class, MapUtils.builder().field(GoodsDonSku::getGoodsId, id).build());
+        if (goodsDonViewer.getType() == 1) {
+            goodsDonSkus.forEach(sku -> {
+                if (sku.getIsDp()) {
+                    sku.setDpSku(beanSearcher.searchAll(GoodsDiscountPlusPurchaseRelation.class, MapUtils.builder()
+                            .field(GoodsDiscountPlusPurchaseRelation::getSkuId, sku.getId())
+                            .build()));
+                }
+            });
+        }
         goodsDonViewer.setSkus(goodsDonSkus);
         return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDonViewer);
     }

+ 14 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonSkuController.java

@@ -1,6 +1,7 @@
 package com.cyksj.web.controller.manage.goods;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.annotation.Log;
 import com.cyksj.common.exception.BusinessRuntimeException;
@@ -218,12 +219,19 @@ public class CmsGoodsDonSkuController {
             goodsDonSku.setSpecVal(specVal);
             goodsDonSku.setSpecJson(specJson);
             if (goods.getType() == 1) {
-                if (sku.getMonths() != null && sku.getDays() != null)
+                if (sku.getMonths() != null && sku.getMonths() > 0 && sku.getDays() != null && sku.getDays() > 0) {
                     throw BusinessRuntimeException.getInstance("续费天数和续费月数不能同时存在");
+                }
                 if (sku.getMonths() == null && sku.getDays() == null)
                     throw BusinessRuntimeException.getInstance("请输入对应续费时间");
             }
+            if (CollUtil.isNotEmpty(sku.getDpSku())) {
+                goodsDonSku.setIsDp(true);
+            }
             goodsDonSkuService.save(goodsDonSku);
+            if (CollUtil.isNotEmpty(sku.getDpSku())) {
+                goodsDonSkuService.handleDiscountPurchaseGoods(goodsDonSku, sku.getDpSku());
+            }
 
         }
         //给平台更新额外属性
@@ -243,8 +251,9 @@ public class CmsGoodsDonSkuController {
         Long goodsId = sku.getGoodsId();
         GoodsDon goods = goodsDonService.getById(goodsId);
         if (goods.getType() == 1) {
-            if (sku.getMonths() != null && sku.getDays() != null)
+            if (sku.getMonths() != null && sku.getMonths() > 0 && sku.getDays() != null && sku.getDays() > 0) {
                 throw BusinessRuntimeException.getInstance("续费天数和续费月数不能同时存在");
+            }
             if (sku.getMonths() == null && sku.getDays() == null)
                 throw BusinessRuntimeException.getInstance("请输入对应续费时间");
         }
@@ -254,6 +263,8 @@ public class CmsGoodsDonSkuController {
         if (sku.getDays() == null) {
             sku.setDays(null);
         }
+        //优惠加购
+        goodsDonSkuService.handleDiscountPurchaseGoods(sku, sku.getDpSku());
         goodsDonSkuService.saveOrUpdate(sku);
         //给平台更新额外属性
         goodsDonService.updateGoodsSkuPrice(sku.getGoodsId(), null);
@@ -272,6 +283,7 @@ public class CmsGoodsDonSkuController {
     public Result<String> skuDelete(@PathVariable Long skuId) {
         //给平台更新额外属性
         GoodsDonSku sku = goodsDonSkuService.getById(skuId);
+        goodsDonSkuService.handleDiscountPurchaseGoods(sku, null);
         goodsDonSkuService.removeById(skuId);
         goodsDonService.updateGoodsSkuPrice(sku.getGoodsId(), null);
         Set<String> keys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "*");