付费会员价格 #110
@ -23,6 +23,7 @@ export interface Sku {
|
||||
firstBrokeragePrice?: number | string // 一级分销的佣金
|
||||
secondBrokeragePrice?: number | string // 二级分销的佣金
|
||||
salesCount?: number // 商品销量
|
||||
paidMemberPrice?: number | string //付费会员价
|
||||
}
|
||||
|
||||
export interface GiveCouponTemplate {
|
||||
@ -58,6 +59,8 @@ export interface Spu {
|
||||
status?: number // 商品状态
|
||||
pointsStatus?: number // 商品使用积分状态
|
||||
usePointsMax?: number // 单商品积分使用上限
|
||||
isPaidMemberPrice?: number//是否设置付费会员价
|
||||
paidMemberPrice?: number//会员价
|
||||
}
|
||||
|
||||
// 获得 Spu 列表
|
||||
|
@ -0,0 +1,470 @@
|
||||
<!-- 情况一:添加/修改 -->
|
||||
<template>
|
||||
<template v-if="!isDetail && isBatch">
|
||||
<el-input v-model="formData.paidMemberPrice"
|
||||
placeholder="请输入会员价" label="会员价" style="width: 180px; margin-right: 10px;"/>
|
||||
<el-button type="primary" @click="batchAdd">
|
||||
批量添加
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table
|
||||
v-if="!isDetail && !isBatch"
|
||||
:data="isBatch ? skuList : formData!.skus!"
|
||||
border
|
||||
class="tabNumWidth"
|
||||
max-height="500"
|
||||
size="small"
|
||||
>
|
||||
<template v-if="formData!.specType && !isBatch">
|
||||
<!-- 根据商品属性动态添加 -->
|
||||
<el-table-column
|
||||
v-for="(item, index) in tableHeaders"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
align="center"
|
||||
min-width="120"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<span style="font-weight: bold; color: #40aaff">
|
||||
{{ row.properties[index]?.valueName }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column align="center" label="图片" min-width="65">
|
||||
<template #default="{ row }">
|
||||
<el-image
|
||||
v-if="row.picUrl"
|
||||
:src="row.picUrl"
|
||||
class="h-50px w-50px"
|
||||
@click="imagePreview(row.picUrl)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="售价" min-width="168">
|
||||
<template #default="{ row }">
|
||||
{{row.price}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="库存" min-width="168">
|
||||
<template #default="{ row }">
|
||||
{{row.stock}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template v-if="formData!.subCommissionType">
|
||||
<el-table-column align="center" label="一级返佣(元)" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.firstBrokeragePrice"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
class="w-100%"
|
||||
controls-position="right"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="二级返佣(元)" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.secondBrokeragePrice"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
class="w-100%"
|
||||
controls-position="right"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<template v-if="formData!.isPaidMemberPrice === 1">
|
||||
<el-table-column align="center" label="会员价" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.paidMemberPrice"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
class="w-100%"
|
||||
controls-position="right"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</el-table>
|
||||
|
||||
<!-- 情况二:详情-->
|
||||
<template v-if="isDetail && isBatch">
|
||||
<el-input v-model="formData.paidMemberPrice"
|
||||
placeholder="请输入会员价" label="会员价" style="width: 180px; margin-right: 10px;"/>
|
||||
<el-button type="primary" @click="batchAdd">
|
||||
批量添加
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table
|
||||
v-if="isDetail"
|
||||
ref="activitySkuListRef"
|
||||
:data="formData!.skus!"
|
||||
border
|
||||
max-height="500"
|
||||
size="small"
|
||||
style="width: 99%"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column v-if="isComponent" type="selection" width="45" />
|
||||
|
||||
<template v-if="formData!.specType && !isBatch">
|
||||
<!-- 根据商品属性动态添加 -->
|
||||
<el-table-column
|
||||
v-for="(item, index) in tableHeaders"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
align="center"
|
||||
min-width="80"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<span style="font-weight: bold; color: #40aaff">
|
||||
{{ row.properties[index]?.valueName }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column align="center" label="图片" min-width="80">
|
||||
<template #default="{ row }">
|
||||
<el-image
|
||||
v-if="row.picUrl"
|
||||
:src="row.picUrl"
|
||||
class="h-50px w-50px"
|
||||
@click="imagePreview(row.picUrl)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="售价(元)" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.price }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="库存" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.stock }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<template v-if="formData!.subCommissionType">
|
||||
<el-table-column align="center" label="一级返佣(元)" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.firstBrokeragePrice }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="二级返佣(元)" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.secondBrokeragePrice }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<template v-if="formData!.isPaidMemberPrice === 1">
|
||||
<el-table-column align="center" label="会员价" min-width="168">
|
||||
<template #default="{ row }">
|
||||
{{row.paidMemberPrice}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</el-table>
|
||||
|
||||
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { PropType, Ref } from 'vue'
|
||||
import { copyValueToTarget } from '@/utils'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { UploadImg } from '@/components/UploadFile'
|
||||
import type { Property, Sku, Spu } from '@/api/mall/product/spu'
|
||||
import { createImageViewer } from '@/components/ImageViewer'
|
||||
import { RuleConfig } from '@/views/mall/product/spu/components/index'
|
||||
import { PropertyAndValues } from './index'
|
||||
import { ElTable } from 'element-plus'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
|
||||
defineOptions({ name: 'MarkingtingList' })
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
propFormData: {
|
||||
type: Object as PropType<Spu>,
|
||||
default: () => {}
|
||||
},
|
||||
propertyList: {
|
||||
type: Array as PropType<PropertyAndValues[]>,
|
||||
default: () => []
|
||||
},
|
||||
ruleConfig: {
|
||||
type: Array as PropType<RuleConfig[]>,
|
||||
default: () => []
|
||||
},
|
||||
isBatch: propTypes.bool.def(false), // 是否作为批量操作组件
|
||||
isDetail: propTypes.bool.def(false), // 是否作为 sku 详情组件
|
||||
isComponent: propTypes.bool.def(false), // 是否作为 sku 选择组件
|
||||
isActivityComponent: propTypes.bool.def(false) // 是否作为 sku 活动配置组件
|
||||
})
|
||||
const formData: Ref<Spu | undefined> = ref<Spu>() // 表单数据
|
||||
const skuList = ref<Sku[]>([
|
||||
{
|
||||
price: 0, // 商品价格
|
||||
marketPrice: 0, // 市场价
|
||||
costPrice: 0, // 成本价
|
||||
barCode: '', // 商品条码
|
||||
picUrl: '', // 图片地址
|
||||
stock: 0, // 库存
|
||||
weight: 0, // 商品重量
|
||||
volume: 0, // 商品体积
|
||||
firstBrokeragePrice: 0, // 一级分销的佣金
|
||||
secondBrokeragePrice: 0, // 二级分销的佣金
|
||||
paidMemberPrice: 0 //会员价格
|
||||
}
|
||||
]) // 批量添加时的临时数据
|
||||
|
||||
/** 商品图预览 */
|
||||
const imagePreview = (imgUrl: string) => {
|
||||
createImageViewer({
|
||||
zIndex: 9999999,
|
||||
urlList: [imgUrl]
|
||||
})
|
||||
}
|
||||
|
||||
/** 批量添加 */
|
||||
const batchAdd = () => {
|
||||
validateProperty()
|
||||
formData.value!.skus!.forEach((item) => {
|
||||
console.log("item:",item,"formSkus:",formData.value!.paidMemberPrice)
|
||||
item.paidMemberPrice = formData.value!.paidMemberPrice
|
||||
// copyValueToTarget(item.paidMemberPrice, formData.value!.paidMemberPrice)
|
||||
})
|
||||
}
|
||||
/** 校验商品属性属性值 */
|
||||
const validateProperty = () => {
|
||||
// 校验商品属性属性值是否为空,有一个为空都不给过
|
||||
const warningInfo = '存在属性属性值为空,请先检查完善属性值后重试!!!'
|
||||
for (const item of props.propertyList) {
|
||||
if (!item.values || isEmpty(item.values)) {
|
||||
message.warning(warningInfo)
|
||||
throw new Error(warningInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 删除 sku */
|
||||
const deleteSku = (row) => {
|
||||
const index = formData.value!.skus!.findIndex(
|
||||
// 直接把列表转成字符串比较
|
||||
(sku) => JSON.stringify(sku.properties) === JSON.stringify(row.properties)
|
||||
)
|
||||
formData.value!.skus!.splice(index, 1)
|
||||
}
|
||||
const tableHeaders = ref<{ prop: string; label: string }[]>([]) // 多属性表头
|
||||
/**
|
||||
* 保存时,每个商品规格的表单要校验下。例如说,销售金额最低是 0.01 这种。
|
||||
*/
|
||||
const validateSku = () => {
|
||||
validateProperty()
|
||||
let warningInfo = '请检查商品各行相关属性配置,'
|
||||
let validate = true // 默认通过
|
||||
for (const sku of formData.value!.skus!) {
|
||||
// 作为活动组件的校验
|
||||
for (const rule of props?.ruleConfig) {
|
||||
const arg = getValue(sku, rule.name)
|
||||
if (!rule.rule(arg)) {
|
||||
validate = false // 只要有一个不通过则直接不通过
|
||||
warningInfo += rule.message
|
||||
break
|
||||
}
|
||||
}
|
||||
// 只要有一个不通过则结束后续的校验
|
||||
if (!validate) {
|
||||
message.warning(warningInfo)
|
||||
throw new Error(warningInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
const getValue = (obj, arg) => {
|
||||
const keys = arg.split('.')
|
||||
let value = obj
|
||||
for (const key of keys) {
|
||||
if (value && typeof value === 'object' && key in value) {
|
||||
value = value[key]
|
||||
} else {
|
||||
value = undefined
|
||||
break
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'selectionChange', value: Sku[]): void
|
||||
}>()
|
||||
/**
|
||||
* 选择时触发
|
||||
* @param Sku 传递过来的选中的 sku 是一个数组
|
||||
*/
|
||||
const handleSelectionChange = (val: Sku[]) => {
|
||||
emit('selectionChange', val)
|
||||
}
|
||||
|
||||
/**
|
||||
* 将传进来的值赋值给 skuList
|
||||
*/
|
||||
watch(
|
||||
() => props.propFormData,
|
||||
(data) => {
|
||||
if (!data) return
|
||||
formData.value = data
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
/** 生成表数据 */
|
||||
const generateTableData = (propertyList: any[]) => {
|
||||
// 构建数据结构
|
||||
const propertyValues = propertyList.map((item) =>
|
||||
item.values.map((v: any) => ({
|
||||
propertyId: item.id,
|
||||
propertyName: item.name,
|
||||
valueId: v.id,
|
||||
valueName: v.name
|
||||
}))
|
||||
)
|
||||
const buildSkuList = build(propertyValues)
|
||||
// 如果回显的 sku 属性和添加的属性不一致则重置 skus 列表
|
||||
if (!validateData(propertyList)) {
|
||||
// 如果不一致则重置表数据,默认添加新的属性重新生成 sku 列表
|
||||
formData.value!.skus = []
|
||||
}
|
||||
for (const item of buildSkuList) {
|
||||
const row = {
|
||||
properties: Array.isArray(item) ? item : [item], // 如果只有一个属性的话返回的是一个 property 对象
|
||||
price: 0,
|
||||
marketPrice: 0,
|
||||
costPrice: 0,
|
||||
barCode: '',
|
||||
picUrl: '',
|
||||
stock: 0,
|
||||
weight: 0,
|
||||
volume: 0,
|
||||
firstBrokeragePrice: 0,
|
||||
secondBrokeragePrice: 0
|
||||
}
|
||||
// 如果存在属性相同的 sku 则不做处理
|
||||
const index = formData.value!.skus!.findIndex(
|
||||
(sku) => JSON.stringify(sku.properties) === JSON.stringify(row.properties)
|
||||
)
|
||||
if (index !== -1) {
|
||||
continue
|
||||
}
|
||||
formData.value!.skus!.push(row)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 skus 前置校验
|
||||
*/
|
||||
const validateData = (propertyList: any[]) => {
|
||||
const skuPropertyIds: number[] = []
|
||||
formData.value!.skus!.forEach((sku) =>
|
||||
sku.properties
|
||||
?.map((property) => property.propertyId)
|
||||
?.forEach((propertyId) => {
|
||||
if (skuPropertyIds.indexOf(propertyId!) === -1) {
|
||||
skuPropertyIds.push(propertyId!)
|
||||
}
|
||||
})
|
||||
)
|
||||
const propertyIds = propertyList.map((item) => item.id)
|
||||
return skuPropertyIds.length === propertyIds.length
|
||||
}
|
||||
|
||||
/** 构建所有排列组合 */
|
||||
const build = (propertyValuesList: Property[][]) => {
|
||||
if (propertyValuesList.length === 0) {
|
||||
return []
|
||||
} else if (propertyValuesList.length === 1) {
|
||||
return propertyValuesList[0]
|
||||
} else {
|
||||
const result: Property[][] = []
|
||||
const rest = build(propertyValuesList.slice(1))
|
||||
for (let i = 0; i < propertyValuesList[0].length; i++) {
|
||||
for (let j = 0; j < rest.length; j++) {
|
||||
// 第一次不是数组结构,后面的都是数组结构
|
||||
if (Array.isArray(rest[j])) {
|
||||
result.push([propertyValuesList[0][i], ...rest[j]])
|
||||
} else {
|
||||
result.push([propertyValuesList[0][i], rest[j]])
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** 监听属性列表,生成相关参数和表头 */
|
||||
watch(
|
||||
() => props.propertyList,
|
||||
(propertyList: PropertyAndValues[]) => {
|
||||
// 如果不是多规格则结束
|
||||
if (!formData.value!.specType) {
|
||||
return
|
||||
}
|
||||
// 如果当前组件作为批量添加数据使用,则重置表数据
|
||||
if (props.isBatch) {
|
||||
skuList.value = [
|
||||
{
|
||||
price: 0,
|
||||
marketPrice: 0,
|
||||
costPrice: 0,
|
||||
barCode: '',
|
||||
picUrl: '',
|
||||
stock: 0,
|
||||
weight: 0,
|
||||
volume: 0,
|
||||
firstBrokeragePrice: 0,
|
||||
secondBrokeragePrice: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// 判断代理对象是否为空
|
||||
if (JSON.stringify(propertyList) === '[]') {
|
||||
return
|
||||
}
|
||||
// 重置表头
|
||||
tableHeaders.value = []
|
||||
// 生成表头
|
||||
propertyList.forEach((item, index) => {
|
||||
// name加属性项index区分属性值
|
||||
tableHeaders.value.push({ prop: `name${index}`, label: item.name })
|
||||
})
|
||||
// 如果回显的 sku 属性和添加的属性一致则不处理
|
||||
if (validateData(propertyList)) {
|
||||
return
|
||||
}
|
||||
// 添加新属性没有属性值也不做处理
|
||||
if (propertyList.some((item) => !item.values || isEmpty(item.values))) {
|
||||
return
|
||||
}
|
||||
// 生成 table 数据,即 sku 列表
|
||||
generateTableData(propertyList)
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
const activitySkuListRef = ref<InstanceType<typeof ElTable>>()
|
||||
|
||||
const getSkuTableRef = () => {
|
||||
return activitySkuListRef.value
|
||||
}
|
||||
// 暴露出生成 sku 方法,给添加属性成功时调用
|
||||
defineExpose({ generateTableData, validateSku, getSkuTableRef })
|
||||
</script>
|
@ -1,4 +1,5 @@
|
||||
import SkuList from './SkuList.vue'
|
||||
import MarkingtingList from './MarkingtingList.vue'
|
||||
import { Spu } from '@/api/mall/product/spu'
|
||||
|
||||
interface PropertyAndValues {
|
||||
@ -51,4 +52,4 @@ const getPropertyList = (spu: Spu): PropertyAndValues[] => {
|
||||
return properties
|
||||
}
|
||||
|
||||
export { SkuList, PropertyAndValues, RuleConfig, getPropertyList }
|
||||
export { MarkingtingList, SkuList, PropertyAndValues, RuleConfig, getPropertyList }
|
||||
|
@ -6,8 +6,38 @@
|
||||
v-model="formData.onlyPaidMemberView"
|
||||
:active-value="1"
|
||||
:inactive-value="0" />
|
||||
<el-text class="mx-1" size="small">开启后仅付费会员可以看见并购买此商品</el-text>
|
||||
<el-text class="mx-1" size="small">开启后仅付费会员可以看见并购买此商品</el-text>
|
||||
</el-form-item>
|
||||
<el-form-item label="单独设置" >
|
||||
<el-checkbox
|
||||
v-model="formData.isPaidMemberPrice"
|
||||
:true-value="1"
|
||||
:false-value="0" >付费会员价</el-checkbox>
|
||||
</el-form-item>
|
||||
<template v-if="formData.isPaidMemberPrice === 1 ">
|
||||
<el-form-item label="批量设置" >
|
||||
<!-- <el-input v-model="formData.paidMemberPrice"-->
|
||||
<!-- placeholder="请输入会员价" label="会员价" style="width: 180px; margin-right: 10px;"/>-->
|
||||
<!-- <el-button type="primary" @click="batchAdd">-->
|
||||
<!-- 批量添加-->
|
||||
<!-- </el-button>-->
|
||||
<MarkingtingList ref="skuListRef"
|
||||
:is-batch="true"
|
||||
:prop-form-data="formData"
|
||||
:property-list="propertyList"
|
||||
:rule-config="ruleConfig"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品属性">
|
||||
<MarkingtingList
|
||||
ref="skuListRef"
|
||||
:is-detail="isDetail"
|
||||
:prop-form-data="formData"
|
||||
:property-list="propertyList"
|
||||
:rule-config="ruleConfig"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-form-item label="商品推荐">
|
||||
<el-checkbox
|
||||
v-model="formData.recommendHot"
|
||||
@ -48,8 +78,8 @@
|
||||
|
||||
</el-form>
|
||||
|
||||
<!-- 商品属性添加 Form 表单 -->
|
||||
<ProductPropertyAddForm ref="attributesAddFormRef" :propertyList="propertyList" />
|
||||
<!-- <!– 商品属性添加 Form 表单 –>-->
|
||||
<!-- <ProductPropertyAddForm ref="attributesAddFormRef" :propertyList="propertyList" />-->
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { PropType } from 'vue'
|
||||
@ -59,11 +89,12 @@ import {
|
||||
getPropertyList,
|
||||
PropertyAndValues,
|
||||
RuleConfig,
|
||||
SkuList
|
||||
MarkingtingList
|
||||
} from '@/views/mall/product/spu/components/index'
|
||||
import ProductAttributes from './ProductAttributes.vue'
|
||||
import ProductPropertyAddForm from './ProductPropertyAddForm.vue'
|
||||
import type { Spu } from '@/api/mall/product/spu'
|
||||
import {isEmpty} from "@/utils/is";
|
||||
|
||||
defineOptions({ name: 'ProductSpuSkuForm' })
|
||||
|
||||
@ -75,8 +106,18 @@ const props = defineProps({
|
||||
type: Object as PropType<Spu>,
|
||||
default: () => {}
|
||||
},
|
||||
isDetail: propTypes.bool.def(false) // 是否作为详情组件
|
||||
isBatch: propTypes.bool.def(false), // 是否作为批量操作组件
|
||||
isDetail: propTypes.bool.def(false), // 是否作为 sku 详情组件
|
||||
isComponent: propTypes.bool.def(false), // 是否作为 sku 选择组件
|
||||
isActivityComponent: propTypes.bool.def(false) // 是否作为 sku 活动配置组件
|
||||
})
|
||||
const ruleConfig: RuleConfig[] = [
|
||||
{
|
||||
name: 'paidMemberPrice',
|
||||
rule: (arg) => arg >= 0,
|
||||
message: '会员价必须大于等于 0 !!!'
|
||||
}
|
||||
]
|
||||
const attributesAddFormRef = ref() // 添加商品属性表单
|
||||
const formRef = ref() // 表单 Ref
|
||||
const propertyList = ref<PropertyAndValues[]>([]) // 商品属性列表
|
||||
@ -87,7 +128,12 @@ const formData = reactive<Spu>({
|
||||
recommendBest: 0, // 精品推荐
|
||||
recommendNew: 0, // 新品推荐
|
||||
recommendGood: 0, // 优品推荐
|
||||
onlyPaidMemberView: 0 // 仅限付费会员可见
|
||||
onlyPaidMemberView: 0, // 仅限付费会员可见
|
||||
isPaidMemberPrice: 0, //是否为付费会员价
|
||||
paidMemberPrice: 0, //付费会员价
|
||||
specType: false, //商品规格
|
||||
subCommissionType: false, // 分销类型
|
||||
skus: []
|
||||
})
|
||||
const rules = reactive({
|
||||
// specType: [required],
|
||||
|
@ -146,6 +146,7 @@ const getDetail = async () => {
|
||||
item.price = floatToFixed2(item.price)
|
||||
item.marketPrice = floatToFixed2(item.marketPrice)
|
||||
item.costPrice = floatToFixed2(item.costPrice)
|
||||
item.paidMemberPrice = floatToFixed2(item.paidMemberPrice)
|
||||
item.firstBrokeragePrice = floatToFixed2(item.firstBrokeragePrice)
|
||||
item.secondBrokeragePrice = floatToFixed2(item.secondBrokeragePrice)
|
||||
} else {
|
||||
@ -153,12 +154,19 @@ const getDetail = async () => {
|
||||
item.price = formatToFraction(item.price)
|
||||
item.marketPrice = formatToFraction(item.marketPrice)
|
||||
item.costPrice = formatToFraction(item.costPrice)
|
||||
item.paidMemberPrice = formatToFraction(item.paidMemberPrice)
|
||||
item.firstBrokeragePrice = formatToFraction(item.firstBrokeragePrice)
|
||||
item.secondBrokeragePrice = formatToFraction(item.secondBrokeragePrice)
|
||||
}
|
||||
})
|
||||
if (isDetail.value){
|
||||
res.paidMemberPrice = floatToFixed2(res.paidMemberPrice)
|
||||
} else {
|
||||
res.paidMemberPrice = formatToFraction(res.paidMemberPrice)
|
||||
}
|
||||
formData.value = res
|
||||
|
||||
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
@ -186,6 +194,7 @@ const submitForm = async () => {
|
||||
item.price = convertToInteger(item.price)
|
||||
item.marketPrice = convertToInteger(item.marketPrice)
|
||||
item.costPrice = convertToInteger(item.costPrice)
|
||||
item.paidMemberPrice = convertToInteger(item.paidMemberPrice)
|
||||
item.firstBrokeragePrice = convertToInteger(item.firstBrokeragePrice)
|
||||
item.secondBrokeragePrice = convertToInteger(item.secondBrokeragePrice)
|
||||
})
|
||||
|
@ -39,6 +39,11 @@ public class ProductSkuRespDTO {
|
||||
* 成本价,单位:分
|
||||
*/
|
||||
private Integer costPrice;
|
||||
/**
|
||||
* 付费会员价格,单位:分
|
||||
*
|
||||
*/
|
||||
private Integer paidMemberPrice;
|
||||
/**
|
||||
* SKU 的条形码
|
||||
*/
|
||||
|
@ -68,6 +68,11 @@ public class ProductSpuRespDTO {
|
||||
* 库存
|
||||
*/
|
||||
private Integer stock;
|
||||
/**
|
||||
* 付费会员价格,单位:分
|
||||
*
|
||||
*/
|
||||
private Integer paidMemberPrice;
|
||||
|
||||
// ========== 物流相关字段 =========
|
||||
|
||||
|
@ -48,4 +48,6 @@ public class ProductSkuRespVO {
|
||||
@Schema(description = "属性数组")
|
||||
private List<ProductSkuSaveReqVO.Property> properties;
|
||||
|
||||
@Schema(description = "商品价格,单位:分", example = "199")
|
||||
private Integer paidMemberPrice;
|
||||
}
|
||||
|
@ -50,6 +50,9 @@ public class ProductSkuSaveReqVO {
|
||||
@Schema(description = "二级分销的佣金,单位:分", example = "19")
|
||||
private Integer secondBrokeragePrice;
|
||||
|
||||
@Schema(description = "商品价格,单位:分", example = "199")
|
||||
private Integer paidMemberPrice;
|
||||
|
||||
@Schema(description = "属性数组")
|
||||
private List<Property> properties;
|
||||
|
||||
|
@ -89,6 +89,14 @@ public class ProductSpuRespVO {
|
||||
@Schema(description = "是否仅付费会员可见")
|
||||
@ExcelProperty("是否仅付费会员可见")
|
||||
private Integer onlyPaidMemberView;
|
||||
|
||||
@Schema(description = "是否为付费会员价")
|
||||
@ExcelProperty("是否为付费会员价")
|
||||
private Integer isPaidMemberPrice;
|
||||
|
||||
@Schema(description = " 商品价格,单位:分")
|
||||
@ExcelProperty("商品价格,单位:分")
|
||||
private Integer paidMemberPrice;
|
||||
// ========== SKU 相关字段 =========
|
||||
|
||||
@Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
|
@ -122,4 +122,12 @@ public class ProductSpuSaveReqVO {
|
||||
@Schema(description = "是否仅付费会员可见")
|
||||
@Valid
|
||||
private Integer onlyPaidMemberView;
|
||||
|
||||
@Schema(description = "是否为付费会员价")
|
||||
@Valid
|
||||
private Integer isPaidMemberPrice;
|
||||
|
||||
@Schema(description = " 商品价格,单位:分")
|
||||
@Valid
|
||||
private Integer paidMemberPrice;
|
||||
}
|
||||
|
@ -78,9 +78,20 @@ public class AppProductSpuController {
|
||||
// 拼接返回
|
||||
list.forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()));
|
||||
List<AppProductSpuRespVO> voList = BeanUtils.toBean(list, AppProductSpuRespVO.class);
|
||||
|
||||
// 处理 vip 价格
|
||||
MemberLevelRespDTO memberLevel = getMemberLevel();
|
||||
voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
//判断当前用户是否为付费会员
|
||||
if (memberUserApi.validUserActivate(getLoginUserId())){
|
||||
voList.forEach(vo -> {
|
||||
Integer priceToUse = vo.getPaidMemberPrice() != null ? vo.getPaidMemberPrice() : vo.getPrice();
|
||||
vo.setVipPrice(calculateVipPrice(priceToUse, memberLevel));
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
}
|
||||
return success(voList);
|
||||
}
|
||||
|
||||
@ -97,7 +108,16 @@ public class AppProductSpuController {
|
||||
PageResult<AppProductSpuRespVO> voPageResult = BeanUtils.toBean(pageResult, AppProductSpuRespVO.class);
|
||||
// 处理 vip 价格
|
||||
MemberLevelRespDTO memberLevel = getMemberLevel();
|
||||
voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
//判断当前用户是否为付费会员
|
||||
if (memberUserApi.validUserActivate(getLoginUserId())){
|
||||
voPageResult.getList().forEach(vo -> {
|
||||
Integer priceToUse = vo.getPaidMemberPrice() != null ? vo.getPaidMemberPrice() : vo.getPrice();
|
||||
vo.setVipPrice(calculateVipPrice(priceToUse, memberLevel));
|
||||
});
|
||||
}
|
||||
else {
|
||||
voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
}
|
||||
return success(voPageResult);
|
||||
}
|
||||
|
||||
@ -114,7 +134,16 @@ public class AppProductSpuController {
|
||||
PageResult<AppProductSpuRespVO> voPageResult = BeanUtils.toBean(pageResult, AppProductSpuRespVO.class);
|
||||
// 处理 vip 价格
|
||||
MemberLevelRespDTO memberLevel = getMemberLevel();
|
||||
voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
//判断当前用户是否为付费会员
|
||||
if (memberUserApi.validUserActivate(getLoginUserId())){
|
||||
voPageResult.getList().forEach(vo -> {
|
||||
Integer priceToUse = vo.getPaidMemberPrice() != null ? vo.getPaidMemberPrice() : vo.getPrice();
|
||||
vo.setVipPrice(calculateVipPrice(priceToUse, memberLevel));
|
||||
});
|
||||
}
|
||||
else {
|
||||
voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
}
|
||||
return success(voPageResult);
|
||||
}
|
||||
|
||||
@ -146,7 +175,13 @@ public class AppProductSpuController {
|
||||
spuVO.setProductBrand(productBrandService.getBrandByIdStatus(spu.getBrandId(), CommonStatusEnum.ENABLE.getStatus()));
|
||||
// 处理 vip 价格
|
||||
MemberLevelRespDTO memberLevel = getMemberLevel();
|
||||
spuVO.setVipPrice(calculateVipPrice(spuVO.getPrice(), memberLevel));
|
||||
//判断当前用户是否为付费会员
|
||||
if (memberUserApi.validUserActivate(getLoginUserId()) && spuVO.getPaidMemberPrice() != null){
|
||||
spuVO.setVipPrice(calculateVipPrice(spuVO.getPaidMemberPrice(), memberLevel));
|
||||
}
|
||||
else {
|
||||
spuVO.setVipPrice(calculateVipPrice(spuVO.getPrice(), memberLevel));
|
||||
}
|
||||
return success(spuVO);
|
||||
}
|
||||
|
||||
@ -215,7 +250,16 @@ public class AppProductSpuController {
|
||||
List<AppProductSpuRespVO> voList = BeanUtils.toBean(list, AppProductSpuRespVO.class);
|
||||
// 处理 vip 价格
|
||||
MemberLevelRespDTO memberLevel = getMemberLevel();
|
||||
voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
//判断当前用户是否为付费会员
|
||||
if (memberUserApi.validUserActivate(getLoginUserId())){
|
||||
voList.forEach(vo -> {
|
||||
Integer priceToUse = vo.getPaidMemberPrice() != null ? vo.getPaidMemberPrice() : vo.getPrice();
|
||||
vo.setVipPrice(calculateVipPrice(priceToUse, memberLevel));
|
||||
});
|
||||
}
|
||||
else {
|
||||
voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
}
|
||||
return success(voList);
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,9 @@ public class AppProductSpuDetailRespVO {
|
||||
@Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格
|
||||
private Integer vipPrice;
|
||||
|
||||
@Schema(description = "付费会员价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer paidMemberPrice;
|
||||
|
||||
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
|
||||
private Integer stock;
|
||||
|
||||
@ -87,6 +90,9 @@ public class AppProductSpuDetailRespVO {
|
||||
@Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格
|
||||
private Integer vipPrice;
|
||||
|
||||
@Schema(description = "付费会员价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer paidMemberPrice;
|
||||
|
||||
@Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
|
||||
private String picUrl;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.product.controller.app.spu.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@ -41,6 +42,9 @@ public class AppProductSpuRespVO {
|
||||
@Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格
|
||||
private Integer vipPrice;
|
||||
|
||||
@Schema(description = "付费会员价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer paidMemberPrice;
|
||||
|
||||
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
|
||||
private Integer stock;
|
||||
|
||||
|
@ -86,6 +86,11 @@ public class ProductSkuDO extends BaseDO {
|
||||
*/
|
||||
private Integer secondBrokeragePrice;
|
||||
|
||||
/**
|
||||
* 付费会员价格,单位:分
|
||||
*/
|
||||
private Integer paidMemberPrice;
|
||||
|
||||
// ========== 营销相关字段 =========
|
||||
|
||||
// ========== 统计相关字段 =========
|
||||
|
@ -121,6 +121,12 @@ public class ProductSpuDO extends BaseDO {
|
||||
*/
|
||||
private Integer onlyPaidMemberView;
|
||||
|
||||
/**
|
||||
* 是否为付费会员价
|
||||
*/
|
||||
private Integer isPaidMemberPrice;
|
||||
|
||||
|
||||
// ========== SKU 相关字段 =========
|
||||
|
||||
/**
|
||||
@ -148,6 +154,11 @@ public class ProductSpuDO extends BaseDO {
|
||||
* 基于其对应的 {@link ProductSkuDO#getCostPrice()} sku单价最低的商品的
|
||||
*/
|
||||
private Integer costPrice;
|
||||
/**
|
||||
* 付费会员价格,单位:分
|
||||
* 基于其对应的 {@link ProductSkuDO#getPaidMemberPrice()} ()} sku单价最低的商品的
|
||||
*/
|
||||
private Integer paidMemberPrice;
|
||||
/**
|
||||
* 库存
|
||||
*
|
||||
|
@ -113,6 +113,8 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
||||
spu.setMarketPrice(getMinValue(skus, ProductSkuSaveReqVO::getMarketPrice));
|
||||
// sku 单价最低的商品的成本价格
|
||||
spu.setCostPrice(getMinValue(skus, ProductSkuSaveReqVO::getCostPrice));
|
||||
// sku 单价最低的商品的付费会员价格
|
||||
spu.setPaidMemberPrice(getMinValue(skus, ProductSkuSaveReqVO::getPaidMemberPrice));
|
||||
// skus 库存总数
|
||||
spu.setStock(getSumValue(skus, ProductSkuSaveReqVO::getStock, Integer::sum));
|
||||
// 若是 spu 已有状态则不处理
|
||||
|
@ -23,6 +23,9 @@ public class AppProductSkuBaseRespVO {
|
||||
@Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
private Integer price;
|
||||
|
||||
@Schema(description = "付费会员价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
private Integer paidMemberPrice;
|
||||
|
||||
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer stock;
|
||||
|
||||
|
@ -61,6 +61,10 @@ public class AppTradeOrderSettlementRespVO {
|
||||
private Integer skuId;
|
||||
@Schema(description = "价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
private Integer price;
|
||||
|
||||
@Schema(description = "付费会员价(总),单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer paidMemberPrice;
|
||||
|
||||
@Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||
private String picUrl;
|
||||
|
||||
|
@ -252,7 +252,7 @@ public interface TradeOrderConvert {
|
||||
return respVO;
|
||||
}
|
||||
|
||||
AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address);
|
||||
AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address);
|
||||
|
||||
List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list);
|
||||
|
||||
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.service.price;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||
@ -57,6 +58,9 @@ public class TradePriceServiceImpl implements TradePriceService {
|
||||
@Resource
|
||||
private TradeDiscountActivityPriceCalculator discountActivityPriceCalculator;
|
||||
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
@Override
|
||||
public TradePriceCalculateRespBO calculateOrderPrice(TradePriceCalculateReqBO calculateReqBO) {
|
||||
// 1.1 获得商品 SKU 数组
|
||||
@ -64,9 +68,11 @@ public class TradePriceServiceImpl implements TradePriceService {
|
||||
// 1.2 获得商品 SPU 数组
|
||||
List<ProductSpuRespDTO> spuList = checkSpuList(skuList);
|
||||
|
||||
//判断是否为付费会员
|
||||
Boolean valid = memberUserApi.validUserActivate(calculateReqBO.getUserId());
|
||||
// 2.1 计算价格
|
||||
TradePriceCalculateRespBO calculateRespBO = TradePriceCalculatorHelper
|
||||
.buildCalculateResp(calculateReqBO, spuList, skuList);
|
||||
.buildCalculateResp(calculateReqBO, spuList, skuList,valid);
|
||||
priceCalculators.forEach(calculator -> calculator.calculate(calculateReqBO, calculateRespBO));
|
||||
// 2.2 如果最终支付金额小于等于 0,则抛出业务异常
|
||||
if (calculateReqBO.getPointActivityId() == null // 积分订单,允许支付金额为 0
|
||||
|
@ -97,7 +97,7 @@ public class TradePriceCalculateRespBO {
|
||||
/**
|
||||
* 商品原价(总),单位:分
|
||||
*
|
||||
* 基于 {@link OrderItem#getPrice()} * {@link OrderItem#getCount()} 求和
|
||||
* 基于 {@link OrderItem#getPrice()} || {@link OrderItem#getPaidMemberPrice()} * {@link OrderItem#getCount()} 求和
|
||||
*
|
||||
* 对应 taobao 的 trade.total_fee 字段
|
||||
*/
|
||||
@ -206,10 +206,15 @@ public class TradePriceCalculateRespBO {
|
||||
* VIP 减免金额,单位:分
|
||||
*/
|
||||
private Integer vipPrice;
|
||||
/**
|
||||
* 付费会员价格(总),单位:分
|
||||
*/
|
||||
private Integer paidMemberPrice;
|
||||
/**
|
||||
* 应付金额(总),单位:分
|
||||
*
|
||||
* = {@link #price} * {@link #count}
|
||||
* = {@link #price} || {@link #paidMemberPrice}
|
||||
* * {@link #count}
|
||||
* - {@link #couponPrice}
|
||||
* - {@link #pointPrice}
|
||||
* - {@link #discountPrice}
|
||||
|
@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO;
|
||||
@ -43,6 +44,9 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator {
|
||||
@Resource
|
||||
private CouponApi couponApi;
|
||||
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
@Override
|
||||
public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
|
||||
// 只有【普通】订单,才允许使用优惠劵
|
||||
@ -90,9 +94,18 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator {
|
||||
for (int i = 0; i < orderItems.size(); i++) {
|
||||
TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i);
|
||||
orderItem.setCouponPrice(divideCouponPrices.get(i));
|
||||
TradePriceCalculatorHelper.recountPayPrice(orderItem);
|
||||
if (memberUserApi.validUserActivate(param.getUserId()) && orderItem.getPaidMemberPrice() != null){
|
||||
TradePriceCalculatorHelper.recountPayPriceisPaidMember(orderItem);
|
||||
}
|
||||
else {
|
||||
TradePriceCalculatorHelper.recountPayPrice(orderItem);
|
||||
}
|
||||
}
|
||||
if (memberUserApi.validUserActivate(param.getUserId()) ){
|
||||
TradePriceCalculatorHelper.recountAllPriceisPaidMember(result);
|
||||
}else {
|
||||
TradePriceCalculatorHelper.recountAllPrice(result);
|
||||
}
|
||||
TradePriceCalculatorHelper.recountAllPrice(result);
|
||||
}
|
||||
|
||||
|
||||
|
@ -142,10 +142,16 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
|
||||
// 更新 SKU 的优惠金额
|
||||
orderItem.setVipPrice(vipPrice);
|
||||
}
|
||||
|
||||
// 4. 分摊优惠
|
||||
TradePriceCalculatorHelper.recountPayPrice(orderItem);
|
||||
TradePriceCalculatorHelper.recountAllPrice(result);
|
||||
//判断是否为会员且具有会员价
|
||||
if(memberUserApi.validUserActivate(param.getUserId()) && orderItem.getPaidMemberPrice() != null){
|
||||
TradePriceCalculatorHelper.recountPayPriceisPaidMember(orderItem);
|
||||
TradePriceCalculatorHelper.recountAllPriceisPaidMember(result);
|
||||
}
|
||||
else {
|
||||
TradePriceCalculatorHelper.recountPayPrice(orderItem);
|
||||
TradePriceCalculatorHelper.recountAllPrice(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -78,9 +78,18 @@ public class TradePointUsePriceCalculator implements TradePriceCalculator {
|
||||
TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i);
|
||||
orderItem.setPointPrice(dividePointPrices.get(i));
|
||||
orderItem.setUsePoint(divideUsePoints.get(i));
|
||||
TradePriceCalculatorHelper.recountPayPrice(orderItem);
|
||||
if(memberUserApi.validUserActivate(param.getUserId()) && orderItem.getPaidMemberPrice() != null ){
|
||||
TradePriceCalculatorHelper.recountPayPriceisPaidMember(orderItem);
|
||||
}
|
||||
else{
|
||||
TradePriceCalculatorHelper.recountPayPrice(orderItem);
|
||||
}
|
||||
}
|
||||
if(memberUserApi.validUserActivate(param.getUserId())){
|
||||
TradePriceCalculatorHelper.recountAllPriceisPaidMember(result);
|
||||
}else {
|
||||
TradePriceCalculatorHelper.recountAllPrice(result);
|
||||
}
|
||||
TradePriceCalculatorHelper.recountAllPrice(result);
|
||||
}
|
||||
|
||||
private boolean isDeductPointEnable(MemberConfigRespDTO config) {
|
||||
|
@ -29,7 +29,7 @@ import static java.util.Collections.singletonList;
|
||||
public class TradePriceCalculatorHelper {
|
||||
|
||||
public static TradePriceCalculateRespBO buildCalculateResp(TradePriceCalculateReqBO param,
|
||||
List<ProductSpuRespDTO> spuList, List<ProductSkuRespDTO> skuList) {
|
||||
List<ProductSpuRespDTO> spuList, List<ProductSkuRespDTO> skuList,Boolean valid) {
|
||||
// 创建 PriceCalculateRespDTO 对象
|
||||
TradePriceCalculateRespBO result = new TradePriceCalculateRespBO();
|
||||
result.setType(getOrderType(param)).setPromotions(new ArrayList<>()).setGiveCouponTemplateCounts(new LinkedHashMap<>());
|
||||
@ -53,8 +53,15 @@ public class TradePriceCalculatorHelper {
|
||||
orderItem.setSpuId(sku.getSpuId()).setSkuId(sku.getId())
|
||||
.setCount(item.getCount()).setCartId(item.getCartId()).setSelected(item.getSelected());
|
||||
// sku 价格
|
||||
orderItem.setPrice(sku.getPrice()).setPayPrice(sku.getPrice() * item.getCount())
|
||||
.setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0).setVipPrice(0);
|
||||
//判断当前订单的用户是否为付费会员
|
||||
if(valid && sku.getPaidMemberPrice() !=null){
|
||||
orderItem.setPrice(sku.getPrice()).setPayPrice(sku.getPaidMemberPrice() * item.getCount())
|
||||
.setPaidMemberPrice(sku.getPaidMemberPrice())
|
||||
.setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0).setVipPrice(0);
|
||||
}else {
|
||||
orderItem.setPrice(sku.getPrice()).setPayPrice(sku.getPrice() * item.getCount())
|
||||
.setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0).setVipPrice(0);
|
||||
}
|
||||
// sku 信息
|
||||
orderItem.setPicUrl(sku.getPicUrl()).setProperties(sku.getProperties())
|
||||
.setWeight(sku.getWeight()).setVolume(sku.getVolume());
|
||||
@ -69,7 +76,12 @@ public class TradePriceCalculatorHelper {
|
||||
|
||||
// 创建它的 Price 属性
|
||||
result.setPrice(new TradePriceCalculateRespBO.Price());
|
||||
recountAllPrice(result);
|
||||
if(valid){
|
||||
recountAllPriceisPaidMember(result);
|
||||
}
|
||||
else {
|
||||
recountAllPrice(result);
|
||||
}
|
||||
recountAllGivePoint(result);
|
||||
return result;
|
||||
}
|
||||
@ -96,6 +108,36 @@ public class TradePriceCalculatorHelper {
|
||||
return TradeOrderTypeEnum.NORMAL.getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于订单项,重新计算 price 总价
|
||||
*(付费会员)
|
||||
* @param result 计算结果
|
||||
*/
|
||||
public static void recountAllPriceisPaidMember(TradePriceCalculateRespBO result) {
|
||||
// 先重置
|
||||
TradePriceCalculateRespBO.Price price = result.getPrice();
|
||||
price.setTotalPrice(0).setDiscountPrice(0).setDeliveryPrice(0)
|
||||
.setCouponPrice(0).setPointPrice(0).setVipPrice(0).setPayPrice(0);
|
||||
// 再合计 item
|
||||
result.getItems().forEach(item -> {
|
||||
if (!item.getSelected()) {
|
||||
return;
|
||||
}
|
||||
if(item.getPaidMemberPrice() != null){
|
||||
price.setTotalPrice(price.getTotalPrice() + item.getPaidMemberPrice() * item.getCount());
|
||||
}
|
||||
else{
|
||||
price.setTotalPrice(price.getTotalPrice() + item.getPrice() * item.getCount());
|
||||
}
|
||||
price.setDiscountPrice(price.getDiscountPrice() + item.getDiscountPrice());
|
||||
price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice());
|
||||
price.setCouponPrice(price.getCouponPrice() + item.getCouponPrice());
|
||||
price.setPointPrice(price.getPointPrice() + item.getPointPrice());
|
||||
price.setVipPrice(price.getVipPrice() + item.getVipPrice());
|
||||
price.setPayPrice(price.getPayPrice() + item.getPayPrice());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于订单项,重新计算 price 总价
|
||||
*
|
||||
@ -130,6 +172,32 @@ public class TradePriceCalculatorHelper {
|
||||
result.setGivePoint(getSumValue(result.getItems(), item -> item.getSelected() ? item.getGivePoint() : 0, Integer::sum));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新计算单个订单项的支付金额
|
||||
*(付费会员)
|
||||
* @param orderItem 订单项
|
||||
*/
|
||||
public static void recountPayPriceisPaidMember(TradePriceCalculateRespBO.OrderItem orderItem) {
|
||||
if(orderItem.getPaidMemberPrice() != null){
|
||||
orderItem.setPayPrice(orderItem.getPaidMemberPrice() * orderItem.getCount()
|
||||
- orderItem.getDiscountPrice()
|
||||
+ orderItem.getDeliveryPrice()
|
||||
- orderItem.getCouponPrice()
|
||||
- orderItem.getPointPrice()
|
||||
- orderItem.getVipPrice()
|
||||
);
|
||||
}
|
||||
else {
|
||||
orderItem.setPayPrice(orderItem.getPrice() * orderItem.getCount()
|
||||
- orderItem.getDiscountPrice()
|
||||
+ orderItem.getDeliveryPrice()
|
||||
- orderItem.getCouponPrice()
|
||||
- orderItem.getPointPrice()
|
||||
- orderItem.getVipPrice()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新计算单个订单项的支付金额
|
||||
*
|
||||
|
@ -65,4 +65,13 @@ public interface MemberUserApi {
|
||||
*/
|
||||
void validateUser(Long id);
|
||||
|
||||
|
||||
/**
|
||||
* 校验用户是否为付费会员
|
||||
*
|
||||
* @param id 用户编号
|
||||
* @return 用户信息
|
||||
*/
|
||||
Boolean validUserActivate(Long id);
|
||||
|
||||
}
|
||||
|
@ -56,4 +56,9 @@ public class MemberUserRespDTO {
|
||||
*/
|
||||
private Integer point;
|
||||
|
||||
/**
|
||||
* 是否绑过卡,是否开通过会员(0:未开通,1:试用,2:有效期,3:永久,4:过期)
|
||||
*/
|
||||
private Integer activate;
|
||||
|
||||
}
|
||||
|
@ -55,4 +55,14 @@ public class MemberUserApiImpl implements MemberUserApi {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean validUserActivate(Long id) {
|
||||
MemberUserDO user = userService.getUser(id);
|
||||
if (user.getActivate() == 0 || user.getActivate() == 4){
|
||||
return false;
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user