parent
8962631b6a
commit
7277ecb2d4
|
@ -1 +0,0 @@
|
||||||
package cn.iocoder.mall.admin;
|
|
|
@ -16,7 +16,6 @@ export function getProductRecommendList() {
|
||||||
url: '/promotion-api/users/product_recommend/list',
|
url: '/promotion-api/users/product_recommend/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: {
|
params: {
|
||||||
id,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import App from './App.vue';
|
||||||
import VueLazyload from 'vue-lazyload'
|
import VueLazyload from 'vue-lazyload'
|
||||||
import components from './config/components.js';
|
import components from './config/components.js';
|
||||||
import { Dialog } from 'vant';
|
import { Dialog } from 'vant';
|
||||||
|
import { CouponCell, CouponList } from 'vant';
|
||||||
|
|
||||||
import { formatDate } from './utils/date.js';
|
import { formatDate } from './utils/date.js';
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@ Vue.use(components);
|
||||||
|
|
||||||
Vue.use(VueLazyload);
|
Vue.use(VueLazyload);
|
||||||
Vue.use(Dialog);
|
Vue.use(Dialog);
|
||||||
|
Vue.use(CouponCell).use(CouponList);
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
router,
|
router,
|
||||||
|
|
|
@ -133,13 +133,14 @@ export default {
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
|
|
||||||
formatItemGroupDiscountPriceText() {
|
formatItemGroupDiscountPriceText() {
|
||||||
let price = 0;
|
// let price = 0;
|
||||||
for (let i in this.itemGroups) {
|
// for (let i in this.itemGroups) {
|
||||||
let itemGroup = this.itemGroups[i];
|
// let itemGroup = this.itemGroups[i];
|
||||||
price += itemGroup.fee.discountTotal;
|
// price += itemGroup.activityDiscountTotal || 0;
|
||||||
}
|
// }
|
||||||
return price > 0 ? '立减 ' + price / 100.0 + ' 元' : '';
|
return this.fee.discountTotal > 0 ? '立减 ' + this.fee.discountTotal / 100.0 + ' 元' : '';
|
||||||
},
|
},
|
||||||
|
|
||||||
calCheckedItemIds() {
|
calCheckedItemIds() {
|
||||||
|
@ -226,7 +227,7 @@ export default {
|
||||||
return {
|
return {
|
||||||
...item.spu,
|
...item.spu,
|
||||||
quantity: item.buyQuantity,
|
quantity: item.buyQuantity,
|
||||||
price: item.discountPrice || item.price,
|
price: item.buyPrice || item.price,
|
||||||
sku: {
|
sku: {
|
||||||
...item,
|
...item,
|
||||||
spu: undefined,
|
spu: undefined,
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
<!-- TODO 这里需要优化下,芋艿 -->
|
<!-- TODO 这里需要优化下,芋艿 -->
|
||||||
<van-cell-group>
|
<van-cell-group>
|
||||||
<van-cell>
|
<van-cell>
|
||||||
<div v-if="calSkuPriceResult.originalPrice && calSkuPriceResult.originalPrice !== calSkuPriceResult.presentPrice">
|
<div v-if="calSkuPriceResult.originalPrice && calSkuPriceResult.originalPrice !== calSkuPriceResult.buyPrice">
|
||||||
<span class="goods-price">{{ formatPrice(calSkuPriceResult.presentPrice) }}</span>
|
<span class="goods-price">{{ formatPrice(calSkuPriceResult.buyPrice) }}</span>
|
||||||
<span class="goods-market-price">{{ formatPrice(calSkuPriceResult.originalPrice) }}</span>
|
<span class="goods-market-price">{{ formatPrice(calSkuPriceResult.originalPrice) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
|
@ -283,7 +283,7 @@
|
||||||
for (let i in this.vanSku.list) {
|
for (let i in this.vanSku.list) {
|
||||||
let sku = this.vanSku.list[i];
|
let sku = this.vanSku.list[i];
|
||||||
if (sku.id === skuId) {
|
if (sku.id === skuId) {
|
||||||
sku.price = data.presentPrice;
|
sku.price = data.buyPrice;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,21 +43,36 @@
|
||||||
/>
|
/>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
<div style="height:15px;"></div>
|
<div style="height:15px;"></div>
|
||||||
<van-cell-group class="total">
|
|
||||||
<van-cell title="优惠券" is-link value="抵扣¥5.00"/>
|
|
||||||
</van-cell-group>
|
<!-- 优惠券单元格 -->
|
||||||
|
<van-coupon-cell
|
||||||
|
:coupons="coupons"
|
||||||
|
:chosen-coupon="chosenCoupon"
|
||||||
|
@click="showCouponPopup = true"
|
||||||
|
/>
|
||||||
|
<!-- 优惠券列表 -->
|
||||||
|
<van-popup v-model="showCouponPopup" position="bottom">
|
||||||
|
<van-coupon-list
|
||||||
|
:coupons="coupons"
|
||||||
|
:chosen-coupon="chosenCoupon"
|
||||||
|
:disabled-coupons="disabledCoupons"
|
||||||
|
@change="onCouponChange"
|
||||||
|
@exchange="onCouponExchange"
|
||||||
|
/>
|
||||||
|
</van-popup>
|
||||||
|
|
||||||
<div style="height:15px;"></div>
|
<div style="height:15px;"></div>
|
||||||
<van-cell-group class="total">
|
<van-cell-group class="total">
|
||||||
<van-cell title="商品总额" :value="fee.originalTotal"/>
|
<van-cell title="商品总额" :value="fee.buyTotal / 100.0"/>
|
||||||
<van-cell title="运费" :value="+ fee.postageTotal"/>
|
<van-cell title="运费" :value="+ fee.postageTotal / 100.0"/>
|
||||||
<van-cell title="折扣" :value="- fee.discountTotal"/>
|
<van-cell title="折扣" :value="- fee.discountTotal / 100.0"/>
|
||||||
<van-cell title="实付金额" :value="fee.presentTotal" style="font-weight: 700;"/>
|
<van-cell title="实付金额" :value="fee.presentTotal / 100.0" style="font-weight: 700;"/>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
|
|
||||||
<div style="height:50px;"></div>
|
<div style="height:50px;"></div>
|
||||||
<van-submit-bar
|
<van-submit-bar
|
||||||
:price="3050"
|
:price="fee.presentTotal"
|
||||||
button-text="提交订单"
|
button-text="提交订单"
|
||||||
label='实付金额:'
|
label='实付金额:'
|
||||||
@submit="onSubmit"
|
@submit="onSubmit"
|
||||||
|
@ -75,7 +90,8 @@
|
||||||
createOrderFromCart
|
createOrderFromCart
|
||||||
} from '../../api/order';
|
} from '../../api/order';
|
||||||
import {GetDefaultAddress} from '../../api/user';
|
import {GetDefaultAddress} from '../../api/user';
|
||||||
import orderStore from '../../store/order'
|
import orderStore from '../../store/order';
|
||||||
|
import { Dialog } from 'vant';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
|
@ -89,6 +105,8 @@
|
||||||
addressData: {
|
addressData: {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 商品 + 促销相关
|
||||||
itemGroups: [],
|
itemGroups: [],
|
||||||
fee: {
|
fee: {
|
||||||
originalTotal: undefined,
|
originalTotal: undefined,
|
||||||
|
@ -96,12 +114,36 @@
|
||||||
postageTotal: undefined,
|
postageTotal: undefined,
|
||||||
presentTotal: undefined,
|
presentTotal: undefined,
|
||||||
},
|
},
|
||||||
products: [],
|
// products: [], // 应该没用了
|
||||||
|
|
||||||
|
// 优惠劵相关
|
||||||
|
showCouponPopup: false,
|
||||||
|
coupons: [],
|
||||||
|
disabledCoupons: [],
|
||||||
|
chosenCoupon: -1,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
onCouponChange(a, b, c) {
|
||||||
|
debugger;
|
||||||
|
},
|
||||||
|
onCouponExchange(a, b, c) {
|
||||||
|
Dialog.alert({
|
||||||
|
title: '系统提示',
|
||||||
|
message: '暂未开发', // TODO 芋艿
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
const userAddressId = this.addressData.id;
|
const userAddressId = this.addressData.id;
|
||||||
|
if (!userAddressId) {
|
||||||
|
Dialog.alert({
|
||||||
|
title: '系统提示',
|
||||||
|
message: '请选择收获地址',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const remark = '';
|
const remark = '';
|
||||||
|
|
||||||
if (this.from === 'direct_order') {
|
if (this.from === 'direct_order') {
|
||||||
|
@ -116,7 +158,7 @@
|
||||||
remark,
|
remark,
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
const { orderNo } = result;
|
// const { orderNo } = result;
|
||||||
this.$router.push({ //核心语句
|
this.$router.push({ //核心语句
|
||||||
path:`/order/success`, //跳转的路径
|
path:`/order/success`, //跳转的路径
|
||||||
query:{ //路由传参时push和query搭配使用 ,作用时传递参数
|
query:{ //路由传参时push和query搭配使用 ,作用时传递参数
|
||||||
|
@ -128,7 +170,7 @@
|
||||||
} else if (this.from === 'cart') {
|
} else if (this.from === 'cart') {
|
||||||
createOrderFromCart(userAddressId, remark).then(result => {
|
createOrderFromCart(userAddressId, remark).then(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
const { orderNo } = result;
|
// const { orderNo } = result;
|
||||||
this.$router.push({ //核心语句
|
this.$router.push({ //核心语句
|
||||||
path:`/order/success`, //跳转的路径
|
path:`/order/success`, //跳转的路径
|
||||||
query:{ //路由传参时push和query搭配使用 ,作用时传递参数
|
query:{ //路由传参时push和query搭配使用 ,作用时传递参数
|
||||||
|
@ -140,16 +182,34 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
convertProduct(item) {
|
convertProduct(item) {
|
||||||
// debugger;
|
|
||||||
return {
|
return {
|
||||||
...item.spu,
|
...item.spu,
|
||||||
quantity: item.buyQuantity,
|
quantity: item.buyQuantity,
|
||||||
price: item.price,
|
price: item.buyPrice || item.price,
|
||||||
sku: {
|
sku: {
|
||||||
...item,
|
...item,
|
||||||
spu: undefined,
|
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() {
|
mounted: function() {
|
||||||
|
@ -166,11 +226,19 @@
|
||||||
getOrderConfirmCreateOrder(this.skuId, this.quantity).then(data => {
|
getOrderConfirmCreateOrder(this.skuId, this.quantity).then(data => {
|
||||||
this.itemGroups = data.itemGroups;
|
this.itemGroups = data.itemGroups;
|
||||||
this.fee = data.fee;
|
this.fee = data.fee;
|
||||||
|
// 获得优惠劵列表
|
||||||
})
|
})
|
||||||
} else if (this.from === 'cart') {
|
} else if (this.from === 'cart') {
|
||||||
getCartConfirmCreateOrder().then(data => {
|
getCartConfirmCreateOrder().then(data => {
|
||||||
this.itemGroups = data.itemGroups;
|
this.itemGroups = data.itemGroups;
|
||||||
this.fee = data.fee;
|
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;
|
||||||
|
}));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
<span class="amountSign">折</span>
|
<span class="amountSign">折</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="condition">
|
<div class="condition">
|
||||||
<span>满 {{item.priceAvailable}} 元可用</span>
|
<span>满 {{item.priceAvailable / 100.0}} 元可用</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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.UsersCalcSkuPriceVO;
|
||||||
import cn.iocoder.mall.order.application.vo.UsersCartDetailVO;
|
import cn.iocoder.mall.order.application.vo.UsersCartDetailVO;
|
||||||
import cn.iocoder.mall.order.application.vo.UsersOrderConfirmCreateVO;
|
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 cn.iocoder.mall.user.sdk.context.UserSecurityContextHolder;
|
||||||
import com.alibaba.dubbo.config.annotation.Reference;
|
import com.alibaba.dubbo.config.annotation.Reference;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
@ -28,6 +30,8 @@ public class UsersCartController {
|
||||||
private CartService cartService;
|
private CartService cartService;
|
||||||
@Reference(validation = "true")
|
@Reference(validation = "true")
|
||||||
private OrderService orderService;
|
private OrderService orderService;
|
||||||
|
@Reference(validation = "true")
|
||||||
|
private CouponService couponService;
|
||||||
|
|
||||||
@PostMapping("add")
|
@PostMapping("add")
|
||||||
public CommonResult<Integer> add(@RequestParam("skuId") Integer skuId,
|
public CommonResult<Integer> add(@RequestParam("skuId") Integer skuId,
|
||||||
|
@ -102,8 +106,9 @@ public class UsersCartController {
|
||||||
|
|
||||||
@GetMapping("/confirm_create_order")
|
@GetMapping("/confirm_create_order")
|
||||||
public CommonResult<UsersOrderConfirmCreateVO> getConfirmCreateOrder() {
|
public CommonResult<UsersOrderConfirmCreateVO> getConfirmCreateOrder() {
|
||||||
|
Integer userId = UserSecurityContextHolder.getContext().getUserId();
|
||||||
// 获得购物车中选中的
|
// 获得购物车中选中的
|
||||||
List<CartItemBO> cartItems = cartService.list(UserSecurityContextHolder.getContext().getUserId(), true).getData();
|
List<CartItemBO> cartItems = cartService.list(userId, true).getData();
|
||||||
// 购物车为空时,构造空的 UsersOrderConfirmCreateVO 返回
|
// 购物车为空时,构造空的 UsersOrderConfirmCreateVO 返回
|
||||||
if (cartItems.isEmpty()) {
|
if (cartItems.isEmpty()) {
|
||||||
UsersOrderConfirmCreateVO result = new UsersOrderConfirmCreateVO();
|
UsersOrderConfirmCreateVO result = new UsersOrderConfirmCreateVO();
|
||||||
|
@ -116,8 +121,13 @@ public class UsersCartController {
|
||||||
if (calcOrderPriceResult.isError()) {
|
if (calcOrderPriceResult.isError()) {
|
||||||
return CommonResult.error(calcOrderPriceResult);
|
return CommonResult.error(calcOrderPriceResult);
|
||||||
}
|
}
|
||||||
|
// 获得优惠劵
|
||||||
|
CalcOrderPriceBO calcOrderPrice = calcOrderPriceResult.getData();
|
||||||
|
List<CouponCardAvailableBO> 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<CalcOrderPriceBO> list0(List<CartItemBO> cartItems) {
|
private CommonResult<CalcOrderPriceBO> list0(List<CartItemBO> cartItems) {
|
||||||
|
|
|
@ -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.UsersCalcSkuPriceVO;
|
||||||
import cn.iocoder.mall.order.application.vo.UsersCartDetailVO;
|
import cn.iocoder.mall.order.application.vo.UsersCartDetailVO;
|
||||||
import cn.iocoder.mall.order.application.vo.UsersOrderConfirmCreateVO;
|
import cn.iocoder.mall.order.application.vo.UsersOrderConfirmCreateVO;
|
||||||
|
import cn.iocoder.mall.promotion.api.dto.CouponCardSpuDTO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface CartConvert {
|
public interface CartConvert {
|
||||||
|
|
||||||
|
@ -19,4 +24,17 @@ public interface CartConvert {
|
||||||
|
|
||||||
UsersCalcSkuPriceVO convert2(CalcSkuPriceBO calcSkuPriceBO);
|
UsersCalcSkuPriceVO convert2(CalcSkuPriceBO calcSkuPriceBO);
|
||||||
|
|
||||||
|
default List<CouponCardSpuDTO> convertList(List<CalcOrderPriceBO.ItemGroup> itemGroups) {
|
||||||
|
List<CouponCardSpuDTO> 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,6 @@ public class UsersCalcSkuPriceVO {
|
||||||
/**
|
/**
|
||||||
* 最终价格,单位:分。
|
* 最终价格,单位:分。
|
||||||
*/
|
*/
|
||||||
private Integer presentPrice;
|
private Integer buyPrice;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,25 +36,16 @@ public class UsersCartDetailVO {
|
||||||
*/
|
*/
|
||||||
private PromotionActivityBO activity; // TODO 芋艿,偷懒
|
private PromotionActivityBO activity; // TODO 芋艿,偷懒
|
||||||
/**
|
/**
|
||||||
* 优惠活动是否生效
|
* 促销减少的金额
|
||||||
*
|
*
|
||||||
* 多个商品,参与某个活动,因为并发达到条件,所以会存在未生效的情况。所以一共有三种情况
|
* 1. 若未参与促销活动,或不满足促销条件,返回 null
|
||||||
*
|
* 2. 该金额,已经分摊到每个 Item 的 discountTotal ,需要注意。
|
||||||
* 1. activity 非空,activityEffectEffective 为 true,参与活动,且生效
|
|
||||||
* 2. activity 非空,activityEffectEffective 为 false ,参与活动,并未生效
|
|
||||||
* 3. activity 为空,activityEffectEffective 为空,并未参与活动。
|
|
||||||
*/
|
*/
|
||||||
private Boolean activityEffectEffective;
|
private Integer activityDiscountTotal;
|
||||||
/**
|
/**
|
||||||
* 商品数组
|
* 商品数组
|
||||||
*/
|
*/
|
||||||
private List<Sku> items;
|
private List<Sku> items;
|
||||||
/**
|
|
||||||
* 费用
|
|
||||||
*
|
|
||||||
* TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
|
|
||||||
*/
|
|
||||||
private Fee fee;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,15 +94,36 @@ public class UsersCartDetailVO {
|
||||||
*/
|
*/
|
||||||
private PromotionActivityBO activity;
|
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 {
|
public static class Fee {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 总价
|
* 购买总价
|
||||||
*/
|
*/
|
||||||
private Integer originalTotal;
|
private Integer buyTotal;
|
||||||
/**
|
/**
|
||||||
* 优惠总价
|
* 优惠总价
|
||||||
*
|
*
|
||||||
|
@ -175,8 +187,8 @@ public class UsersCartDetailVO {
|
||||||
public Fee() {
|
public Fee() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Fee(Integer originalTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) {
|
public Fee(Integer buyTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) {
|
||||||
this.originalTotal = originalTotal;
|
this.buyTotal = buyTotal;
|
||||||
this.discountTotal = discountTotal;
|
this.discountTotal = discountTotal;
|
||||||
this.postageTotal = postageTotal;
|
this.postageTotal = postageTotal;
|
||||||
this.presentTotal = presentTotal;
|
this.presentTotal = presentTotal;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package cn.iocoder.mall.order.application.vo;
|
package cn.iocoder.mall.order.application.vo;
|
||||||
|
|
||||||
import cn.iocoder.mall.product.api.bo.ProductAttrAndValuePairBO;
|
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 cn.iocoder.mall.promotion.api.bo.PromotionActivityBO;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
@ -19,6 +20,10 @@ public class UsersOrderConfirmCreateVO {
|
||||||
* 费用
|
* 费用
|
||||||
*/
|
*/
|
||||||
private Fee fee;
|
private Fee fee;
|
||||||
|
/**
|
||||||
|
* 优惠劵列表 TODO 芋艿,后续改改
|
||||||
|
*/
|
||||||
|
private List<CouponCardAvailableBO> couponCards;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品分组
|
* 商品分组
|
||||||
|
@ -79,9 +84,36 @@ public class UsersOrderConfirmCreateVO {
|
||||||
*/
|
*/
|
||||||
private Integer buyQuantity;
|
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 {
|
public static class Fee {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 总价
|
* 购买总价
|
||||||
*/
|
*/
|
||||||
private Integer originalTotal;
|
private Integer buyTotal;
|
||||||
/**
|
/**
|
||||||
* 优惠总价
|
* 优惠总价
|
||||||
*
|
*
|
||||||
|
@ -145,8 +177,8 @@ public class UsersOrderConfirmCreateVO {
|
||||||
public Fee() {
|
public Fee() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Fee(Integer originalTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) {
|
public Fee(Integer buyTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) {
|
||||||
this.originalTotal = originalTotal;
|
this.buyTotal = buyTotal;
|
||||||
this.discountTotal = discountTotal;
|
this.discountTotal = discountTotal;
|
||||||
this.postageTotal = postageTotal;
|
this.postageTotal = postageTotal;
|
||||||
this.presentTotal = presentTotal;
|
this.presentTotal = presentTotal;
|
||||||
|
|
|
@ -20,6 +20,8 @@ public class CalcOrderPriceBO {
|
||||||
private List<ItemGroup> itemGroups;
|
private List<ItemGroup> itemGroups;
|
||||||
/**
|
/**
|
||||||
* 邮费信息
|
* 邮费信息
|
||||||
|
*
|
||||||
|
* TODO 芋艿,暂时未弄
|
||||||
*/
|
*/
|
||||||
private Postage postage;
|
private Postage postage;
|
||||||
/**
|
/**
|
||||||
|
@ -42,25 +44,22 @@ public class CalcOrderPriceBO {
|
||||||
// TODO 芋艿,目前只会有【满减送】的情况,未来有新的促销方式,可能需要改成数组
|
// TODO 芋艿,目前只会有【满减送】的情况,未来有新的促销方式,可能需要改成数组
|
||||||
private PromotionActivityBO activity;
|
private PromotionActivityBO activity;
|
||||||
/**
|
/**
|
||||||
* 优惠活动是否生效
|
* 促销减少的金额
|
||||||
*
|
*
|
||||||
* 多个商品,参与某个活动,因为并发达到条件,所以会存在未生效的情况。所以一共有三种情况
|
* 1. 若未参与促销活动,或不满足促销条件,返回 null
|
||||||
*
|
* 2. 该金额,已经分摊到每个 Item 的 discountTotal ,需要注意。
|
||||||
* 1. activity 非空,activityEffectEffective 为 true,参与活动,且生效
|
|
||||||
* 2. activity 非空,activityEffectEffective 为 false ,参与活动,并未生效
|
|
||||||
* 3. activity 为空,activityEffectEffective 为空,并未参与活动。
|
|
||||||
*/
|
*/
|
||||||
private Boolean activityEffectEffective;
|
private Integer activityDiscountTotal;
|
||||||
/**
|
/**
|
||||||
* 商品数组
|
* 商品数组
|
||||||
*/
|
*/
|
||||||
private List<Item> items;
|
private List<Item> items;
|
||||||
/**
|
// /**
|
||||||
* 费用
|
// * 费用
|
||||||
*
|
// *
|
||||||
* TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
|
// * TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
|
||||||
*/
|
// */
|
||||||
private Fee fee;
|
// private Fee fee; // 注释原因,不用这里了
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,15 +80,36 @@ public class CalcOrderPriceBO {
|
||||||
*/
|
*/
|
||||||
private PromotionActivityBO activity;
|
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 {
|
public static class Fee {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 总价
|
* 购买总价
|
||||||
*/
|
*/
|
||||||
private Integer originalTotal;
|
private Integer buyTotal;
|
||||||
/**
|
/**
|
||||||
* 优惠总价
|
* 优惠总价
|
||||||
*
|
*
|
||||||
|
@ -124,8 +144,8 @@ public class CalcOrderPriceBO {
|
||||||
public Fee() {
|
public Fee() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Fee(Integer originalTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) {
|
public Fee(Integer buyTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) {
|
||||||
this.originalTotal = originalTotal;
|
this.buyTotal = buyTotal;
|
||||||
this.discountTotal = discountTotal;
|
this.discountTotal = discountTotal;
|
||||||
this.postageTotal = postageTotal;
|
this.postageTotal = postageTotal;
|
||||||
this.presentTotal = presentTotal;
|
this.presentTotal = presentTotal;
|
||||||
|
|
|
@ -24,8 +24,8 @@ public class CalcSkuPriceBO {
|
||||||
*/
|
*/
|
||||||
private Integer originalPrice;
|
private Integer originalPrice;
|
||||||
/**
|
/**
|
||||||
* 最终价格,单位:分。
|
* 购买价格,单位:分。
|
||||||
*/
|
*/
|
||||||
private Integer presentPrice;
|
private Integer buyPrice;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,18 +49,62 @@ public class OrderItemDO extends DeletableDO {
|
||||||
*/
|
*/
|
||||||
private Integer quantity;
|
private Integer quantity;
|
||||||
/**
|
/**
|
||||||
* 价格(分)
|
* 商品成交单价(分)
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
private Integer price;
|
private Integer price;
|
||||||
/**
|
/**
|
||||||
* 支付金额(实付金额)
|
* 支付金额(实付金额)
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
private Integer payAmount;
|
private Integer payAmount;
|
||||||
/**
|
/**
|
||||||
* 物流金额 (分)
|
* 物流金额 (分)
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
private Integer logisticsPrice;
|
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
|
||||||
|
|
||||||
///
|
///
|
||||||
/// 时间信息
|
/// 时间信息
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
/**
|
|
||||||
* @author Sin
|
|
||||||
* @time 2019-03-16 13:49
|
|
||||||
*/
|
|
||||||
package cn.iocoder.mall.order.biz;
|
|
|
@ -178,17 +178,17 @@ public class CartServiceImpl implements CartService {
|
||||||
List<CalcOrderPriceBO.ItemGroup> itemGroups = groupByFullPrivilege(items, activityList);
|
List<CalcOrderPriceBO.ItemGroup> itemGroups = groupByFullPrivilege(items, activityList);
|
||||||
calcOrderPriceBO.setItemGroups(itemGroups);
|
calcOrderPriceBO.setItemGroups(itemGroups);
|
||||||
// 4. 计算最终的价格
|
// 4. 计算最终的价格
|
||||||
Integer originalTotal = 0;
|
int buyTotal = 0;
|
||||||
Integer presentTotal = 0;
|
int discountTotal = 0;
|
||||||
Integer discountTotal = 0;
|
int presentTotal = 0;
|
||||||
for (CalcOrderPriceBO.ItemGroup itemGroup : calcOrderPriceBO.getItemGroups()) {
|
for (CalcOrderPriceBO.ItemGroup itemGroup : calcOrderPriceBO.getItemGroups()) {
|
||||||
originalTotal += itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getFee().getOriginalTotal() : 0).sum();
|
buyTotal += itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getBuyTotal() : 0).sum();
|
||||||
discountTotal += itemGroup.getFee().getDiscountTotal() + itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getFee().getDiscountTotal() : 0).sum();
|
discountTotal += itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getDiscountTotal() : 0).sum();
|
||||||
presentTotal += itemGroup.getFee().getPresentTotal();
|
presentTotal += itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getPresentTotal() : 0).sum();
|
||||||
}
|
}
|
||||||
Assert.isTrue(originalTotal - discountTotal == presentTotal,
|
Assert.isTrue(buyTotal - discountTotal == presentTotal,
|
||||||
String.format("价格合计( %d - %d == %d )不正确", originalTotal, discountTotal, presentTotal));
|
String.format("价格合计( %d - %d == %d )不正确", buyTotal, discountTotal, presentTotal));
|
||||||
calcOrderPriceBO.setFee(new CalcOrderPriceBO.Fee(originalTotal, discountTotal, 0, presentTotal));
|
calcOrderPriceBO.setFee(new CalcOrderPriceBO.Fee(buyTotal, discountTotal, 0, presentTotal));
|
||||||
// 返回
|
// 返回
|
||||||
return CommonResult.success(calcOrderPriceBO);
|
return CommonResult.success(calcOrderPriceBO);
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ public class CartServiceImpl implements CartService {
|
||||||
// 如果无促销活动,则直接返回默认结果即可
|
// 如果无促销活动,则直接返回默认结果即可
|
||||||
List<PromotionActivityBO> activityList = activityListResult.getData();
|
List<PromotionActivityBO> activityList = activityListResult.getData();
|
||||||
if (activityList.isEmpty()) {
|
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 芋艿,因为现在暂时只有限时折扣 + 满减送。所以写的比较简单先
|
// 如果有促销活动,则开始做计算 TODO 芋艿,因为现在暂时只有限时折扣 + 满减送。所以写的比较简单先
|
||||||
PromotionActivityBO fullPrivilege = findPromotionActivityByType(activityList, PromotionActivityTypeEnum.FULL_PRIVILEGE);
|
PromotionActivityBO fullPrivilege = findPromotionActivityByType(activityList, PromotionActivityTypeEnum.FULL_PRIVILEGE);
|
||||||
|
@ -223,7 +223,7 @@ public class CartServiceImpl implements CartService {
|
||||||
Integer presentPrice = calcSkuPriceByTimeLimitDiscount(sku, timeLimitedDiscount);
|
Integer presentPrice = calcSkuPriceByTimeLimitDiscount(sku, timeLimitedDiscount);
|
||||||
// 返回结果
|
// 返回结果
|
||||||
return CommonResult.success(new CalcSkuPriceBO().setFullPrivilege(fullPrivilege).setTimeLimitedDiscount(timeLimitedDiscount)
|
return CommonResult.success(new CalcSkuPriceBO().setFullPrivilege(fullPrivilege).setTimeLimitedDiscount(timeLimitedDiscount)
|
||||||
.setOriginalPrice(sku.getPrice()).setPresentPrice(presentPrice));
|
.setOriginalPrice(sku.getPrice()).setBuyPrice(presentPrice));
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<CalcOrderPriceBO.Item> initCalcOrderPriceItems(List<ProductSkuDetailBO> skus,
|
private List<CalcOrderPriceBO.Item> initCalcOrderPriceItems(List<ProductSkuDetailBO> skus,
|
||||||
|
@ -237,10 +237,12 @@ public class CartServiceImpl implements CartService {
|
||||||
item.setSelected(calcOrderItem.getSelected());
|
item.setSelected(calcOrderItem.getSelected());
|
||||||
item.setBuyQuantity(calcOrderItem.getQuantity());
|
item.setBuyQuantity(calcOrderItem.getQuantity());
|
||||||
// 计算初始价格
|
// 计算初始价格
|
||||||
CalcOrderPriceBO.Fee fee = new CalcOrderPriceBO.Fee(0, 0, 0, 0);
|
item.setOriginPrice(sku.getPrice());
|
||||||
fee.setOriginalTotal(item.getPrice() * item.getBuyQuantity());
|
item.setBuyPrice(sku.getPrice());
|
||||||
fee.setPresentTotal(fee.getOriginalTotal());
|
item.setPresentPrice(sku.getPrice());
|
||||||
item.setFee(fee);
|
item.setBuyTotal(sku.getPrice() * calcOrderItem.getQuantity());
|
||||||
|
item.setDiscountTotal(0);
|
||||||
|
item.setPresentTotal(item.getBuyTotal());
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
@ -264,10 +266,10 @@ public class CartServiceImpl implements CartService {
|
||||||
// 设置优惠
|
// 设置优惠
|
||||||
item.setActivity(timeLimitedDiscount);
|
item.setActivity(timeLimitedDiscount);
|
||||||
// 设置价格
|
// 设置价格
|
||||||
item.setDiscountPrice(newPrice);
|
item.setBuyPrice(newPrice);
|
||||||
CalcOrderPriceBO.Fee fee = item.getFee();
|
item.setBuyTotal(newPrice * item.getBuyQuantity());
|
||||||
fee.setDiscountTotal(fee.getDiscountTotal() + (item.getPrice() - newPrice) * item.getBuyQuantity());
|
item.setPresentTotal(item.getBuyTotal() - item.getDiscountTotal());
|
||||||
fee.setPresentTotal(fee.getOriginalTotal() - fee.getDiscountTotal() + fee.getPostageTotal());
|
item.setPresentPrice(item.getPresentTotal() / item.getBuyQuantity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,14 +304,11 @@ public class CartServiceImpl implements CartService {
|
||||||
}
|
}
|
||||||
// 处理未参加活动的商品,形成一个分组
|
// 处理未参加活动的商品,形成一个分组
|
||||||
if (!items.isEmpty()) {
|
if (!items.isEmpty()) {
|
||||||
CalcOrderPriceBO.ItemGroup itemGroup = new CalcOrderPriceBO.ItemGroup()
|
itemGroups.add(new CalcOrderPriceBO.ItemGroup().setItems(items));
|
||||||
.setItems(items);
|
|
||||||
itemGroups.add(itemGroup);
|
|
||||||
}
|
}
|
||||||
// 计算每个分组的价格
|
// 计算每个分组的价格
|
||||||
for (CalcOrderPriceBO.ItemGroup itemGroup : itemGroups) {
|
for (CalcOrderPriceBO.ItemGroup itemGroup : itemGroups) {
|
||||||
itemGroup.setFee(calcSkuPriceByFullPrivilege(itemGroup));
|
itemGroup.setActivityDiscountTotal(calcSkuPriceByFullPrivilege(itemGroup));
|
||||||
itemGroup.setActivityEffectEffective(itemGroup.getFee().getDiscountTotal() > 0);
|
|
||||||
}
|
}
|
||||||
// 返回结果
|
// 返回结果
|
||||||
return itemGroups;
|
return itemGroups;
|
||||||
|
@ -346,17 +345,18 @@ public class CartServiceImpl implements CartService {
|
||||||
throw new IllegalArgumentException(String.format("折扣活动(%s) 的优惠类型不正确", timeLimitedDiscount.toString()));
|
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) {
|
if (itemGroup.getActivity() == null) {
|
||||||
Integer originalTotal = itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getFee().getPresentTotal() : 0).sum();
|
return null;
|
||||||
return new CalcOrderPriceBO.Fee(originalTotal, 0, 0, originalTotal);
|
|
||||||
}
|
}
|
||||||
PromotionActivityBO activity = itemGroup.getActivity();
|
PromotionActivityBO activity = itemGroup.getActivity();
|
||||||
Assert.isTrue(PromotionActivityTypeEnum.FULL_PRIVILEGE.getValue().equals(activity.getActivityType()),
|
Assert.isTrue(PromotionActivityTypeEnum.FULL_PRIVILEGE.getValue().equals(activity.getActivityType()),
|
||||||
"传入的必须的满减送活动必须是满减送");
|
"传入的必须的满减送活动必须是满减送");
|
||||||
// 获得优惠信息
|
// 获得优惠信息
|
||||||
Integer itemCnt = itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getBuyQuantity() : 0).sum();
|
List<CalcOrderPriceBO.Item> items = itemGroup.getItems().stream().filter(item -> !item.getSelected())
|
||||||
Integer originalTotal = itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getFee().getPresentTotal() : 0).sum();
|
.collect(Collectors.toList());
|
||||||
|
Integer itemCnt = items.stream().mapToInt(CalcOrderPriceBO.Item::getBuyQuantity).sum();
|
||||||
|
Integer originalTotal = items.stream().mapToInt(CalcOrderPriceBO.Item::getPresentTotal).sum();
|
||||||
List<PromotionActivityBO.FullPrivilege.Privilege> privileges = activity.getFullPrivilege().getPrivileges().stream()
|
List<PromotionActivityBO.FullPrivilege.Privilege> privileges = activity.getFullPrivilege().getPrivileges().stream()
|
||||||
.filter(privilege -> {
|
.filter(privilege -> {
|
||||||
if (MeetTypeEnum.PRICE.getValue().equals(privilege.getMeetType())) {
|
if (MeetTypeEnum.PRICE.getValue().equals(privilege.getMeetType())) {
|
||||||
|
@ -369,7 +369,7 @@ public class CartServiceImpl implements CartService {
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
// 获得不到优惠信息,返回原始价格
|
// 获得不到优惠信息,返回原始价格
|
||||||
if (privileges.isEmpty()) {
|
if (privileges.isEmpty()) {
|
||||||
return new CalcOrderPriceBO.Fee(originalTotal, 0, 0, originalTotal);
|
return null;
|
||||||
}
|
}
|
||||||
// 获得到优惠信息,进行价格计算
|
// 获得到优惠信息,进行价格计算
|
||||||
PromotionActivityBO.FullPrivilege.Privilege privilege = privileges.get(privileges.size() - 1);
|
PromotionActivityBO.FullPrivilege.Privilege privilege = privileges.get(privileges.size() - 1);
|
||||||
|
@ -393,7 +393,26 @@ public class CartServiceImpl implements CartService {
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(String.format("满减送促销(%s) 的优惠类型不正确", activity.toString()));
|
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<PromotionActivityBO> activityList, PromotionActivityTypeEnum type) {
|
private PromotionActivityBO findPromotionActivityByType(List<PromotionActivityBO> activityList, PromotionActivityTypeEnum type) {
|
||||||
|
|
|
@ -212,6 +212,8 @@ public class OrderServiceImpl implements OrderService {
|
||||||
return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_GET_GOODS_INFO_INCORRECT.getCode());
|
return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_GET_GOODS_INFO_INCORRECT.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
// 设置 orderItem
|
// 设置 orderItem
|
||||||
|
|
||||||
Map<Integer, ProductSkuDetailBO> productSpuBOMap = productResult.getData()
|
Map<Integer, ProductSkuDetailBO> productSpuBOMap = productResult.getData()
|
||||||
|
@ -293,7 +295,7 @@ public class OrderServiceImpl implements OrderService {
|
||||||
.setDeleted(DeletedStatusEnum.DELETED_NO.getValue())
|
.setDeleted(DeletedStatusEnum.DELETED_NO.getValue())
|
||||||
.setCreateTime(new Date())
|
.setCreateTime(new Date())
|
||||||
.setUpdateTime(null);
|
.setUpdateTime(null);
|
||||||
orderItemMapper.insert(orderItemDO);
|
orderItemMapper.insert(orderItemDO); // TODO 芋艿,需要改成一次性插入
|
||||||
});
|
});
|
||||||
|
|
||||||
// 创建预订单
|
// 创建预订单
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
package cn.iocoder.mall.pay.biz.mq;
|
|
|
@ -1 +0,0 @@
|
||||||
package cn.iocoder.mall.product;
|
|
|
@ -2,13 +2,12 @@ package cn.iocoder.mall.promotion.api;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.validator.InEnum;
|
import cn.iocoder.common.framework.validator.InEnum;
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
|
import cn.iocoder.mall.promotion.api.bo.*;
|
||||||
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.constant.CouponTemplateStatusEnum;
|
import cn.iocoder.mall.promotion.api.constant.CouponTemplateStatusEnum;
|
||||||
import cn.iocoder.mall.promotion.api.dto.*;
|
import cn.iocoder.mall.promotion.api.dto.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface CouponService {
|
public interface CouponService {
|
||||||
|
|
||||||
// ========== 优惠劵(码)模板 ==========
|
// ========== 优惠劵(码)模板 ==========
|
||||||
|
@ -93,6 +92,17 @@ public interface CouponService {
|
||||||
*/
|
*/
|
||||||
CommonResult<Boolean> cancelUseCouponCard(Integer userId, Integer couponCardId);
|
CommonResult<Boolean> cancelUseCouponCard(Integer userId, Integer couponCardId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得用户所有优惠劵,并标明是否可用
|
||||||
|
*
|
||||||
|
* 注意,spus 是作为条件,判断优惠劵是否可用
|
||||||
|
*
|
||||||
|
* @param userId 用户编号
|
||||||
|
* @param spus 匹配的商品/分类
|
||||||
|
* @return 优惠劵列表
|
||||||
|
*/
|
||||||
|
CommonResult<List<CouponCardAvailableBO>> getCouponCardList(Integer userId, List<CouponCardSpuDTO> spus);
|
||||||
|
|
||||||
// ========== 优惠码 ==========
|
// ========== 优惠码 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package cn.iocoder.mall.promotion.biz.convert;
|
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.api.bo.CouponCardBO;
|
||||||
import cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO;
|
import cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
@ -22,4 +23,7 @@ public interface CouponCardConvert {
|
||||||
@Mappings({})
|
@Mappings({})
|
||||||
CouponCardBO convert(CouponCardDO card);
|
CouponCardBO convert(CouponCardDO card);
|
||||||
|
|
||||||
|
@Mappings({})
|
||||||
|
CouponCardAvailableBO convert2(CouponCardDO card, boolean x); // TODO 芋艿,临时用来解决 mapstruct 无法正确匹配方法的问题
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@ public interface CouponCardMapper {
|
||||||
|
|
||||||
CouponCardDO selectById(@Param("id") Integer id);
|
CouponCardDO selectById(@Param("id") Integer id);
|
||||||
|
|
||||||
|
List<CouponCardDO> selectListByUserIdAndStatus(@Param("userId") Integer userId,
|
||||||
|
@Param("status") Integer status);
|
||||||
|
|
||||||
List<CouponCardDO> selectListByPage(@Param("userId") Integer userId,
|
List<CouponCardDO> selectListByPage(@Param("userId") Integer userId,
|
||||||
@Param("status") Integer status,
|
@Param("status") Integer status,
|
||||||
@Param("offset") Integer offset,
|
@Param("offset") Integer offset,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import cn.iocoder.mall.promotion.biz.dataobject.CouponTemplateDO;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
|
@ -11,6 +12,8 @@ public interface CouponTemplateMapper {
|
||||||
|
|
||||||
CouponTemplateDO selectById(@Param("id") Integer id);
|
CouponTemplateDO selectById(@Param("id") Integer id);
|
||||||
|
|
||||||
|
List<CouponTemplateDO> selectListByIds(@Param("ids") Collection<Integer> ids);
|
||||||
|
|
||||||
List<CouponTemplateDO> selectListByPage(@Param("type") Integer type,
|
List<CouponTemplateDO> selectListByPage(@Param("type") Integer type,
|
||||||
@Param("title") String title,
|
@Param("title") String title,
|
||||||
@Param("status") Integer status,
|
@Param("status") Integer status,
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
package cn.iocoder.mall.promotion.biz;
|
|
|
@ -3,12 +3,10 @@ package cn.iocoder.mall.promotion.biz.service;
|
||||||
import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
|
import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
|
||||||
import cn.iocoder.common.framework.util.DateUtil;
|
import cn.iocoder.common.framework.util.DateUtil;
|
||||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||||
|
import cn.iocoder.common.framework.util.StringUtil;
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
import cn.iocoder.mall.promotion.api.CouponService;
|
import cn.iocoder.mall.promotion.api.CouponService;
|
||||||
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
|
import cn.iocoder.mall.promotion.api.bo.*;
|
||||||
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.constant.*;
|
import cn.iocoder.mall.promotion.api.constant.*;
|
||||||
import cn.iocoder.mall.promotion.api.dto.*;
|
import cn.iocoder.mall.promotion.api.dto.*;
|
||||||
import cn.iocoder.mall.promotion.biz.convert.CouponCardConvert;
|
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.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.*;
|
||||||
import java.util.Date;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service // 实际上不用添加。添加的原因是,必须 Spring 报错提示
|
@Service // 实际上不用添加。添加的原因是,必须 Spring 报错提示
|
||||||
@com.alibaba.dubbo.config.annotation.Service(validation = "true")
|
@com.alibaba.dubbo.config.annotation.Service(validation = "true")
|
||||||
|
@ -252,6 +250,23 @@ public class CouponServiceImpl implements CouponService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<List<CouponCardAvailableBO>> getCouponCardList(Integer userId, List<CouponCardSpuDTO> spus) {
|
||||||
|
// 查询用户未使用的优惠劵列表
|
||||||
|
List<CouponCardDO> cards = couponCardMapper.selectListByUserIdAndStatus(userId, CouponCardStatusEnum.UNUSED.getValue());
|
||||||
|
Map<Integer, CouponTemplateDO> templates = couponTemplateMapper.selectListByIds(cards.stream().map(CouponCardDO::getTemplateId).collect(Collectors.toSet()))
|
||||||
|
.stream().collect(Collectors.toMap(CouponTemplateDO::getId, template -> template));
|
||||||
|
// 逐个判断是否可用
|
||||||
|
List<CouponCardAvailableBO> 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) {
|
private void setCouponCardValidTime(CouponCardDO card, CouponTemplateDO template) {
|
||||||
if (CouponTemplateDateTypeEnum.FIXED_DATE.getValue().equals(template.getDateType())) {
|
if (CouponTemplateDateTypeEnum.FIXED_DATE.getValue().equals(template.getDateType())) {
|
||||||
card.setValidStartTime(template.getValidStartTime()).setValidEndTime(template.getValidEndTime());
|
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<CouponCardSpuDTO> 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<Integer> 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<Integer> 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<Integer> 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<Integer> 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
|
@Override
|
||||||
|
|
|
@ -33,6 +33,20 @@
|
||||||
WHERE id = #{id}
|
WHERE id = #{id}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectListByUserIdAndStatus" resultType="CouponCardDO">
|
||||||
|
SELECT
|
||||||
|
<include refid="FIELDS" />
|
||||||
|
FROM coupon_card
|
||||||
|
<where>
|
||||||
|
<if test="userId != null">
|
||||||
|
AND user_id = #{userId}
|
||||||
|
</if>
|
||||||
|
<if test="status != null">
|
||||||
|
AND status = #{status}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectListByPage" resultType="CouponCardDO">
|
<select id="selectListByPage" resultType="CouponCardDO">
|
||||||
SELECT
|
SELECT
|
||||||
<include refid="FIELDS" />
|
<include refid="FIELDS" />
|
||||||
|
|
|
@ -34,6 +34,16 @@
|
||||||
WHERE id = #{id}
|
WHERE id = #{id}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectListByIds" resultType="CouponTemplateDO">
|
||||||
|
SELECT
|
||||||
|
<include refid="FIELDS"/>
|
||||||
|
FROM coupon_template
|
||||||
|
WHERE id IN
|
||||||
|
<foreach item="id" collection="ids" separator="," open="(" close=")" index="">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectListByPage" resultType="CouponTemplateDO">
|
<select id="selectListByPage" resultType="CouponTemplateDO">
|
||||||
SELECT
|
SELECT
|
||||||
<include refid="FIELDS" />
|
<include refid="FIELDS" />
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
package cn.iocoder.mall.promotion.biz;
|
|
|
@ -1,6 +0,0 @@
|
||||||
/**
|
|
||||||
* 提供 SDK 给其它服务,使用如下功能:
|
|
||||||
*
|
|
||||||
* 1. 通过 {@link cn.iocoder.mall.user.sdk.interceptor.UserSecurityInterceptor} 拦截器,实现需要登陆 URL 的鉴权
|
|
||||||
*/
|
|
||||||
package cn.iocoder.mall.user.sdk;
|
|
|
@ -1 +0,0 @@
|
||||||
package cn.iocoder.mall.user.biz;
|
|
Loading…
Reference in New Issue