From 7277ecb2d42882e531175a2b9b292b002cd7b0e1 Mon Sep 17 00:00:00 2001 From: YunaiV <> Date: Thu, 18 Apr 2019 22:46:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E5=90=8E=E7=AB=AF=EF=BC=9A=E5=95=86?= =?UTF-8?q?=E5=93=81=E7=A1=AE=E8=AE=A4=E9=A1=B5=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E4=BC=98=E6=83=A0=E5=8A=B5=E6=8E=A5=E5=85=A5=20=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=EF=BC=9A=E4=BF=AE=E6=94=B9=E4=BA=86=E4=BB=B7=E6=A0=BC?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/mall/admin/package-info.java | 1 - mobile-web/src/api/promotion.js | 1 - mobile-web/src/main.js | 2 + mobile-web/src/page/cart/index.vue | 15 +-- mobile-web/src/page/product/detail.vue | 6 +- mobile-web/src/page/shipping/order.vue | 96 ++++++++++++++++--- mobile-web/src/page/user/coupon/list.vue | 2 +- .../controller/users/UsersCartController.java | 14 ++- .../application/convert/CartConvert.java | 18 ++++ .../application/vo/UsersCalcSkuPriceVO.java | 2 +- .../application/vo/UsersCartDetailVO.java | 58 ++++++----- .../vo/UsersOrderConfirmCreateVO.java | 44 +++++++-- .../mall/order/api/bo/CalcOrderPriceBO.java | 66 ++++++++----- .../mall/order/api/bo/CalcSkuPriceBO.java | 4 +- .../order/biz/dataobject/OrderItemDO.java | 46 ++++++++- .../biz/dataobject/OrderPreferentialDO.java | 46 +++++++++ .../iocoder/mall/order/biz/package-info.java | 5 - .../order/biz/service/CartServiceImpl.java | 81 ++++++++++------ .../order/biz/service/OrderServiceImpl.java | 4 +- .../iocoder/mall/pay/biz/mq/package-info.java | 1 - .../cn/iocoder/mall/product/package-info.java | 1 - .../mall/promotion/api/CouponService.java | 18 +++- .../api/bo/CouponCardAvailableBO.java | 24 +++++ .../promotion/api/dto/CouponCardSpuDTO.java | 39 ++++++++ .../biz/convert/CouponCardConvert.java | 4 + .../promotion/biz/dao/CouponCardMapper.java | 3 + .../biz/dao/CouponTemplateMapper.java | 3 + .../mall/promotion/biz/package-info.java | 1 - .../biz/service/CouponServiceImpl.java | 56 +++++++++-- .../resources/mapper/CouponCardMapper.xml | 14 +++ .../resources/mapper/CouponTemplateMapper.xml | 10 ++ .../mall/promotion/biz/package-info.java | 1 - .../iocoder/mall/user/sdk/package-info.java | 6 -- .../iocoder/mall/user/biz/package-info.java | 1 - 34 files changed, 550 insertions(+), 143 deletions(-) delete mode 100644 admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/package-info.java create mode 100644 order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderPreferentialDO.java delete mode 100644 order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/package-info.java delete mode 100644 pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/package-info.java delete mode 100644 product/product-service-impl/src/main/java/cn/iocoder/mall/product/package-info.java create mode 100644 promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/bo/CouponCardAvailableBO.java create mode 100644 promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/dto/CouponCardSpuDTO.java delete mode 100644 promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/package-info.java delete mode 100644 promotion/promotion-service-impl/src/test/java/cn/iocoder/mall/promotion/biz/package-info.java delete mode 100644 user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/package-info.java delete mode 100644 user/user-service-impl/src/main/java/cn/iocoder/mall/user/biz/package-info.java diff --git a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/package-info.java b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/package-info.java deleted file mode 100644 index 35990e238..000000000 --- a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.mall.admin; \ No newline at end of file diff --git a/mobile-web/src/api/promotion.js b/mobile-web/src/api/promotion.js index f58154c09..ee61a7a71 100644 --- a/mobile-web/src/api/promotion.js +++ b/mobile-web/src/api/promotion.js @@ -16,7 +16,6 @@ export function getProductRecommendList() { url: '/promotion-api/users/product_recommend/list', method: 'get', params: { - id, } }); } diff --git a/mobile-web/src/main.js b/mobile-web/src/main.js index 9577aa1c7..985866096 100644 --- a/mobile-web/src/main.js +++ b/mobile-web/src/main.js @@ -6,6 +6,7 @@ import App from './App.vue'; import VueLazyload from 'vue-lazyload' import components from './config/components.js'; import { Dialog } from 'vant'; +import { CouponCell, CouponList } from 'vant'; import { formatDate } from './utils/date.js'; @@ -13,6 +14,7 @@ Vue.use(components); Vue.use(VueLazyload); Vue.use(Dialog); +Vue.use(CouponCell).use(CouponList); new Vue({ router, diff --git a/mobile-web/src/page/cart/index.vue b/mobile-web/src/page/cart/index.vue index 54e787e04..d07bf260e 100644 --- a/mobile-web/src/page/cart/index.vue +++ b/mobile-web/src/page/cart/index.vue @@ -133,13 +133,14 @@ export default { } return text; }, + formatItemGroupDiscountPriceText() { - let price = 0; - for (let i in this.itemGroups) { - let itemGroup = this.itemGroups[i]; - price += itemGroup.fee.discountTotal; - } - return price > 0 ? '立减 ' + price / 100.0 + ' 元' : ''; + // let price = 0; + // for (let i in this.itemGroups) { + // let itemGroup = this.itemGroups[i]; + // price += itemGroup.activityDiscountTotal || 0; + // } + return this.fee.discountTotal > 0 ? '立减 ' + this.fee.discountTotal / 100.0 + ' 元' : ''; }, calCheckedItemIds() { @@ -226,7 +227,7 @@ export default { return { ...item.spu, quantity: item.buyQuantity, - price: item.discountPrice || item.price, + price: item.buyPrice || item.price, sku: { ...item, spu: undefined, diff --git a/mobile-web/src/page/product/detail.vue b/mobile-web/src/page/product/detail.vue index fe7b0bdbb..c34a42499 100644 --- a/mobile-web/src/page/product/detail.vue +++ b/mobile-web/src/page/product/detail.vue @@ -9,8 +9,8 @@ -
- {{ formatPrice(calSkuPriceResult.presentPrice) }} +
+ {{ formatPrice(calSkuPriceResult.buyPrice) }} {{ formatPrice(calSkuPriceResult.originalPrice) }}
@@ -283,7 +283,7 @@ for (let i in this.vanSku.list) { let sku = this.vanSku.list[i]; if (sku.id === skuId) { - sku.price = data.presentPrice; + sku.price = data.buyPrice; break; } } diff --git a/mobile-web/src/page/shipping/order.vue b/mobile-web/src/page/shipping/order.vue index 5e6fea44d..9d677d2e9 100644 --- a/mobile-web/src/page/shipping/order.vue +++ b/mobile-web/src/page/shipping/order.vue @@ -43,21 +43,36 @@ />
- - - + + + + + + + +
- - - - + + + +
{ if (result) { - const { orderNo } = result; + // const { orderNo } = result; this.$router.push({ //核心语句 path:`/order/success`, //跳转的路径 query:{ //路由传参时push和query搭配使用 ,作用时传递参数 @@ -128,7 +170,7 @@ } else if (this.from === 'cart') { createOrderFromCart(userAddressId, remark).then(result => { if (result) { - const { orderNo } = result; + // const { orderNo } = result; this.$router.push({ //核心语句 path:`/order/success`, //跳转的路径 query:{ //路由传参时push和query搭配使用 ,作用时传递参数 @@ -140,16 +182,34 @@ } }, convertProduct(item) { - // debugger; return { ...item.spu, quantity: item.buyQuantity, - price: item.price, + price: item.buyPrice || item.price, sku: { ...item, spu: undefined, } }; + }, + convertCouponList(cards) { + let newCards = []; + for (let i in cards) { + let card = cards[i]; + newCards.push({ + id: card.id, + name: card.title, + condition: '满 ' + card.priceAvailable / 100.0 + ' 元可用', + startAt: card.validStartTime / 1000, + endAt: card.validEndTime / 1000, + // description: '述信息,优惠券可用时展示', + reason: card.unavailableReason, + value: card.preferentialType === 1 ? card.priceOff : card.percentOff, + valueDesc: card.preferentialType === 1 ? card.priceOff / 100 : card.percentOff / 10.0, + unitDesc: card.preferentialType === 1 ? '元' : '折' + }) + } + return newCards; } }, mounted: function() { @@ -166,11 +226,19 @@ getOrderConfirmCreateOrder(this.skuId, this.quantity).then(data => { this.itemGroups = data.itemGroups; this.fee = data.fee; + // 获得优惠劵列表 }) } else if (this.from === 'cart') { getCartConfirmCreateOrder().then(data => { this.itemGroups = data.itemGroups; this.fee = data.fee; + // 获得优惠劵列表 + this.coupons = this.convertCouponList(data.couponCards.filter(function (element) { + return element.available; + })); + this.disabledCoupons = this.convertCouponList(data.couponCards.filter(function (element) { + return !element.available; + })); }) } }, diff --git a/mobile-web/src/page/user/coupon/list.vue b/mobile-web/src/page/user/coupon/list.vue index 044ba9a69..59a6e1eb1 100644 --- a/mobile-web/src/page/user/coupon/list.vue +++ b/mobile-web/src/page/user/coupon/list.vue @@ -33,7 +33,7 @@
- 满 {{item.priceAvailable}} 元可用 + 满 {{item.priceAvailable / 100.0}} 元可用
diff --git a/order/order-application/src/main/java/cn/iocoder/mall/order/application/controller/users/UsersCartController.java b/order/order-application/src/main/java/cn/iocoder/mall/order/application/controller/users/UsersCartController.java index 7141ffbe6..0f2abf46d 100644 --- a/order/order-application/src/main/java/cn/iocoder/mall/order/application/controller/users/UsersCartController.java +++ b/order/order-application/src/main/java/cn/iocoder/mall/order/application/controller/users/UsersCartController.java @@ -11,6 +11,8 @@ import cn.iocoder.mall.order.application.convert.CartConvert; import cn.iocoder.mall.order.application.vo.UsersCalcSkuPriceVO; import cn.iocoder.mall.order.application.vo.UsersCartDetailVO; import cn.iocoder.mall.order.application.vo.UsersOrderConfirmCreateVO; +import cn.iocoder.mall.promotion.api.CouponService; +import cn.iocoder.mall.promotion.api.bo.CouponCardAvailableBO; import cn.iocoder.mall.user.sdk.context.UserSecurityContextHolder; import com.alibaba.dubbo.config.annotation.Reference; import org.springframework.web.bind.annotation.*; @@ -28,6 +30,8 @@ public class UsersCartController { private CartService cartService; @Reference(validation = "true") private OrderService orderService; + @Reference(validation = "true") + private CouponService couponService; @PostMapping("add") public CommonResult add(@RequestParam("skuId") Integer skuId, @@ -102,8 +106,9 @@ public class UsersCartController { @GetMapping("/confirm_create_order") public CommonResult getConfirmCreateOrder() { + Integer userId = UserSecurityContextHolder.getContext().getUserId(); // 获得购物车中选中的 - List cartItems = cartService.list(UserSecurityContextHolder.getContext().getUserId(), true).getData(); + List cartItems = cartService.list(userId, true).getData(); // 购物车为空时,构造空的 UsersOrderConfirmCreateVO 返回 if (cartItems.isEmpty()) { UsersOrderConfirmCreateVO result = new UsersOrderConfirmCreateVO(); @@ -116,8 +121,13 @@ public class UsersCartController { if (calcOrderPriceResult.isError()) { return CommonResult.error(calcOrderPriceResult); } + // 获得优惠劵 + CalcOrderPriceBO calcOrderPrice = calcOrderPriceResult.getData(); + List couponCards = couponService.getCouponCardList(userId, + CartConvert.INSTANCE.convertList(calcOrderPrice.getItemGroups())).getData(); // 执行数据拼装 - return CommonResult.success(CartConvert.INSTANCE.convert(calcOrderPriceResult.getData())); + return CommonResult.success(CartConvert.INSTANCE.convert(calcOrderPrice) + .setCouponCards(couponCards)); } private CommonResult list0(List cartItems) { diff --git a/order/order-application/src/main/java/cn/iocoder/mall/order/application/convert/CartConvert.java b/order/order-application/src/main/java/cn/iocoder/mall/order/application/convert/CartConvert.java index 2f78757bf..eec491ebe 100644 --- a/order/order-application/src/main/java/cn/iocoder/mall/order/application/convert/CartConvert.java +++ b/order/order-application/src/main/java/cn/iocoder/mall/order/application/convert/CartConvert.java @@ -5,9 +5,14 @@ import cn.iocoder.mall.order.api.bo.CalcSkuPriceBO; import cn.iocoder.mall.order.application.vo.UsersCalcSkuPriceVO; import cn.iocoder.mall.order.application.vo.UsersCartDetailVO; import cn.iocoder.mall.order.application.vo.UsersOrderConfirmCreateVO; +import cn.iocoder.mall.promotion.api.dto.CouponCardSpuDTO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + @Mapper public interface CartConvert { @@ -19,4 +24,17 @@ public interface CartConvert { UsersCalcSkuPriceVO convert2(CalcSkuPriceBO calcSkuPriceBO); + default List convertList(List itemGroups) { + List items = new ArrayList<>(); + itemGroups.forEach(itemGroup -> items.addAll(itemGroup.getItems().stream().map( + item -> new CouponCardSpuDTO() + .setSpuId(item.getSpu().getId()) + .setSkuId(item.getId()) + .setCategoryId(item.getSpu().getCid()) + .setPrice(item.getBuyPrice()) + .setQuantity(item.getBuyQuantity())) + .collect(Collectors.toList()))); + return items; + } + } diff --git a/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersCalcSkuPriceVO.java b/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersCalcSkuPriceVO.java index 65cdb6669..d8826ed7e 100644 --- a/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersCalcSkuPriceVO.java +++ b/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersCalcSkuPriceVO.java @@ -29,6 +29,6 @@ public class UsersCalcSkuPriceVO { /** * 最终价格,单位:分。 */ - private Integer presentPrice; + private Integer buyPrice; } diff --git a/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersCartDetailVO.java b/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersCartDetailVO.java index f63d3ad27..c34696f1a 100644 --- a/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersCartDetailVO.java +++ b/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersCartDetailVO.java @@ -36,25 +36,16 @@ public class UsersCartDetailVO { */ private PromotionActivityBO activity; // TODO 芋艿,偷懒 /** - * 优惠活动是否生效 + * 促销减少的金额 * - * 多个商品,参与某个活动,因为并发达到条件,所以会存在未生效的情况。所以一共有三种情况 - * - * 1. activity 非空,activityEffectEffective 为 true,参与活动,且生效 - * 2. activity 非空,activityEffectEffective 为 false ,参与活动,并未生效 - * 3. activity 为空,activityEffectEffective 为空,并未参与活动。 + * 1. 若未参与促销活动,或不满足促销条件,返回 null + * 2. 该金额,已经分摊到每个 Item 的 discountTotal ,需要注意。 */ - private Boolean activityEffectEffective; + private Integer activityDiscountTotal; /** * 商品数组 */ private List items; - /** - * 费用 - * - * TODO 芋艿,这里先偷懒,postageTotal 字段用不到。 - */ - private Fee fee; } @@ -103,15 +94,36 @@ public class UsersCartDetailVO { */ private PromotionActivityBO activity; /** - * 折扣价 + * 原始单价,单位:分。 */ - private Integer discountPrice; + private Integer originPrice; /** - * 费用 - * - * TODO 芋艿,这里先偷懒,postageTotal 字段用不到。 + * 购买单价,单位:分 */ - private Fee fee; + private Integer buyPrice; + /** + * 最终价格,单位:分。 + */ + private Integer presentPrice; + /** + * 购买总金额,单位:分 + * + * 用途类似 {@link #presentTotal} + */ + private Integer buyTotal; + /** + * 优惠总金额,单位:分。 + */ + private Integer discountTotal; + /** + * 最终总金额,单位:分。 + * + * 注意,presentPrice * quantity 不一定等于 presentTotal 。 + * 因为,存在无法整除的情况。 + * 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。 + * 所以,需要存储一个该字段。 + */ + private Integer presentTotal; } @@ -152,9 +164,9 @@ public class UsersCartDetailVO { public static class Fee { /** - * 总价 + * 购买总价 */ - private Integer originalTotal; + private Integer buyTotal; /** * 优惠总价 * @@ -175,8 +187,8 @@ public class UsersCartDetailVO { public Fee() { } - public Fee(Integer originalTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) { - this.originalTotal = originalTotal; + public Fee(Integer buyTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) { + this.buyTotal = buyTotal; this.discountTotal = discountTotal; this.postageTotal = postageTotal; this.presentTotal = presentTotal; diff --git a/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersOrderConfirmCreateVO.java b/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersOrderConfirmCreateVO.java index 3ab835a87..7d5981f30 100644 --- a/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersOrderConfirmCreateVO.java +++ b/order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersOrderConfirmCreateVO.java @@ -1,6 +1,7 @@ package cn.iocoder.mall.order.application.vo; import cn.iocoder.mall.product.api.bo.ProductAttrAndValuePairBO; +import cn.iocoder.mall.promotion.api.bo.CouponCardAvailableBO; import cn.iocoder.mall.promotion.api.bo.PromotionActivityBO; import lombok.Data; import lombok.experimental.Accessors; @@ -19,6 +20,10 @@ public class UsersOrderConfirmCreateVO { * 费用 */ private Fee fee; + /** + * 优惠劵列表 TODO 芋艿,后续改改 + */ + private List couponCards; /** * 商品分组 @@ -79,9 +84,36 @@ public class UsersOrderConfirmCreateVO { */ private Integer buyQuantity; /** - * 折扣价 + * 原始单价,单位:分。 */ - private Integer discountPrice; + private Integer originPrice; + /** + * 购买单价,单位:分 + */ + private Integer buyPrice; + /** + * 最终价格,单位:分。 + */ + private Integer presentPrice; + /** + * 购买总金额,单位:分 + * + * 用途类似 {@link #presentTotal} + */ + private Integer buyTotal; + /** + * 优惠总金额,单位:分。 + */ + private Integer discountTotal; + /** + * 最终总金额,单位:分。 + * + * 注意,presentPrice * quantity 不一定等于 presentTotal 。 + * 因为,存在无法整除的情况。 + * 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。 + * 所以,需要存储一个该字段。 + */ + private Integer presentTotal; } @@ -122,9 +154,9 @@ public class UsersOrderConfirmCreateVO { public static class Fee { /** - * 总价 + * 购买总价 */ - private Integer originalTotal; + private Integer buyTotal; /** * 优惠总价 * @@ -145,8 +177,8 @@ public class UsersOrderConfirmCreateVO { public Fee() { } - public Fee(Integer originalTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) { - this.originalTotal = originalTotal; + public Fee(Integer buyTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) { + this.buyTotal = buyTotal; this.discountTotal = discountTotal; this.postageTotal = postageTotal; this.presentTotal = presentTotal; diff --git a/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcOrderPriceBO.java b/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcOrderPriceBO.java index 8ecfe80c7..5ef38fcd5 100644 --- a/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcOrderPriceBO.java +++ b/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcOrderPriceBO.java @@ -20,6 +20,8 @@ public class CalcOrderPriceBO { private List itemGroups; /** * 邮费信息 + * + * TODO 芋艿,暂时未弄 */ private Postage postage; /** @@ -42,25 +44,22 @@ public class CalcOrderPriceBO { // TODO 芋艿,目前只会有【满减送】的情况,未来有新的促销方式,可能需要改成数组 private PromotionActivityBO activity; /** - * 优惠活动是否生效 + * 促销减少的金额 * - * 多个商品,参与某个活动,因为并发达到条件,所以会存在未生效的情况。所以一共有三种情况 - * - * 1. activity 非空,activityEffectEffective 为 true,参与活动,且生效 - * 2. activity 非空,activityEffectEffective 为 false ,参与活动,并未生效 - * 3. activity 为空,activityEffectEffective 为空,并未参与活动。 + * 1. 若未参与促销活动,或不满足促销条件,返回 null + * 2. 该金额,已经分摊到每个 Item 的 discountTotal ,需要注意。 */ - private Boolean activityEffectEffective; + private Integer activityDiscountTotal; /** * 商品数组 */ private List items; - /** - * 费用 - * - * TODO 芋艿,这里先偷懒,postageTotal 字段用不到。 - */ - private Fee fee; +// /** +// * 费用 +// * +// * TODO 芋艿,这里先偷懒,postageTotal 字段用不到。 +// */ +// private Fee fee; // 注释原因,不用这里了 } @@ -81,15 +80,36 @@ public class CalcOrderPriceBO { */ private PromotionActivityBO activity; /** - * 费用 - * - * TODO 芋艿,这里先偷懒,postageTotal 字段用不到。 + * 原始单价,单位:分。 */ - private Fee fee; + private Integer originPrice; /** - * 折扣价 + * 购买单价,单位:分 */ - private Integer discountPrice; + private Integer buyPrice; + /** + * 最终价格,单位:分。 + */ + private Integer presentPrice; + /** + * 购买总金额,单位:分 + * + * 用途类似 {@link #presentTotal} + */ + private Integer buyTotal; + /** + * 优惠总金额,单位:分。 + */ + private Integer discountTotal; + /** + * 最终总金额,单位:分。 + * + * 注意,presentPrice * quantity 不一定等于 presentTotal 。 + * 因为,存在无法整除的情况。 + * 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。 + * 所以,需要存储一个该字段。 + */ + private Integer presentTotal; } @@ -101,9 +121,9 @@ public class CalcOrderPriceBO { public static class Fee { /** - * 总价 + * 购买总价 */ - private Integer originalTotal; + private Integer buyTotal; /** * 优惠总价 * @@ -124,8 +144,8 @@ public class CalcOrderPriceBO { public Fee() { } - public Fee(Integer originalTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) { - this.originalTotal = originalTotal; + public Fee(Integer buyTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) { + this.buyTotal = buyTotal; this.discountTotal = discountTotal; this.postageTotal = postageTotal; this.presentTotal = presentTotal; diff --git a/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcSkuPriceBO.java b/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcSkuPriceBO.java index 4b554b925..ed835ff70 100644 --- a/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcSkuPriceBO.java +++ b/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcSkuPriceBO.java @@ -24,8 +24,8 @@ public class CalcSkuPriceBO { */ private Integer originalPrice; /** - * 最终价格,单位:分。 + * 购买价格,单位:分。 */ - private Integer presentPrice; + private Integer buyPrice; } diff --git a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderItemDO.java b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderItemDO.java index 295a75889..a096954a8 100644 --- a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderItemDO.java +++ b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderItemDO.java @@ -49,18 +49,62 @@ public class OrderItemDO extends DeletableDO { */ private Integer quantity; /** - * 价格(分) + * 商品成交单价(分) */ + @Deprecated private Integer price; /** * 支付金额(实付金额) */ + @Deprecated private Integer payAmount; /** * 物流金额 (分) */ + @Deprecated private Integer logisticsPrice; + /** + * 原始单价,单位:分。 + */ + private Integer originPrice; + /** + * 购买单价,单位:分 + */ + private Integer buyPrice; + /** + * 最终价格,单位:分。 + */ + private Integer presentPrice; + /** + * 购买总金额,单位:分 + * + * 用途类似 {@link #presentTotal} + */ + private Integer buyTotal; + /** + * 优惠总金额,单位:分。 + */ + private Integer discountTotal; + /** + * 最终总金额,单位:分。 + * + * 注意,presentPrice * quantity 不一定等于 presentTotal 。 + * 因为,存在无法整除的情况。 + * 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。 + * 所以,需要存储一个该字段。 + */ + private Integer presentTotal; + // 如上字段,举个例子: + // 假设购买三个,即 quantity = 3 。 + // originPrice = 15 + // 使用限时折扣(单品优惠)8 折,buyPrice = 12 + // 开始算总的价格 + // buyTotal = buyPrice * quantity = 12 * 3 = 36 + // discountTotal ,假设有满减送(分组优惠)满 20 减 10 ,并且使用优惠劵满 1.01 减 1 ,则 discountTotal = 10 + 1 = 11 + // presentTotal = buyTotal - discountTotal = 24 - 11 = 13 + // 最终 presentPrice = presentTotal / quantity = 13 / 3 = 4.33 + /// /// 时间信息 diff --git a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderPreferentialDO.java b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderPreferentialDO.java new file mode 100644 index 000000000..b7b06cf42 --- /dev/null +++ b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderPreferentialDO.java @@ -0,0 +1,46 @@ +package cn.iocoder.mall.order.biz.dataobject; + +/** + * 订单优惠明细 + */ +// TODO 芋艿 后续在完善 +public class OrderPreferentialDO { + + /** + * 编号 + */ + private Integer id; + /** + * 类型 + * + * 1 - 促销活动 + * 2 - 优惠劵 + */ + private Integer type; + // TODO 芋艿 优惠劵编号 or 促销活动编号 + /** + * 订单编号 + */ + private Integer orderId; + /** + * 商品 SPU 编号 + */ + private Integer spuId; + /** + * 商品 SKU 编号 + */ + private Integer skuId; + /** + * 商品数量 + */ + private Integer quantity; + /** + * 传入时的价格 + */ + private Integer originTotal; + /** + * 总优惠价格 + */ + private Integer discountTotal; + +} diff --git a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/package-info.java b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/package-info.java deleted file mode 100644 index 289015993..000000000 --- a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * @author Sin - * @time 2019-03-16 13:49 - */ -package cn.iocoder.mall.order.biz; \ No newline at end of file diff --git a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/CartServiceImpl.java b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/CartServiceImpl.java index c899254f5..f6c54f887 100644 --- a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/CartServiceImpl.java +++ b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/CartServiceImpl.java @@ -178,17 +178,17 @@ public class CartServiceImpl implements CartService { List itemGroups = groupByFullPrivilege(items, activityList); calcOrderPriceBO.setItemGroups(itemGroups); // 4. 计算最终的价格 - Integer originalTotal = 0; - Integer presentTotal = 0; - Integer discountTotal = 0; + int buyTotal = 0; + int discountTotal = 0; + int presentTotal = 0; for (CalcOrderPriceBO.ItemGroup itemGroup : calcOrderPriceBO.getItemGroups()) { - originalTotal += itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getFee().getOriginalTotal() : 0).sum(); - discountTotal += itemGroup.getFee().getDiscountTotal() + itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getFee().getDiscountTotal() : 0).sum(); - presentTotal += itemGroup.getFee().getPresentTotal(); + buyTotal += itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getBuyTotal() : 0).sum(); + discountTotal += itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getDiscountTotal() : 0).sum(); + presentTotal += itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getPresentTotal() : 0).sum(); } - Assert.isTrue(originalTotal - discountTotal == presentTotal, - String.format("价格合计( %d - %d == %d )不正确", originalTotal, discountTotal, presentTotal)); - calcOrderPriceBO.setFee(new CalcOrderPriceBO.Fee(originalTotal, discountTotal, 0, presentTotal)); + Assert.isTrue(buyTotal - discountTotal == presentTotal, + String.format("价格合计( %d - %d == %d )不正确", buyTotal, discountTotal, presentTotal)); + calcOrderPriceBO.setFee(new CalcOrderPriceBO.Fee(buyTotal, discountTotal, 0, presentTotal)); // 返回 return CommonResult.success(calcOrderPriceBO); } @@ -215,7 +215,7 @@ public class CartServiceImpl implements CartService { // 如果无促销活动,则直接返回默认结果即可 List activityList = activityListResult.getData(); if (activityList.isEmpty()) { - return CommonResult.success(new CalcSkuPriceBO().setOriginalPrice(sku.getPrice()).setPresentPrice(sku.getPrice())); + return CommonResult.success(new CalcSkuPriceBO().setOriginalPrice(sku.getPrice()).setBuyPrice(sku.getPrice())); } // 如果有促销活动,则开始做计算 TODO 芋艿,因为现在暂时只有限时折扣 + 满减送。所以写的比较简单先 PromotionActivityBO fullPrivilege = findPromotionActivityByType(activityList, PromotionActivityTypeEnum.FULL_PRIVILEGE); @@ -223,7 +223,7 @@ public class CartServiceImpl implements CartService { Integer presentPrice = calcSkuPriceByTimeLimitDiscount(sku, timeLimitedDiscount); // 返回结果 return CommonResult.success(new CalcSkuPriceBO().setFullPrivilege(fullPrivilege).setTimeLimitedDiscount(timeLimitedDiscount) - .setOriginalPrice(sku.getPrice()).setPresentPrice(presentPrice)); + .setOriginalPrice(sku.getPrice()).setBuyPrice(presentPrice)); } private List initCalcOrderPriceItems(List skus, @@ -237,10 +237,12 @@ public class CartServiceImpl implements CartService { item.setSelected(calcOrderItem.getSelected()); item.setBuyQuantity(calcOrderItem.getQuantity()); // 计算初始价格 - CalcOrderPriceBO.Fee fee = new CalcOrderPriceBO.Fee(0, 0, 0, 0); - fee.setOriginalTotal(item.getPrice() * item.getBuyQuantity()); - fee.setPresentTotal(fee.getOriginalTotal()); - item.setFee(fee); + item.setOriginPrice(sku.getPrice()); + item.setBuyPrice(sku.getPrice()); + item.setPresentPrice(sku.getPrice()); + item.setBuyTotal(sku.getPrice() * calcOrderItem.getQuantity()); + item.setDiscountTotal(0); + item.setPresentTotal(item.getBuyTotal()); } return items; } @@ -264,10 +266,10 @@ public class CartServiceImpl implements CartService { // 设置优惠 item.setActivity(timeLimitedDiscount); // 设置价格 - item.setDiscountPrice(newPrice); - CalcOrderPriceBO.Fee fee = item.getFee(); - fee.setDiscountTotal(fee.getDiscountTotal() + (item.getPrice() - newPrice) * item.getBuyQuantity()); - fee.setPresentTotal(fee.getOriginalTotal() - fee.getDiscountTotal() + fee.getPostageTotal()); + item.setBuyPrice(newPrice); + item.setBuyTotal(newPrice * item.getBuyQuantity()); + item.setPresentTotal(item.getBuyTotal() - item.getDiscountTotal()); + item.setPresentPrice(item.getPresentTotal() / item.getBuyQuantity()); } } @@ -302,14 +304,11 @@ public class CartServiceImpl implements CartService { } // 处理未参加活动的商品,形成一个分组 if (!items.isEmpty()) { - CalcOrderPriceBO.ItemGroup itemGroup = new CalcOrderPriceBO.ItemGroup() - .setItems(items); - itemGroups.add(itemGroup); + itemGroups.add(new CalcOrderPriceBO.ItemGroup().setItems(items)); } // 计算每个分组的价格 for (CalcOrderPriceBO.ItemGroup itemGroup : itemGroups) { - itemGroup.setFee(calcSkuPriceByFullPrivilege(itemGroup)); - itemGroup.setActivityEffectEffective(itemGroup.getFee().getDiscountTotal() > 0); + itemGroup.setActivityDiscountTotal(calcSkuPriceByFullPrivilege(itemGroup)); } // 返回结果 return itemGroups; @@ -346,17 +345,18 @@ public class CartServiceImpl implements CartService { throw new IllegalArgumentException(String.format("折扣活动(%s) 的优惠类型不正确", timeLimitedDiscount.toString())); } - private CalcOrderPriceBO.Fee calcSkuPriceByFullPrivilege(CalcOrderPriceBO.ItemGroup itemGroup) { + private Integer calcSkuPriceByFullPrivilege(CalcOrderPriceBO.ItemGroup itemGroup) { if (itemGroup.getActivity() == null) { - Integer originalTotal = itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getFee().getPresentTotal() : 0).sum(); - return new CalcOrderPriceBO.Fee(originalTotal, 0, 0, originalTotal); + return null; } PromotionActivityBO activity = itemGroup.getActivity(); Assert.isTrue(PromotionActivityTypeEnum.FULL_PRIVILEGE.getValue().equals(activity.getActivityType()), "传入的必须的满减送活动必须是满减送"); // 获得优惠信息 - Integer itemCnt = itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getBuyQuantity() : 0).sum(); - Integer originalTotal = itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getFee().getPresentTotal() : 0).sum(); + List items = itemGroup.getItems().stream().filter(item -> !item.getSelected()) + .collect(Collectors.toList()); + Integer itemCnt = items.stream().mapToInt(CalcOrderPriceBO.Item::getBuyQuantity).sum(); + Integer originalTotal = items.stream().mapToInt(CalcOrderPriceBO.Item::getPresentTotal).sum(); List privileges = activity.getFullPrivilege().getPrivileges().stream() .filter(privilege -> { if (MeetTypeEnum.PRICE.getValue().equals(privilege.getMeetType())) { @@ -369,7 +369,7 @@ public class CartServiceImpl implements CartService { }).collect(Collectors.toList()); // 获得不到优惠信息,返回原始价格 if (privileges.isEmpty()) { - return new CalcOrderPriceBO.Fee(originalTotal, 0, 0, originalTotal); + return null; } // 获得到优惠信息,进行价格计算 PromotionActivityBO.FullPrivilege.Privilege privilege = privileges.get(privileges.size() - 1); @@ -393,7 +393,26 @@ public class CartServiceImpl implements CartService { } else { throw new IllegalArgumentException(String.format("满减送促销(%s) 的优惠类型不正确", activity.toString())); } - return new CalcOrderPriceBO.Fee(originalTotal, originalTotal - presentTotal, 0, presentTotal); + Integer discountTotal = originalTotal - presentTotal; + if (discountTotal == 0) { + return null; + } + // 按比例,拆分 presentTotal + for (int i = 0; i < items.size(); i++) { + CalcOrderPriceBO.Item item = items.get(i); + Integer discountPart; + if (i < items.size() - 1) { // 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减 + discountPart = (int) (discountTotal * (1.0D * item.getPresentTotal() / presentTotal)); + discountTotal -= discountPart; + } else { + discountPart = discountTotal; + } + Assert.isTrue(discountPart > 0, "优惠金额必须大于 0"); + item.setDiscountTotal(item.getDiscountTotal() + discountPart); + item.setPresentTotal(item.getBuyTotal() - item.getDiscountTotal()); + item.setPresentPrice(item.getPresentTotal() / item.getBuyQuantity()); + } + return originalTotal - presentTotal; } private PromotionActivityBO findPromotionActivityByType(List activityList, PromotionActivityTypeEnum type) { diff --git a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java index f85655c55..6867b13a4 100644 --- a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java +++ b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java @@ -212,6 +212,8 @@ public class OrderServiceImpl implements OrderService { return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_GET_GOODS_INFO_INCORRECT.getCode()); } + // + // 设置 orderItem Map productSpuBOMap = productResult.getData() @@ -293,7 +295,7 @@ public class OrderServiceImpl implements OrderService { .setDeleted(DeletedStatusEnum.DELETED_NO.getValue()) .setCreateTime(new Date()) .setUpdateTime(null); - orderItemMapper.insert(orderItemDO); + orderItemMapper.insert(orderItemDO); // TODO 芋艿,需要改成一次性插入 }); // 创建预订单 diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/package-info.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/package-info.java deleted file mode 100644 index a8c2c99b9..000000000 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.mall.pay.biz.mq; \ No newline at end of file diff --git a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/package-info.java b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/package-info.java deleted file mode 100644 index ce84a3085..000000000 --- a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.mall.product; \ No newline at end of file diff --git a/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/CouponService.java b/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/CouponService.java index 7101a8db5..ca12c3b85 100644 --- a/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/CouponService.java +++ b/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/CouponService.java @@ -2,13 +2,12 @@ package cn.iocoder.mall.promotion.api; import cn.iocoder.common.framework.validator.InEnum; import cn.iocoder.common.framework.vo.CommonResult; -import cn.iocoder.mall.promotion.api.bo.CouponCardBO; -import cn.iocoder.mall.promotion.api.bo.CouponCardPageBO; -import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO; -import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO; +import cn.iocoder.mall.promotion.api.bo.*; import cn.iocoder.mall.promotion.api.constant.CouponTemplateStatusEnum; import cn.iocoder.mall.promotion.api.dto.*; +import java.util.List; + public interface CouponService { // ========== 优惠劵(码)模板 ========== @@ -93,6 +92,17 @@ public interface CouponService { */ CommonResult cancelUseCouponCard(Integer userId, Integer couponCardId); + /** + * 获得用户所有优惠劵,并标明是否可用 + * + * 注意,spus 是作为条件,判断优惠劵是否可用 + * + * @param userId 用户编号 + * @param spus 匹配的商品/分类 + * @return 优惠劵列表 + */ + CommonResult> getCouponCardList(Integer userId, List spus); + // ========== 优惠码 ========== /** diff --git a/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/bo/CouponCardAvailableBO.java b/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/bo/CouponCardAvailableBO.java new file mode 100644 index 000000000..bae8718c8 --- /dev/null +++ b/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/bo/CouponCardAvailableBO.java @@ -0,0 +1,24 @@ +package cn.iocoder.mall.promotion.api.bo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 可用优惠劵 BO + * + * 注意,如果优惠劵不可用,标记 available = false ,并写明 unavailableReason 原因 + */ +@Data +@Accessors(chain = true) +public class CouponCardAvailableBO extends CouponCardBO { + + /** + * 是否可用 + */ + private Boolean available; + /** + * 不可用原因 + */ + private String unavailableReason; + +} diff --git a/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/dto/CouponCardSpuDTO.java b/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/dto/CouponCardSpuDTO.java new file mode 100644 index 000000000..d3799e2dd --- /dev/null +++ b/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/dto/CouponCardSpuDTO.java @@ -0,0 +1,39 @@ +package cn.iocoder.mall.promotion.api.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * 优惠劵商品 DTO + * + * 主要用于 {@link cn.iocoder.mall.promotion.api.CouponService#getCouponCardList(Integer, List)} + */ +@Data +@Accessors(chain = true) +public class CouponCardSpuDTO implements Serializable { + + /** + * 商品 SPU 编号 + */ + private Integer spuId; + /** + * 商品 SKU 编号 + */ + private Integer skuId; + /** + * 分类编号 + */ + private Integer categoryId; + /** + * 价格 + */ + private Integer price; + /** + * 数量 + */ + private Integer quantity; + +} diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/convert/CouponCardConvert.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/convert/CouponCardConvert.java index 81b211446..f66807fe8 100644 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/convert/CouponCardConvert.java +++ b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/convert/CouponCardConvert.java @@ -1,5 +1,6 @@ package cn.iocoder.mall.promotion.biz.convert; +import cn.iocoder.mall.promotion.api.bo.CouponCardAvailableBO; import cn.iocoder.mall.promotion.api.bo.CouponCardBO; import cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO; import org.mapstruct.Mapper; @@ -22,4 +23,7 @@ public interface CouponCardConvert { @Mappings({}) CouponCardBO convert(CouponCardDO card); + @Mappings({}) + CouponCardAvailableBO convert2(CouponCardDO card, boolean x); // TODO 芋艿,临时用来解决 mapstruct 无法正确匹配方法的问题 + } diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java index af4b697ec..84bba8ac3 100644 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java +++ b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java @@ -11,6 +11,9 @@ public interface CouponCardMapper { CouponCardDO selectById(@Param("id") Integer id); + List selectListByUserIdAndStatus(@Param("userId") Integer userId, + @Param("status") Integer status); + List selectListByPage(@Param("userId") Integer userId, @Param("status") Integer status, @Param("offset") Integer offset, diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponTemplateMapper.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponTemplateMapper.java index 23195949c..a6d727609 100644 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponTemplateMapper.java +++ b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponTemplateMapper.java @@ -4,6 +4,7 @@ import cn.iocoder.mall.promotion.biz.dataobject.CouponTemplateDO; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; +import java.util.Collection; import java.util.List; @Repository @@ -11,6 +12,8 @@ public interface CouponTemplateMapper { CouponTemplateDO selectById(@Param("id") Integer id); + List selectListByIds(@Param("ids") Collection ids); + List selectListByPage(@Param("type") Integer type, @Param("title") String title, @Param("status") Integer status, diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/package-info.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/package-info.java deleted file mode 100644 index a52b7b5d9..000000000 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.mall.promotion.biz; \ No newline at end of file diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java index 9312e32e2..b690dddb6 100644 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java +++ b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java @@ -3,12 +3,10 @@ package cn.iocoder.mall.promotion.biz.service; import cn.iocoder.common.framework.constant.SysErrorCodeEnum; import cn.iocoder.common.framework.util.DateUtil; import cn.iocoder.common.framework.util.ServiceExceptionUtil; +import cn.iocoder.common.framework.util.StringUtil; import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.mall.promotion.api.CouponService; -import cn.iocoder.mall.promotion.api.bo.CouponCardBO; -import cn.iocoder.mall.promotion.api.bo.CouponCardPageBO; -import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO; -import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO; +import cn.iocoder.mall.promotion.api.bo.*; import cn.iocoder.mall.promotion.api.constant.*; import cn.iocoder.mall.promotion.api.dto.*; import cn.iocoder.mall.promotion.biz.convert.CouponCardConvert; @@ -22,8 +20,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Calendar; -import java.util.Date; +import java.util.*; +import java.util.stream.Collectors; @Service // 实际上不用添加。添加的原因是,必须 Spring 报错提示 @com.alibaba.dubbo.config.annotation.Service(validation = "true") @@ -252,6 +250,23 @@ public class CouponServiceImpl implements CouponService { return null; } + @Override + public CommonResult> getCouponCardList(Integer userId, List spus) { + // 查询用户未使用的优惠劵列表 + List cards = couponCardMapper.selectListByUserIdAndStatus(userId, CouponCardStatusEnum.UNUSED.getValue()); + Map templates = couponTemplateMapper.selectListByIds(cards.stream().map(CouponCardDO::getTemplateId).collect(Collectors.toSet())) + .stream().collect(Collectors.toMap(CouponTemplateDO::getId, template -> template)); + // 逐个判断是否可用 + List availableCards = cards.stream().map(card -> { + CouponCardAvailableBO availableCard = CouponCardConvert.INSTANCE.convert2(card, true); + availableCard.setUnavailableReason(isMatch(card, templates.get(card.getTemplateId()), spus)); + availableCard.setAvailable(availableCard.getUnavailableReason() == null); + return availableCard; + }).collect(Collectors.toList()); + // 返回结果 + return CommonResult.success(availableCards); + } + private void setCouponCardValidTime(CouponCardDO card, CouponTemplateDO template) { if (CouponTemplateDateTypeEnum.FIXED_DATE.getValue().equals(template.getDateType())) { card.setValidStartTime(template.getValidStartTime()).setValidEndTime(template.getValidEndTime()); @@ -263,6 +278,35 @@ public class CouponServiceImpl implements CouponService { } } + // 如果匹配,则返回 null 即可。 + private String isMatch(CouponCardDO card, CouponTemplateDO template, List spus) { + int totalPrice = 0; + if (RangeTypeEnum.ALL.getValue().equals(template.getRangeType())) { + totalPrice = spus.stream().mapToInt(spu -> spu.getPrice() * spu.getQuantity()).sum(); + } else if (RangeTypeEnum.PRODUCT_INCLUDE_PART.getValue().equals(template.getRangeType())) { + List spuIds = StringUtil.splitToInt(template.getRangeValues(), ","); + totalPrice = spus.stream().mapToInt(spu -> spuIds.contains(spu.getSpuId()) ? spu.getPrice() * spu.getQuantity() : 0).sum(); + } else if (RangeTypeEnum.PRODUCT_EXCLUDE_PART.getValue().equals(template.getRangeType())) { + List spuIds = StringUtil.splitToInt(template.getRangeValues(), ","); + totalPrice = spus.stream().mapToInt(spu -> !spuIds.contains(spu.getSpuId()) ? spu.getPrice() * spu.getQuantity() : 0).sum(); + } else if (RangeTypeEnum.CATEGORY_INCLUDE_PART.getValue().equals(template.getRangeType())) { + List spuIds = StringUtil.splitToInt(template.getRangeValues(), ","); + totalPrice = spus.stream().mapToInt(spu -> spuIds.contains(spu.getCategoryId()) ? spu.getPrice() * spu.getQuantity() : 0).sum(); + } else if (RangeTypeEnum.CATEGORY_EXCLUDE_PART.getValue().equals(template.getRangeType())) { + List spuIds = StringUtil.splitToInt(template.getRangeValues(), ","); + totalPrice = spus.stream().mapToInt(spu -> !spuIds.contains(spu.getCategoryId()) ? spu.getPrice() * spu.getQuantity() : 0).sum(); + } + // 总价为 0 时,说明优惠劵丫根不匹配 + if (totalPrice == 0) { + return "优惠劵不匹配"; + } + // 如果不满足金额 + if (totalPrice < card.getPriceAvailable()) { + return String.format("差 %1$,.2f 元可用优惠劵", (card.getPriceAvailable() - totalPrice) / 100D); + } + return null; + } + // ========== 优惠码 ========== @Override diff --git a/promotion/promotion-service-impl/src/main/resources/mapper/CouponCardMapper.xml b/promotion/promotion-service-impl/src/main/resources/mapper/CouponCardMapper.xml index 78e26005a..720f97944 100644 --- a/promotion/promotion-service-impl/src/main/resources/mapper/CouponCardMapper.xml +++ b/promotion/promotion-service-impl/src/main/resources/mapper/CouponCardMapper.xml @@ -33,6 +33,20 @@ WHERE id = #{id} + + + +