zhanghua
2025-06-11 2ca169c85f61256fb5185c078dba1bfef2be5066
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
package cn.lili.modules.order.cart.render.impl;
 
import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.common.utils.StringUtils;
import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.enums.RenderStepEnums;
import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
import cn.lili.modules.order.cart.render.CartRenderStep;
import cn.lili.modules.order.cart.render.util.PromotionPriceUtil;
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.enums.CouponTypeEnum;
import cn.lili.modules.promotion.entity.enums.PromotionsScopeTypeEnum;
import cn.lili.modules.promotion.entity.vos.MemberCouponVO;
import cn.lili.modules.promotion.service.MemberCouponService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * 购物促销信息渲染实现
 *
 * @author Chopper
 * @since 2020-07-02 14:47
 */
@Service
public class CouponRender implements CartRenderStep {
 
    @Autowired
    private MemberCouponService memberCouponService;
 
    @Override
    public RenderStepEnums step() {
        return RenderStepEnums.COUPON;
    }
 
    @Override
    public void render(TradeDTO tradeDTO) {
 
        //优惠券列表
        this.renderCouponRule(tradeDTO);
        //主要渲染各个优惠的价格
        this.renderCoupon(tradeDTO);
    }
 
 
    /**
     * 渲染优惠券规则
     *
     * @param tradeDTO 交易dto
     */
    private void renderCouponRule(TradeDTO tradeDTO) {
        // 清除之前的优惠券
        tradeDTO.removeCoupon();
 
        List<MemberCoupon> memberCouponList = memberCouponService.getMemberCoupons(tradeDTO.getMemberId());
 
        //获取最新优惠券
        memberCouponList = memberCouponList.stream()
                .filter(item -> item.getStartTime().before(new Date()) && item.getEndTime().after(new Date()))
                .collect(Collectors.toList());
 
        if (!memberCouponList.isEmpty()) {
            this.checkMemberExistCoupon(tradeDTO, memberCouponList);
        } else {
            tradeDTO.setPlatformCoupon(null);
            tradeDTO.setStoreCoupons(new HashMap<>());
        }
        memberCouponList.forEach(memberCoupon -> available(tradeDTO, memberCoupon));
    }
 
    /**
     * 检查使用中的优惠券是否存在与用户的优惠券中
     *
     * @param tradeDTO         交易dto
     * @param memberCouponList 会员优惠券列表
     */
    private void checkMemberExistCoupon(TradeDTO tradeDTO, List<MemberCoupon> memberCouponList) {
        if (tradeDTO.getPlatformCoupon() != null && tradeDTO.getPlatformCoupon().getMemberCoupon() != null) {
            boolean b = memberCouponList.stream().anyMatch(i -> i.getId().equals(tradeDTO.getPlatformCoupon().getMemberCoupon().getId()));
            if (!b) {
                tradeDTO.setPlatformCoupon(null);
            }
        }
        if (!tradeDTO.getStoreCoupons().isEmpty()) {
            for (Map.Entry<String, MemberCouponDTO> entry : tradeDTO.getStoreCoupons().entrySet()) {
                if (entry.getValue().getMemberCoupon() != null && memberCouponList.stream().noneMatch(i -> i.getId().equals(entry.getValue().getMemberCoupon().getId()))) {
                    tradeDTO.getStoreCoupons().remove(entry.getKey());
                }
            }
        }
    }
 
    /**
     * 判定优惠券是否可用
     *
     * @param tradeDTO     交易dto
     * @param memberCoupon 会员优惠券
     */
    private void available(TradeDTO tradeDTO, MemberCoupon memberCoupon) {
        if (memberCoupon == null) {
            return;
        }
        List<CartSkuVO> filterSku = filterSkuVo(tradeDTO.getCheckedSkuList(), memberCoupon);
        if (filterSku == null || filterSku.isEmpty()) {
            tradeDTO.getCantUseCoupons().add(new MemberCouponVO(memberCoupon,
                    "购物车中没有满足优惠券使用范围的优惠券"));
            return;
        }
        List<PriceDetailDTO> priceDetailDTOS =
                filterSku.stream().map(CartSkuVO::getPriceDetailDTO).collect(Collectors.toList());
 
        PriceDetailDTO totalPrice = new PriceDetailDTO();
        totalPrice.accumulationPriceDTO(priceDetailDTOS);
 
        //满足条件判定
        if (totalPrice.getGoodsPrice() >= memberCoupon.getConsumeThreshold()) {
            tradeDTO.getCanUseCoupons().add(memberCoupon);
        } else {
            tradeDTO.getCantUseCoupons().add(new MemberCouponVO(memberCoupon,
                    "优惠券使用门槛不足,还差" +
                            StringUtils.toFen(CurrencyUtil.sub(memberCoupon.getConsumeThreshold(), totalPrice.getGoodsPrice())) +
                            "元"));
        }
 
    }
 
    /**
     * 过滤购物车商品信息,按照优惠券的适用范围过滤
     *
     * @param cartSkuVOS   购物车中的产品列表
     * @param memberCoupon 会员优惠券
     * @return 按照优惠券的适用范围过滤的购物车商品信息
     */
    private List<CartSkuVO> filterSkuVo(List<CartSkuVO> cartSkuVOS, MemberCoupon memberCoupon) {
 
        List<CartSkuVO> filterSku;
        //平台店铺过滤
        if (Boolean.TRUE.equals(memberCoupon.getPlatformFlag())) {
            filterSku = cartSkuVOS;
        } else {
            filterSku = cartSkuVOS.stream().filter(cartSkuVO -> cartSkuVO.getStoreId().equals(memberCoupon.getStoreId())).collect(Collectors.toList());
        }
        if (filterSku == null || filterSku.isEmpty()) {
            return Collections.emptyList();
        }
        //优惠券类型判定
        switch (PromotionsScopeTypeEnum.valueOf(memberCoupon.getScopeType())) {
            case ALL:
                return filterSku;
            case PORTION_GOODS:
                //按照商品过滤
                filterSku = filterSku.stream().filter(cartSkuVO -> memberCoupon.getScopeId().contains(cartSkuVO.getGoodsSku().getId())).collect(Collectors.toList());
                break;
 
            case PORTION_SHOP_CATEGORY:
                //按照店铺分类过滤
                filterSku = this.filterPromotionShopCategory(filterSku, memberCoupon);
                break;
 
            case PORTION_GOODS_CATEGORY:
 
                //按照店铺分类过滤
                filterSku = filterSku.stream().filter(cartSkuVO -> {
                    //平台分类获取
                    String[] categoryPath = cartSkuVO.getGoodsSku().getCategoryPath().split(",");
                    //平台三级分类
                    String categoryId = categoryPath[categoryPath.length - 1];
                    return memberCoupon.getScopeId().contains(categoryId);
                }).collect(Collectors.toList());
                break;
            default:
                return Collections.emptyList();
        }
        return filterSku;
    }
 
    /**
     * 优惠券按照店铺分类过滤
     *
     * @param filterSku    过滤的购物车商品信息
     * @param memberCoupon 会员优惠
     * @return 优惠券按照店铺分类过滤的购物车商品信息
     */
    private List<CartSkuVO> filterPromotionShopCategory(List<CartSkuVO> filterSku, MemberCoupon memberCoupon) {
        return filterSku.stream().filter(cartSkuVO -> {
            if (CharSequenceUtil.isNotEmpty(cartSkuVO.getGoodsSku().getStoreCategoryPath())) {
                //获取店铺分类
                String[] storeCategoryPath = cartSkuVO.getGoodsSku().getStoreCategoryPath().split(",");
                for (String category : storeCategoryPath) {
                    //店铺分类只要有一项吻合,即可返回true
                    if (memberCoupon.getScopeId().contains(category)) {
                        return true;
                    }
                }
            }
            return false;
        }).collect(Collectors.toList());
    }
 
    /**
     * 渲染优惠券
     *
     * @param tradeDTO 购物车展示信息
     */
    private void renderCoupon(TradeDTO tradeDTO) {
        MemberCouponDTO platformCoupon = tradeDTO.getPlatformCoupon();
        //如果有勾选平台优惠券
        if (platformCoupon != null) {
            renderSku(tradeDTO, platformCoupon);
        }
        //计算商家优惠券
        Map<String, MemberCouponDTO> map = tradeDTO.getStoreCoupons();
        if (map != null && map.size() > 0) {
            for (MemberCouponDTO memberCouponDTO : map.values()) {
                renderSku(tradeDTO, memberCouponDTO);
            }
        }
    }
 
    /**
     * 渲染sku优惠信息
     *
     * @param tradeDTO        交易DTO
     * @param memberCouponDTO 优惠券DTO
     */
    private void renderSku(TradeDTO tradeDTO, MemberCouponDTO memberCouponDTO) {
 
        //计算优惠总金额
        Double countPrice = 0D;
        Map<String, Double> couponMap = memberCouponDTO.getSkuDetail();
        for (Double skuPrice : couponMap.values()) {
            countPrice = CurrencyUtil.add(countPrice, skuPrice);
        }
 
        //接收具体优惠券信息
        MemberCoupon coupon = memberCouponDTO.getMemberCoupon();
        //处理一个极端情况,如果优惠券满减金额大于订单金额
        if (coupon.getCouponType().equals(CouponTypeEnum.PRICE.name()) && coupon.getPrice() > countPrice) {
            //将符合优惠券的金额写入,即最大扣减金额
            coupon.setPrice(countPrice);
        }
 
        if (coupon.getCouponType().equals(CouponTypeEnum.PRICE.name())) {
            //减免现金,则按照商品价格计算 需要通过工具类进行优惠金额的分发,分发给每个商品
            this.renderCouponPrice(couponMap, tradeDTO, coupon, memberCouponDTO);
        } else {
            //打折券 直接计算
            this.renderCouponDiscount(couponMap, tradeDTO, coupon);
        }
    }
 
    /**
     * 减免现金,则按照商品价格计算 需要通过工具类进行优惠金额的分发,分发给每个商品
     *
     * @param couponMap       优惠券结算信息
     * @param tradeDTO        交易dto
     * @param coupon          优惠券信息
     * @param memberCouponDTO 用于计算优惠券结算详情
     */
    private void renderCouponPrice(Map<String, Double> couponMap, TradeDTO tradeDTO, MemberCoupon coupon, MemberCouponDTO memberCouponDTO) {
        //分发优惠券
        PromotionPriceUtil.recountPrice(tradeDTO, memberCouponDTO.getSkuDetail(), memberCouponDTO.getMemberCoupon().getPrice(),
                Boolean.TRUE.equals(coupon.getPlatformFlag()) ?
                        PromotionTypeEnum.PLATFORM_COUPON : PromotionTypeEnum.COUPON, memberCouponDTO.getMemberCoupon().getCouponId());
        //如果是平台券 则需要计算商家承担比例
        if (Boolean.TRUE.equals(coupon.getPlatformFlag()) && coupon.getStoreCommission() > 0) {
 
            //循环所有优惠券
            for (String skuId : couponMap.keySet()) {
 
                for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) {
                    //写入平台优惠券承担比例
                    if (cartSkuVO.getGoodsSku().getId().equals(skuId)) {
                        //写入店铺承担比例
                        cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission());
                    }
                }
            }
        }
    }
 
 
    /**
     * 打折券计算
     *
     * @param couponMap 优惠券结算信息
     * @param tradeDTO  交易dto
     * @param coupon    优惠券信息
     */
    private void renderCouponDiscount(Map<String, Double> couponMap, TradeDTO tradeDTO, MemberCoupon coupon) {
        //循环所有优惠券
        for (String skuId : couponMap.keySet()) {
 
            // 循环购物车商品
            for (CartSkuVO item : tradeDTO.getSkuList()) {
                //如果id相等,则渲染商品价格信息
                if (item.getGoodsSku().getId().equals(skuId)) {
 
                    PriceDetailDTO priceDetailDTO = item.getPriceDetailDTO();
 
                    // 打折金额=商品金额*折扣/10
                    Double discountCouponPrice = CurrencyUtil.mul(priceDetailDTO.getGoodsPrice(),
                            CurrencyUtil.sub(1, CurrencyUtil.div(coupon.getDiscount(), 10, 3)));
 
                    //平台券则写入店铺承担优惠券比例
                    if (Boolean.TRUE.equals(coupon.getPlatformFlag())) {
                        priceDetailDTO.setSiteCouponPrice(discountCouponPrice);
                        priceDetailDTO.setSiteCouponPoint(coupon.getStoreCommission());
                    }
                    priceDetailDTO.setCouponPrice(CurrencyUtil.add(priceDetailDTO.getCouponPrice(), discountCouponPrice));
 
                }
            }
        }
    }
 
}