Browse Source

消费记录列表

fanzherong_v 3 months ago
parent
commit
54ac49bc0f
16 changed files with 1133 additions and 0 deletions
  1. 28 0
      snowy-admin-web/src/api/biz/consumptionRecordApi.js
  2. 94 0
      snowy-admin-web/src/views/biz/consumptionrecord/form.vue
  3. 132 0
      snowy-admin-web/src/views/biz/consumptionrecord/index.vue
  4. 94 0
      snowy-admin-web/src/views/biz/member/consumption.vue
  5. 7 0
      snowy-admin-web/src/views/biz/member/index.vue
  6. 123 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/controller/ConsumptionRecordController.java
  7. 99 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/entity/ConsumptionRecord.java
  8. 34 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/enums/ConsumptionRecordEnum.java
  9. 25 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/mapper/ConsumptionRecordMapper.java
  10. 5 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/mapper/mapping/ConsumptionRecordMapper.xml
  11. 70 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/param/ConsumptionRecordAddParam.java
  12. 75 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/param/ConsumptionRecordEditParam.java
  13. 35 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/param/ConsumptionRecordIdParam.java
  14. 51 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/param/ConsumptionRecordPageParam.java
  15. 80 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/service/ConsumptionRecordService.java
  16. 181 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/service/impl/ConsumptionRecordServiceImpl.java

+ 28 - 0
snowy-admin-web/src/api/biz/consumptionRecordApi.js

@@ -0,0 +1,28 @@
+import { baseRequest } from '@/utils/request'
+
+const request = (url, ...arg) => baseRequest(`/biz/consumptionrecord/` + url, ...arg)
+
+/**
+ * 消费记录Api接口管理器
+ *
+ * @author fanzherong
+ * @date  2025/02/06 08:56
+ **/
+export default {
+	// 获取消费记录分页
+	consumptionRecordPage(data) {
+		return request('page', data, 'get')
+	},
+	// 提交消费记录表单 edit为true时为编辑,默认为新增
+	consumptionRecordSubmitForm(data, edit = false) {
+		return request(edit ? 'edit' : 'add', data)
+	},
+	// 删除消费记录
+	consumptionRecordDelete(data) {
+		return request('delete', data)
+	},
+	// 获取消费记录详情
+	consumptionRecordDetail(data) {
+		return request('detail', data, 'get')
+	}
+}

+ 94 - 0
snowy-admin-web/src/views/biz/consumptionrecord/form.vue

@@ -0,0 +1,94 @@
+<template>
+	<xn-form-container
+		:title="formData.id ? '编辑消费记录' : '增加消费记录'"
+		:width="700"
+		v-model:open="open"
+		:destroy-on-close="true"
+		@close="onClose"
+	>
+		<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
+			<a-form-item label="用户id:" name="userId">
+				<a-input v-model:value="formData.userId" placeholder="请输入用户id" allow-clear />
+			</a-form-item>
+			<a-form-item label="消费方式 1:代金券消费   2:余额消费  3:代金券+余额:" name="consumptionType">
+				<a-input v-model:value="formData.consumptionType" placeholder="请输入消费方式 1:代金券消费   2:余额消费  3:代金券+余额" allow-clear />
+			</a-form-item>
+			<a-form-item label="代金券消费金额:" name="voucherMoney">
+				<a-input v-model:value="formData.voucherMoney" placeholder="请输入代金券消费金额" allow-clear />
+			</a-form-item>
+			<a-form-item label="账户消费金额:" name="accountMoney">
+				<a-input v-model:value="formData.accountMoney" placeholder="请输入账户消费金额" allow-clear />
+			</a-form-item>
+			<a-form-item label="消费时间:" name="consumptionTime">
+				<a-date-picker v-model:value="formData.consumptionTime" value-format="YYYY-MM-DD HH:mm:ss" show-time placeholder="请选择消费时间" style="width: 100%" />
+			</a-form-item>
+			<a-form-item label="消费门店:" name="consumptionOrg">
+				<a-input v-model:value="formData.consumptionOrg" placeholder="请输入消费门店" allow-clear />
+			</a-form-item>
+			<a-form-item label="备注:" name="consumptionRemark">
+				<a-input v-model:value="formData.consumptionRemark" placeholder="请输入备注" allow-clear />
+			</a-form-item>
+			<a-form-item label="操作:1:赠送  2:扣减  3:消费:" name="consumptionOperate">
+				<a-input v-model:value="formData.consumptionOperate" placeholder="请输入操作:1:赠送  2:扣减  3:消费" allow-clear />
+			</a-form-item>
+		</a-form>
+		<template #footer>
+			<a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
+			<a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
+		</template>
+	</xn-form-container>
+</template>
+
+<script setup name="consumptionRecordForm">
+	import { cloneDeep } from 'lodash-es'
+	import { required } from '@/utils/formRules'
+	import consumptionRecordApi from '@/api/biz/consumptionRecordApi'
+	// 抽屉状态
+	const open = ref(false)
+	const emit = defineEmits({ successful: null })
+	const formRef = ref()
+	// 表单数据
+	const formData = ref({})
+	const submitLoading = ref(false)
+
+	// 打开抽屉
+	const onOpen = (record) => {
+		open.value = true
+		if (record) {
+			let recordData = cloneDeep(record)
+			formData.value = Object.assign({}, recordData)
+		}
+	}
+	// 关闭抽屉
+	const onClose = () => {
+		formRef.value.resetFields()
+		formData.value = {}
+		open.value = false
+	}
+	// 默认要校验的
+	const formRules = {
+	}
+	// 验证并提交数据
+	const onSubmit = () => {
+		formRef.value
+			.validate()
+			.then(() => {
+				submitLoading.value = true
+				const formDataParam = cloneDeep(formData.value)
+				consumptionRecordApi
+					.consumptionRecordSubmitForm(formDataParam, formDataParam.id)
+					.then(() => {
+						onClose()
+						emit('successful')
+					})
+					.finally(() => {
+						submitLoading.value = false
+					})
+			})
+			.catch(() => {})
+	}
+	// 抛出函数
+	defineExpose({
+		onOpen
+	})
+</script>

+ 132 - 0
snowy-admin-web/src/views/biz/consumptionrecord/index.vue

@@ -0,0 +1,132 @@
+<template>
+	<a-card :bordered="false">
+		<s-table
+			ref="tableRef"
+			:columns="columns"
+			:data="loadData"
+			bordered
+			:row-key="(record) => record.id"
+		>
+			<template #operator class="table-operator">
+				<a-space>
+					<a-button type="primary" @click="formRef.onOpen()" v-if="hasPerm('consumptionRecordAdd')">
+						<template #icon><plus-outlined /></template>
+						新增
+					</a-button>
+					<xn-batch-button
+						v-if="hasPerm('consumptionRecordBatchDelete')"
+						buttonName="批量删除"
+                        icon="DeleteOutlined"
+						:selectedRowKeys="selectedRowKeys"
+						@batchCallBack="deleteBatchConsumptionRecord"
+					/>
+				</a-space>
+			</template>
+			<template #bodyCell="{ column, record }">
+				<template v-if="column.dataIndex === 'action'">
+					<a-space>
+						<a @click="formRef.onOpen(record)" v-if="hasPerm('consumptionRecordEdit')">编辑</a>
+						<a-divider type="vertical" v-if="hasPerm(['consumptionRecordEdit', 'consumptionRecordDelete'], 'and')" />
+						<a-popconfirm title="确定要删除吗?" @confirm="deleteConsumptionRecord(record)">
+							<a-button type="link" danger size="small" v-if="hasPerm('consumptionRecordDelete')">删除</a-button>
+						</a-popconfirm>
+					</a-space>
+				</template>
+			</template>
+		</s-table>
+	</a-card>
+	<Form ref="formRef" @successful="tableRef.refresh()" />
+</template>
+
+<script setup name="consumptionrecord">
+	import { cloneDeep } from 'lodash-es'
+	import Form from './form.vue'
+	import consumptionRecordApi from '@/api/biz/consumptionRecordApi'
+	const tableRef = ref()
+	const formRef = ref()
+	const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
+	const columns = [
+		{
+			title: '用户id',
+			dataIndex: 'userId',
+			align: 'center',
+		},
+		{
+			title: '消费操作',
+			dataIndex: 'consumptionOperate',
+			align: 'center',
+		},
+		{
+			title: '消费金额',
+			dataIndex: 'consumptionMoney',
+			align: 'center',
+		},
+		{
+			title: '消费时间',
+			dataIndex: 'consumptionTime',
+			align: 'center',
+		},
+		{
+			title: '消费门店',
+			dataIndex: 'consumptionOrg',
+			align: 'center',
+		},
+		{
+			title: '备注',
+			dataIndex: 'consumptionRemark',
+			align: 'center',
+		},
+	]
+	// 操作栏通过权限判断是否显示
+	/*if (hasPerm(['consumptionRecordEdit', 'consumptionRecordDelete'])) {
+		columns.push({
+			title: '操作',
+			dataIndex: 'action',
+			align: 'center',
+			width: 150
+		})
+	}*/
+	const selectedRowKeys = ref([])
+	// 列表选择配置
+	const options = {
+		// columns数字类型字段加入 needTotal: true 可以勾选自动算账
+		alert: {
+			show: true,
+			clear: () => {
+				selectedRowKeys.value = ref([])
+			}
+		},
+		rowSelection: {
+			onChange: (selectedRowKey, selectedRows) => {
+				selectedRowKeys.value = selectedRowKey
+			}
+		}
+	}
+	const loadData = (parameter) => {
+		return consumptionRecordApi.consumptionRecordPage(parameter).then((data) => {
+			return data
+		})
+	}
+	// 重置
+	const reset = () => {
+		searchFormRef.value.resetFields()
+		tableRef.value.refresh(true)
+	}
+	// 删除
+	const deleteConsumptionRecord = (record) => {
+		let params = [
+			{
+				id: record.id
+			}
+		]
+		consumptionRecordApi.consumptionRecordDelete(params).then(() => {
+			tableRef.value.refresh(true)
+		})
+	}
+	// 批量删除
+	const deleteBatchConsumptionRecord = (params) => {
+		consumptionRecordApi.consumptionRecordDelete(params).then(() => {
+			tableRef.value.clearRefreshSelected()
+		})
+	}
+</script>

+ 94 - 0
snowy-admin-web/src/views/biz/member/consumption.vue

@@ -0,0 +1,94 @@
+<template>
+	<xn-form-container
+		:title="formData.id ? '编辑消费记录' : '增加消费记录'"
+		:width="700"
+		v-model:open="open"
+		:destroy-on-close="true"
+		@close="onClose"
+	>
+		<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
+			<a-form-item label="用户id:" name="userId">
+				<a-input v-model:value="formData.userId" placeholder="请输入用户id" allow-clear />
+			</a-form-item>
+			<a-form-item label="消费方式 1:代金券消费   2:余额消费  3:代金券+余额:" name="consumptionType">
+				<a-input v-model:value="formData.consumptionType" placeholder="请输入消费方式 1:代金券消费   2:余额消费  3:代金券+余额" allow-clear />
+			</a-form-item>
+			<a-form-item label="代金券消费金额:" name="voucherMoney">
+				<a-input v-model:value="formData.voucherMoney" placeholder="请输入代金券消费金额" allow-clear />
+			</a-form-item>
+			<a-form-item label="账户消费金额:" name="accountMoney">
+				<a-input v-model:value="formData.accountMoney" placeholder="请输入账户消费金额" allow-clear />
+			</a-form-item>
+			<a-form-item label="消费时间:" name="consumptionTime">
+				<a-date-picker v-model:value="formData.consumptionTime" value-format="YYYY-MM-DD HH:mm:ss" show-time placeholder="请选择消费时间" style="width: 100%" />
+			</a-form-item>
+			<a-form-item label="消费门店:" name="consumptionOrg">
+				<a-input v-model:value="formData.consumptionOrg" placeholder="请输入消费门店" allow-clear />
+			</a-form-item>
+			<a-form-item label="备注:" name="consumptionRemark">
+				<a-input v-model:value="formData.consumptionRemark" placeholder="请输入备注" allow-clear />
+			</a-form-item>
+			<a-form-item label="操作:1:赠送  2:扣减  3:消费:" name="consumptionOperate">
+				<a-input v-model:value="formData.consumptionOperate" placeholder="请输入操作:1:赠送  2:扣减  3:消费" allow-clear />
+			</a-form-item>
+		</a-form>
+		<template #footer>
+			<a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
+			<a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
+		</template>
+	</xn-form-container>
+</template>
+
+<script setup name="consumptionRecordForm">
+	import { cloneDeep } from 'lodash-es'
+	import { required } from '@/utils/formRules'
+	import consumptionRecordApi from '@/api/biz/consumptionRecordApi'
+	// 抽屉状态
+	const open = ref(false)
+	const emit = defineEmits({ successful: null })
+	const formRef = ref()
+	// 表单数据
+	const formData = ref({})
+	const submitLoading = ref(false)
+
+	// 打开抽屉
+	const onOpen = (record) => {
+		open.value = true
+		if (record) {
+			let recordData = cloneDeep(record)
+			formData.value = Object.assign({}, recordData)
+		}
+	}
+	// 关闭抽屉
+	const onClose = () => {
+		formRef.value.resetFields()
+		formData.value = {}
+		open.value = false
+	}
+	// 默认要校验的
+	const formRules = {
+	}
+	// 验证并提交数据
+	const onSubmit = () => {
+		formRef.value
+			.validate()
+			.then(() => {
+				submitLoading.value = true
+				const formDataParam = cloneDeep(formData.value)
+				consumptionRecordApi
+					.consumptionRecordSubmitForm(formDataParam, formDataParam.id)
+					.then(() => {
+						onClose()
+						emit('successful')
+					})
+					.finally(() => {
+						submitLoading.value = false
+					})
+			})
+			.catch(() => {})
+	}
+	// 抛出函数
+	defineExpose({
+		onOpen
+	})
+</script>

+ 7 - 0
snowy-admin-web/src/views/biz/member/index.vue

@@ -49,14 +49,21 @@
 				</template>
 				<template v-if="column.dataIndex === 'action'">
 					<a @click="formRef.onOpen(record)" v-if="hasPerm('bizUserEdit')">余额调整</a>
+					<a-divider type="vertical" v-if="hasPerm('bizUserConsumption')"/>
+					<a @click="consumptionRef.onOpen(record)" v-if="hasPerm('bizUserConsumption')">消费结算</a>
 				</template>
 			</template>
 		</s-table>
 	</a-card>
+	<Consumption ref="consumptionRef" @successful="tableRef.refresh()" />
 </template>
 <script setup name="bizUser">
 	import tool from '@/utils/tool'
 	import bizUserApi from '@/api/biz/bizUserApi'
+	import Form from "@/views/biz/consumptionrecord/form.vue";
+	import Consumption from './consumption.vue'
+
+	const consumptionRef = ref()
 
 	const columns = [
 		{

+ 123 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/controller/ConsumptionRecordController.java

@@ -0,0 +1,123 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.consumptionrecord.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+import vip.xiaonuo.common.annotation.CommonLog;
+import vip.xiaonuo.common.pojo.CommonResult;
+import vip.xiaonuo.biz.modular.consumptionrecord.entity.ConsumptionRecord;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordAddParam;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordEditParam;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordIdParam;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordPageParam;
+import vip.xiaonuo.biz.modular.consumptionrecord.service.ConsumptionRecordService;
+
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotEmpty;
+import java.util.List;
+
+/**
+ * 消费记录控制器
+ *
+ * @author fanzherong
+ * @date  2025/02/06 08:56
+ */
+@Tag(name = "消费记录控制器")
+@RestController
+@Validated
+public class ConsumptionRecordController {
+
+    @Resource
+    private ConsumptionRecordService consumptionRecordService;
+
+    /**
+     * 获取消费记录分页
+     *
+     * @author fanzherong
+     * @date  2025/02/06 08:56
+     */
+    @Operation(summary = "获取消费记录分页")
+    @SaCheckPermission("/biz/consumptionrecord/page")
+    @GetMapping("/biz/consumptionrecord/page")
+    public CommonResult<Page<ConsumptionRecord>> page(ConsumptionRecordPageParam consumptionRecordPageParam) {
+        return CommonResult.data(consumptionRecordService.page(consumptionRecordPageParam));
+    }
+
+    /**
+     * 添加消费记录
+     *
+     * @author fanzherong
+     * @date  2025/02/06 08:56
+     */
+    @Operation(summary = "消费结算&会员管理赠送消费")
+    @CommonLog("消费结算&会员管理赠送消费")
+    @SaCheckPermission("/biz/consumptionrecord/add")
+    @PostMapping("/biz/consumptionrecord/add")
+    public CommonResult<String> add(@RequestBody @Valid ConsumptionRecordAddParam consumptionRecordAddParam) {
+        consumptionRecordService.add(consumptionRecordAddParam);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 编辑消费记录
+     *
+     * @author fanzherong
+     * @date  2025/02/06 08:56
+     */
+    @Operation(summary = "编辑消费记录")
+    @CommonLog("编辑消费记录")
+    @SaCheckPermission("/biz/consumptionrecord/edit")
+    @PostMapping("/biz/consumptionrecord/edit")
+    public CommonResult<String> edit(@RequestBody @Valid ConsumptionRecordEditParam consumptionRecordEditParam) {
+        consumptionRecordService.edit(consumptionRecordEditParam);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 删除消费记录
+     *
+     * @author fanzherong
+     * @date  2025/02/06 08:56
+     */
+    @Operation(summary = "删除消费记录")
+    @CommonLog("删除消费记录")
+    @SaCheckPermission("/biz/consumptionrecord/delete")
+    @PostMapping("/biz/consumptionrecord/delete")
+    public CommonResult<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
+                                                   List<ConsumptionRecordIdParam> consumptionRecordIdParamList) {
+        consumptionRecordService.delete(consumptionRecordIdParamList);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 获取消费记录详情
+     *
+     * @author fanzherong
+     * @date  2025/02/06 08:56
+     */
+    @Operation(summary = "获取消费记录详情")
+    @SaCheckPermission("/biz/consumptionrecord/detail")
+    @GetMapping("/biz/consumptionrecord/detail")
+    public CommonResult<ConsumptionRecord> detail(@Valid ConsumptionRecordIdParam consumptionRecordIdParam) {
+        return CommonResult.data(consumptionRecordService.detail(consumptionRecordIdParam));
+    }
+}

+ 99 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/entity/ConsumptionRecord.java

@@ -0,0 +1,99 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.consumptionrecord.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 消费记录实体
+ *
+ * @author fanzherong
+ * @date  2025/02/06 08:56
+ **/
+@Getter
+@Setter
+@TableName("consumption_record")
+public class ConsumptionRecord {
+
+    /** 主键ID */
+    @TableId
+    @Schema(description = "主键ID")
+    private String id;
+
+    /** 用户id */
+    @Schema(description = "用户id")
+    private String userId;
+
+    /** 消费方式 1:代金券消费   2:余额消费  3:代金券+余额 */
+    @Schema(description = "消费方式 1:代金券消费   2:余额消费  3:代金券+余额")
+    private String consumptionType;
+
+    /** 代金券消费金额 */
+    @Schema(description = "代金券消费金额")
+    private BigDecimal voucherMoney;
+
+    /** 账户消费金额 */
+    @Schema(description = "账户消费金额")
+    private BigDecimal accountMoney;
+
+    /** 消费时间 */
+    @Schema(description = "消费时间")
+    private Date consumptionTime;
+
+    /** 消费门店 */
+    @Schema(description = "消费门店")
+    private String consumptionOrg;
+
+    /** 备注 */
+    @Schema(description = "备注")
+    private String consumptionRemark;
+
+    /** 删除标识 */
+    @Schema(description = "删除标识")
+    @TableLogic
+    @TableField(fill = FieldFill.INSERT)
+    private String deleteFlag;
+
+    /** 创建时间 */
+    @Schema(description = "创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    private Date createTime;
+
+    /** 创建人 */
+    @Schema(description = "创建人")
+    @TableField(fill = FieldFill.INSERT)
+    private String createUser;
+
+    /** 修改时间 */
+    @Schema(description = "修改时间")
+    @TableField(fill = FieldFill.UPDATE)
+    private Date updateTime;
+
+    /** 修改人 */
+    @Schema(description = "修改人")
+    @TableField(fill = FieldFill.UPDATE)
+    private String updateUser;
+
+    /** 操作:1:赠送  2:扣减  3:消费 */
+    @Schema(description = "操作:1:赠送  2:扣减  3:消费")
+    private String consumptionOperate;
+
+    /**总金额*/
+    @Schema(description = "总金额")
+    private BigDecimal consumptionMoney;
+}

+ 34 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/enums/ConsumptionRecordEnum.java

@@ -0,0 +1,34 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.consumptionrecord.enums;
+
+import lombok.Getter;
+
+/**
+ * 消费记录枚举
+ *
+ * @author fanzherong
+ * @date  2025/02/06 08:56
+ **/
+@Getter
+public enum ConsumptionRecordEnum {
+
+    /** 测试 */
+    TEST("TEST");
+
+    private final String value;
+
+    ConsumptionRecordEnum(String value) {
+        this.value = value;
+    }
+}

+ 25 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/mapper/ConsumptionRecordMapper.java

@@ -0,0 +1,25 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.consumptionrecord.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import vip.xiaonuo.biz.modular.consumptionrecord.entity.ConsumptionRecord;
+
+/**
+ * 消费记录Mapper接口
+ *
+ * @author fanzherong
+ * @date  2025/02/06 08:56
+ **/
+public interface ConsumptionRecordMapper extends BaseMapper<ConsumptionRecord> {
+}

+ 5 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/mapper/mapping/ConsumptionRecordMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="vip.xiaonuo.biz.modular.consumptionrecord.mapper.ConsumptionRecordMapper">
+
+</mapper>

+ 70 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/param/ConsumptionRecordAddParam.java

@@ -0,0 +1,70 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.consumptionrecord.param;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 消费记录添加参数
+ *
+ * @author fanzherong
+ * @date  2025/02/06 08:56
+ **/
+@Getter
+@Setter
+public class ConsumptionRecordAddParam {
+
+    /** 用户id */
+    @Schema(description = "用户id")
+    private String userId;
+
+    /** 消费方式 1:代金券消费   2:余额消费  3:代金券+余额 */
+    @Schema(description = "消费方式 1:代金券消费   2:余额消费  3:代金券+余额")
+    private String consumptionType;
+
+    /** 代金券消费金额 */
+    @Schema(description = "代金券消费金额")
+    private BigDecimal voucherMoney;
+
+    /** 账户消费金额 */
+    @Schema(description = "账户消费金额")
+    private BigDecimal accountMoney;
+
+    /** 消费时间 */
+    @Schema(description = "消费时间")
+    private Date consumptionTime;
+
+    /** 消费门店 */
+    @Schema(description = "消费门店")
+    private String consumptionOrg;
+
+    /** 备注 */
+    @Schema(description = "备注")
+    private String consumptionRemark;
+
+    /** 操作:1:赠送  2:扣减  3:消费 */
+    @Schema(description = "操作:1:赠送  2:扣减  3:消费")
+    private String consumptionOperate;
+
+    /**总金额*/
+    @Schema(description = "总金额")
+    private BigDecimal consumptionMoney;
+
+}

+ 75 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/param/ConsumptionRecordEditParam.java

@@ -0,0 +1,75 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.consumptionrecord.param;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 消费记录编辑参数
+ *
+ * @author fanzherong
+ * @date  2025/02/06 08:56
+ **/
+@Getter
+@Setter
+public class ConsumptionRecordEditParam {
+
+    /** 主键ID */
+    @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotBlank(message = "id不能为空")
+    private String id;
+
+    /** 用户id */
+    @Schema(description = "用户id")
+    private String userId;
+
+    /** 消费方式 1:代金券消费   2:余额消费  3:代金券+余额 */
+    @Schema(description = "消费方式 1:代金券消费   2:余额消费  3:代金券+余额")
+    private String consumptionType;
+
+    /** 代金券消费金额 */
+    @Schema(description = "代金券消费金额")
+    private BigDecimal voucherMoney;
+
+    /** 账户消费金额 */
+    @Schema(description = "账户消费金额")
+    private BigDecimal accountMoney;
+
+    /** 消费时间 */
+    @Schema(description = "消费时间")
+    private Date consumptionTime;
+
+    /** 消费门店 */
+    @Schema(description = "消费门店")
+    private String consumptionOrg;
+
+    /** 备注 */
+    @Schema(description = "备注")
+    private String consumptionRemark;
+
+    /** 操作:1:赠送  2:扣减  3:消费 */
+    @Schema(description = "操作:1:赠送  2:扣减  3:消费")
+    private String consumptionOperate;
+
+    /**总金额*/
+    @Schema(description = "总金额")
+    private BigDecimal consumptionMoney;
+
+}

+ 35 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/param/ConsumptionRecordIdParam.java

@@ -0,0 +1,35 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.consumptionrecord.param;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+
+import jakarta.validation.constraints.NotBlank;
+
+/**
+ * 消费记录Id参数
+ *
+ * @author fanzherong
+ * @date  2025/02/06 08:56
+ **/
+@Getter
+@Setter
+public class ConsumptionRecordIdParam {
+
+    /** 主键ID */
+    @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotBlank(message = "id不能为空")
+    private String id;
+}

+ 51 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/param/ConsumptionRecordPageParam.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.consumptionrecord.param;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 消费记录查询参数
+ *
+ * @author fanzherong
+ * @date  2025/02/06 08:56
+ **/
+@Getter
+@Setter
+public class ConsumptionRecordPageParam {
+
+    /** 当前页 */
+    @Schema(description = "当前页码")
+    private Integer current;
+
+    /** 每页条数 */
+    @Schema(description = "每页条数")
+    private Integer size;
+
+    /** 排序字段 */
+    @Schema(description = "排序字段,字段驼峰名称,如:userName")
+    private String sortField;
+
+    /** 排序方式 */
+    @Schema(description = "排序方式,升序:ASCEND;降序:DESCEND")
+    private String sortOrder;
+
+    /** 关键词 */
+    @Schema(description = "关键词")
+    private String searchKey;
+
+}

+ 80 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/service/ConsumptionRecordService.java

@@ -0,0 +1,80 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.consumptionrecord.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import vip.xiaonuo.biz.modular.consumptionrecord.entity.ConsumptionRecord;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordAddParam;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordEditParam;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordIdParam;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordPageParam;
+
+import java.util.List;
+
+/**
+ * 消费记录Service接口
+ *
+ * @author fanzherong
+ * @date  2025/02/06 08:56
+ **/
+public interface ConsumptionRecordService extends IService<ConsumptionRecord> {
+
+    /**
+     * 获取消费记录分页
+     *
+     * @author fanzherong
+     * @date  2025/02/06 08:56
+     */
+    Page<ConsumptionRecord> page(ConsumptionRecordPageParam consumptionRecordPageParam);
+
+    /**
+     * 添加消费记录
+     *
+     * @author fanzherong
+     * @date  2025/02/06 08:56
+     */
+    void add(ConsumptionRecordAddParam consumptionRecordAddParam);
+
+    /**
+     * 编辑消费记录
+     *
+     * @author fanzherong
+     * @date  2025/02/06 08:56
+     */
+    void edit(ConsumptionRecordEditParam consumptionRecordEditParam);
+
+    /**
+     * 删除消费记录
+     *
+     * @author fanzherong
+     * @date  2025/02/06 08:56
+     */
+    void delete(List<ConsumptionRecordIdParam> consumptionRecordIdParamList);
+
+    /**
+     * 获取消费记录详情
+     *
+     * @author fanzherong
+     * @date  2025/02/06 08:56
+     */
+    ConsumptionRecord detail(ConsumptionRecordIdParam consumptionRecordIdParam);
+
+    /**
+     * 获取消费记录详情
+     *
+     * @author fanzherong
+     * @date  2025/02/06 08:56
+     **/
+    ConsumptionRecord queryEntity(String id);
+}

+ 181 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/consumptionrecord/service/impl/ConsumptionRecordServiceImpl.java

@@ -0,0 +1,181 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.consumptionrecord.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollStreamUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import jakarta.annotation.Resource;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import vip.xiaonuo.biz.modular.user.entity.BizUser;
+import vip.xiaonuo.biz.modular.user.service.BizUserService;
+import vip.xiaonuo.common.enums.CommonSortOrderEnum;
+import vip.xiaonuo.common.exception.CommonException;
+import vip.xiaonuo.common.page.CommonPageRequest;
+import vip.xiaonuo.biz.modular.consumptionrecord.entity.ConsumptionRecord;
+import vip.xiaonuo.biz.modular.consumptionrecord.mapper.ConsumptionRecordMapper;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordAddParam;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordEditParam;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordIdParam;
+import vip.xiaonuo.biz.modular.consumptionrecord.param.ConsumptionRecordPageParam;
+import vip.xiaonuo.biz.modular.consumptionrecord.service.ConsumptionRecordService;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 消费记录Service接口实现类
+ *
+ * @author fanzherong
+ * @date  2025/02/06 08:56
+ **/
+@Service
+public class ConsumptionRecordServiceImpl extends ServiceImpl<ConsumptionRecordMapper, ConsumptionRecord> implements ConsumptionRecordService {
+
+    @Resource
+    private BizUserService bizUserService;
+
+    @Override
+    public Page<ConsumptionRecord> page(ConsumptionRecordPageParam consumptionRecordPageParam) {
+        QueryWrapper<ConsumptionRecord> queryWrapper = new QueryWrapper<ConsumptionRecord>().checkSqlInjection();
+        if(ObjectUtil.isAllNotEmpty(consumptionRecordPageParam.getSortField(), consumptionRecordPageParam.getSortOrder())) {
+            CommonSortOrderEnum.validate(consumptionRecordPageParam.getSortOrder());
+            queryWrapper.orderBy(true, consumptionRecordPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
+                    StrUtil.toUnderlineCase(consumptionRecordPageParam.getSortField()));
+        } else {
+            queryWrapper.lambda().orderByAsc(ConsumptionRecord::getId);
+        }
+        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void add(ConsumptionRecordAddParam consumptionRecordAddParam) {
+        //前置参数校验
+        checkParam(consumptionRecordAddParam);
+        ConsumptionRecord consumptionRecord = BeanUtil.toBean(consumptionRecordAddParam, ConsumptionRecord.class);
+        //获取用户信息
+        BizUser bizUser = bizUserService.getById(consumptionRecordAddParam.getUserId());
+        if(StringUtils.equals(consumptionRecordAddParam.getConsumptionOperate(),"1")){
+            //会员赠送
+            if(StringUtils.equals(consumptionRecordAddParam.getConsumptionType(),"1")){
+                //判断当前选择的是代金券还是余额 1:代金券   2:余额
+                //选择代金券,用户原有代金券金额+本地赠送金额
+                bizUser.setVoucherBalance(bizUser.getVoucherBalance().add(consumptionRecordAddParam.getVoucherMoney()));
+                consumptionRecord.setConsumptionMoney(consumptionRecordAddParam.getVoucherMoney());
+            }else if(StringUtils.equals(consumptionRecordAddParam.getConsumptionType(),"2")){
+                //选择余额,用户原有余额+本次赠送余额金额
+                bizUser.setAccountBalance(bizUser.getAccountBalance().add(consumptionRecordAddParam.getAccountMoney()));
+                consumptionRecord.setConsumptionMoney(consumptionRecordAddParam.getAccountMoney());
+            }
+        }else if(StringUtils.equals(consumptionRecordAddParam.getConsumptionOperate(),"2")){
+            //会员扣减
+            if(StringUtils.equals(consumptionRecordAddParam.getConsumptionType(),"1")){
+                //选择代金券,用户原有代金券金额-本次扣减金额
+                bizUser.setVoucherBalance(bizUser.getVoucherBalance().subtract(consumptionRecordAddParam.getVoucherMoney()));
+                consumptionRecord.setConsumptionMoney(consumptionRecordAddParam.getVoucherMoney());
+            }else if(StringUtils.equals(consumptionRecordAddParam.getConsumptionType(),"2")){
+                //选择账户余额,用户原有余额-本次扣减余额
+                bizUser.setAccountBalance(bizUser.getAccountBalance().subtract(consumptionRecordAddParam.getAccountMoney()));
+                consumptionRecord.setConsumptionMoney(consumptionRecordAddParam.getAccountMoney());
+            }
+        }else {
+            //正常消费结算
+            //判断当前消费金额是否大于代金券金额,优先扣减代金券金额
+            if(consumptionRecordAddParam.getConsumptionMoney().compareTo(bizUser.getVoucherBalance()) > 0){
+                //计算本次消费和代金券差额
+                BigDecimal subtract = consumptionRecordAddParam.getConsumptionMoney().subtract(bizUser.getVoucherBalance());
+                //如果差额大于账户余额,表示账户余额不足
+                if(subtract.compareTo(bizUser.getAccountBalance()) > 0){
+                    throw new CommonException("账户余额不足!");
+                }
+                //记录消费信息
+                consumptionRecord.setVoucherMoney(bizUser.getVoucherBalance());
+                //代金券直接清空
+                bizUser.setVoucherBalance(new BigDecimal(0));
+                //余额扣去差额
+                bizUser.setAccountBalance(bizUser.getAccountBalance().subtract(subtract));
+                consumptionRecord.setAccountMoney(subtract);
+            }else{
+                //直接扣减代金券
+                bizUser.setVoucherBalance(bizUser.getVoucherBalance().subtract(consumptionRecordAddParam.getConsumptionMoney()));
+                consumptionRecord.setVoucherMoney(consumptionRecordAddParam.getConsumptionMoney());
+            }
+        }
+        //保存消费记录
+        this.save(consumptionRecord);
+        //修改账户余额
+        bizUserService.updateById(bizUser);
+    }
+
+    //会员赠送/扣减
+    public void customerConsumption(ConsumptionRecordAddParam consumptionRecordAddParam){
+
+    }
+
+    //参数校验
+    public void checkParam(ConsumptionRecordAddParam consumptionRecordAddParam){
+        //判断当前操作consumptionOperate  1:会员赠送  2:会员扣减  3:消费结算
+        if(ObjectUtil.isEmpty(consumptionRecordAddParam.getConsumptionOperate())){
+            throw new CommonException("消费操作consumptionOperate不能为空!");
+        }
+        if(StringUtils.equals(consumptionRecordAddParam.getConsumptionOperate(),"1") || StringUtils.equals(consumptionRecordAddParam.getConsumptionOperate(),"2")){
+            //会员操作填写说明
+            if(ObjectUtil.isEmpty(consumptionRecordAddParam.getConsumptionRemark())){
+                throw new CommonException("消费说明consumptionRemark不能为空!");
+            }
+            //选择赠送和扣减操作时要选择代金券还是账户余额
+            if(ObjectUtil.isEmpty(consumptionRecordAddParam.getConsumptionType())){
+                throw new CommonException("消费方式consumptionType不能为空!");
+            }
+        }
+        if(ObjectUtil.isEmpty(consumptionRecordAddParam.getUserId())){
+            throw new CommonException("用户userId不能为空!");
+        }
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void edit(ConsumptionRecordEditParam consumptionRecordEditParam) {
+        ConsumptionRecord consumptionRecord = this.queryEntity(consumptionRecordEditParam.getId());
+        BeanUtil.copyProperties(consumptionRecordEditParam, consumptionRecord);
+        this.updateById(consumptionRecord);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void delete(List<ConsumptionRecordIdParam> consumptionRecordIdParamList) {
+        // 执行删除
+        this.removeByIds(CollStreamUtil.toList(consumptionRecordIdParamList, ConsumptionRecordIdParam::getId));
+    }
+
+    @Override
+    public ConsumptionRecord detail(ConsumptionRecordIdParam consumptionRecordIdParam) {
+        return this.queryEntity(consumptionRecordIdParam.getId());
+    }
+
+    @Override
+    public ConsumptionRecord queryEntity(String id) {
+        ConsumptionRecord consumptionRecord = this.getById(id);
+        if(ObjectUtil.isEmpty(consumptionRecord)) {
+            throw new CommonException("消费记录不存在,id值为:{}", id);
+        }
+        return consumptionRecord;
+    }
+}