diff --git a/antis-ncc-admin/.env.development b/antis-ncc-admin/.env.development
index 78e23e6..be31aec 100644
--- a/antis-ncc-admin/.env.development
+++ b/antis-ncc-admin/.env.development
@@ -2,6 +2,6 @@
VUE_CLI_BABEL_TRANSPILE_MODULES = true
# VUE_APP_BASE_API = 'http://lvqian.antissoft.com'
-VUE_APP_BASE_API = 'http://erp_test.lvqianmeiye.com'
-# VUE_APP_BASE_API = 'http://localhost:2011'
+# VUE_APP_BASE_API = 'http://erp_test.lvqianmeiye.com'
+VUE_APP_BASE_API = 'http://localhost:2011'
VUE_APP_BASE_WSS = 'ws://192.168.110.45:2011/websocket'
diff --git a/antis-ncc-admin/src/api/extend/lqInventory.js b/antis-ncc-admin/src/api/extend/lqInventory.js
new file mode 100644
index 0000000..5a55f22
--- /dev/null
+++ b/antis-ncc-admin/src/api/extend/lqInventory.js
@@ -0,0 +1,105 @@
+import request from '@/utils/request'
+
+// ========== 库存管理接口 ==========
+
+// 创建库存
+export function createInventory(data) {
+ return request({
+ url: '/api/Extend/LqInventory/Create',
+ method: 'post',
+ data
+ })
+}
+
+// 更新库存
+export function updateInventory(data) {
+ return request({
+ url: '/api/Extend/LqInventory/Update',
+ method: 'put',
+ data
+ })
+}
+
+// 获取库存列表
+export function getInventoryList(params) {
+ return request({
+ url: '/api/Extend/LqInventory/GetList',
+ method: 'get',
+ data: params
+ })
+}
+
+// 获取库存详情
+export function getInventoryInfo(id) {
+ return request({
+ url: '/api/Extend/LqInventory/GetInfo',
+ method: 'get',
+ data: { id }
+ })
+}
+
+// ========== 库存使用记录接口 ==========
+
+// 添加库存使用记录
+export function createInventoryUsage(data) {
+ return request({
+ url: '/api/Extend/LqInventoryUsage/Create',
+ method: 'post',
+ data
+ })
+}
+
+// 作废库存使用记录
+export function cancelInventoryUsage(id, remarks) {
+ return request({
+ url: '/api/Extend/LqInventoryUsage/Cancel',
+ method: 'put',
+ data: { id, remarks }
+ })
+}
+
+// 获取使用记录列表
+export function getInventoryUsageList(params) {
+ return request({
+ url: '/api/Extend/LqInventoryUsage/GetList',
+ method: 'get',
+ data: params
+ })
+}
+
+// 获取产品使用统计
+export function getProductUsageStatistics(data) {
+ return request({
+ url: '/api/Extend/LqInventoryUsage/GetProductUsageStatistics',
+ method: 'post',
+ data
+ })
+}
+
+// 获取门店使用统计
+export function getStoreUsageStatistics(data) {
+ return request({
+ url: '/api/Extend/LqInventoryUsage/GetStoreUsageStatistics',
+ method: 'post',
+ data
+ })
+}
+
+// 获取使用趋势统计
+export function getUsageTrendStatistics(data) {
+ return request({
+ url: '/api/Extend/LqInventoryUsage/GetUsageTrendStatistics',
+ method: 'post',
+ data
+ })
+}
+
+// 获取产品使用排行榜
+export function getProductUsageRanking(data) {
+ return request({
+ url: '/api/Extend/LqInventoryUsage/GetProductUsageRanking',
+ method: 'post',
+ data
+ })
+}
+
diff --git a/antis-ncc-admin/src/api/extend/lqStudyClass.js b/antis-ncc-admin/src/api/extend/lqStudyClass.js
new file mode 100644
index 0000000..97f6ecf
--- /dev/null
+++ b/antis-ncc-admin/src/api/extend/lqStudyClass.js
@@ -0,0 +1,65 @@
+import request from '@/utils/request'
+
+// 创建学习班级并添加学员
+export function createClassWithStudents(data) {
+ return request({
+ url: '/api/Extend/LqStudyClass/CreateClassWithStudents',
+ method: 'post',
+ data
+ })
+}
+
+// 向现有班级添加学员
+export function addStudentsToClass(data) {
+ return request({
+ url: '/api/Extend/LqStudyClass/AddStudentsToClass',
+ method: 'post',
+ data
+ })
+}
+
+// 获取所有班级列表
+export function getClassList(params) {
+ return request({
+ url: '/api/Extend/LqStudyClass/GetClassList',
+ method: 'get',
+ data: params
+ })
+}
+
+// 获取班级下所有学员信息
+export function getStudentListByClassId(params) {
+ return request({
+ url: '/api/Extend/LqStudyClass/GetStudentListByClassId',
+ method: 'get',
+ data: params
+ })
+}
+
+// 添加学习记录
+export function addStudyRecord(data) {
+ return request({
+ url: '/api/Extend/LqStudyClass/AddStudyRecord',
+ method: 'post',
+ data
+ })
+}
+
+// 获取学习记录列表
+export function getStudyRecordList(params) {
+ return request({
+ url: '/api/Extend/LqStudyClass/GetStudyRecordList',
+ method: 'get',
+ data: params
+ })
+}
+
+// 作废学习记录
+export function cancelStudyRecord(id) {
+ return request({
+ url: '/api/Extend/LqStudyClass/CancelStudyRecord',
+ method: 'post',
+ data: id
+ })
+}
+
diff --git a/antis-ncc-admin/src/router/modules/base.js b/antis-ncc-admin/src/router/modules/base.js
index 50ba3da..a82bdc9 100644
--- a/antis-ncc-admin/src/router/modules/base.js
+++ b/antis-ncc-admin/src/router/modules/base.js
@@ -76,6 +76,17 @@ const baseRouter = [{
icon: 'icon-ym icon-ym-s-data',
}
},
+ {
+ path: '/lqInventory',
+ component: (resolve) => require(['@/views/lqInventory'], resolve),
+ name: 'lqInventory',
+ meta: {
+ title: 'lqInventory',
+ affix: false,
+ zhTitle: '库存管理',
+ icon: 'icon-ym icon-ym-box',
+ }
+ },
{
path: '/salaryCalculation',
component: (resolve) => require(['@/views/salaryCalculation/index'], resolve),
diff --git a/antis-ncc-admin/src/views/lqInventory/AddUsageRecordForm.vue b/antis-ncc-admin/src/views/lqInventory/AddUsageRecordForm.vue
new file mode 100644
index 0000000..c9532bf
--- /dev/null
+++ b/antis-ncc-admin/src/views/lqInventory/AddUsageRecordForm.vue
@@ -0,0 +1,260 @@
+
+
+
+
+
+
+
+
+ {{ product.productName }}
+ {{ product.productCategory
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
产品信息
+
+
+
+
+ {{ selectedProduct.productCategory }}
+
+
+
+
+
+ {{ formatMoney(selectedProduct.price) }}
+
+
+
+
+
+ {{
+ selectedProduct.quantity }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/antis-ncc-admin/src/views/lqInventory/InventoryForm.vue b/antis-ncc-admin/src/views/lqInventory/InventoryForm.vue
new file mode 100644
index 0000000..ea29810
--- /dev/null
+++ b/antis-ncc-admin/src/views/lqInventory/InventoryForm.vue
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/antis-ncc-admin/src/views/lqInventory/InventoryInfoDialog.vue b/antis-ncc-admin/src/views/lqInventory/InventoryInfoDialog.vue
new file mode 100644
index 0000000..6a8e065
--- /dev/null
+++ b/antis-ncc-admin/src/views/lqInventory/InventoryInfoDialog.vue
@@ -0,0 +1,194 @@
+
+
+
+
+
+
+
+ {{ inventoryInfo.productName || '无' }}
+
+
+
+
+
+ {{ inventoryInfo.productCategory || '无' }}
+
+
+
+
+
+
+
+
+ {{ formatMoney(inventoryInfo.price) }}
+
+
+
+
+
+ {{ inventoryInfo.quantity || 0
+ }}
+
+
+
+
+
+
+
+
+ {{ inventoryInfo.standardUnit || '无' }}
+
+
+
+
+
+ {{ formatMoney(inventoryInfo.totalValue) }}
+
+
+
+
+
+
+
+
+ {{ inventoryInfo.departmentName || '无' }}
+
+
+
+
+
+
+ {{ inventoryInfo.isEffective === 1 ? '有效' : '无效' }}
+
+
+
+
+
+
+
+
+
+ {{ inventoryInfo.createUserName || '无' }}
+
+
+
+
+
+ {{ inventoryInfo.createTime | dateTimeFormat }}
+
+
+
+
+
+
+
+
+ {{ inventoryInfo.updateUserName || '无' }}
+
+
+
+
+
+ {{ inventoryInfo.updateTime | dateTimeFormat }}
+
+
+
+
+
+
+
+
+ {{ inventoryInfo.remark }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/antis-ncc-admin/src/views/lqInventory/UsageRecordDialog.vue b/antis-ncc-admin/src/views/lqInventory/UsageRecordDialog.vue
new file mode 100644
index 0000000..0cad2e0
--- /dev/null
+++ b/antis-ncc-admin/src/views/lqInventory/UsageRecordDialog.vue
@@ -0,0 +1,288 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+ 添加使用记录
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatMoney(scope.row.productPrice) }}
+
+
+
+
+
+
+ {{ scope.row.usageTime | dateFormat }}
+
+
+
+
+
+
+ {{ scope.row.createTime | dateTimeFormat }}
+
+
+
+
+
+ {{ scope.row.isEffective === 1 ? '有效' : '无效' }}
+
+
+
+
+
+ 作废
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/antis-ncc-admin/src/views/lqInventory/index.vue b/antis-ncc-admin/src/views/lqInventory/index.vue
new file mode 100644
index 0000000..0e0f568
--- /dev/null
+++ b/antis-ncc-admin/src/views/lqInventory/index.vue
@@ -0,0 +1,295 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+
+
+
+
+ 添加库存
+ 编辑库存
+ 使用记录
+ 导出
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatMoney(scope.row.price) }}
+
+
+
+
+ {{ scope.row.quantity }}
+
+
+
+
+
+ {{ formatMoney(scope.row.totalValue) }}
+
+
+
+
+
+ {{ scope.row.createTime | dateTimeFormat }}
+
+
+
+
+ 查看详情
+ 编辑
+ 使用记录
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/antis-ncc-admin/src/views/lqStudyClass/AddStudentForm.vue b/antis-ncc-admin/src/views/lqStudyClass/AddStudentForm.vue
new file mode 100644
index 0000000..8dad244
--- /dev/null
+++ b/antis-ncc-admin/src/views/lqStudyClass/AddStudentForm.vue
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ onStudentChange(scope.$index, ids, users)" size="small" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/antis-ncc-admin/src/views/lqStudyClass/CreateClassForm.vue b/antis-ncc-admin/src/views/lqStudyClass/CreateClassForm.vue
new file mode 100644
index 0000000..a5c22c8
--- /dev/null
+++ b/antis-ncc-admin/src/views/lqStudyClass/CreateClassForm.vue
@@ -0,0 +1,226 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ onStudentChange(scope.$index, ids, users)" size="small" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/antis-ncc-admin/src/views/lqStudyClass/StudentListDialog.vue b/antis-ncc-admin/src/views/lqStudyClass/StudentListDialog.vue
new file mode 100644
index 0000000..4caac97
--- /dev/null
+++ b/antis-ncc-admin/src/views/lqStudyClass/StudentListDialog.vue
@@ -0,0 +1,202 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.admissionTime | dateFormat }}
+
+
+
+
+
+
+ 学习记录
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/antis-ncc-admin/src/views/lqStudyClass/StudyRecordDialog.vue b/antis-ncc-admin/src/views/lqStudyClass/StudyRecordDialog.vue
new file mode 100644
index 0000000..bf3be8d
--- /dev/null
+++ b/antis-ncc-admin/src/views/lqStudyClass/StudyRecordDialog.vue
@@ -0,0 +1,407 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+ 添加记录
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatMoney(scope.row.transportFee) }}
+
+
+
+
+ {{ scope.row.studyDate | dateFormat }}
+
+
+
+
+
+
+
+ {{ scope.row.isStoreAssist === 1 ? '是' : '否' }}
+
+
+
+
+
+
+
+ {{ scope.row.createTime | dateTimeFormat }}
+
+
+
+
+ 作废
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/antis-ncc-admin/src/views/lqStudyClass/index.vue b/antis-ncc-admin/src/views/lqStudyClass/index.vue
new file mode 100644
index 0000000..559f20d
--- /dev/null
+++ b/antis-ncc-admin/src/views/lqStudyClass/index.vue
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+
+
+
+
+ 创建班级
+ 添加学员(需选择班级)
+ 导出
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.startTime | dateFormat }}
+
+
+
+
+ {{ scope.row.endTime | dateFormat }}
+
+
+
+
+
+ 查看学员
+ 添加学员
+ 学习记录
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/antis-ncc-admin/src/views/lqStudyClass/test.html b/antis-ncc-admin/src/views/lqStudyClass/test.html
new file mode 100644
index 0000000..6d6d4f2
--- /dev/null
+++ b/antis-ncc-admin/src/views/lqStudyClass/test.html
@@ -0,0 +1,236 @@
+
+
+
+
+
+ 学习班级管理 - 功能测试
+
+
+
+
+
+
+
+
📋 已实现功能
+
+ - 学习班级列表展示(支持分页、搜索、筛选)
+ - 创建学习班级并添加学员(批量添加)
+ - 向现有班级添加学员
+ - 查看班级下所有学员信息(分页展示)
+ - 学习记录管理(添加、查看、作废)
+ - 学员信息搜索和筛选
+ - 学习记录搜索和筛选
+ - 响应式布局设计
+ - 表单验证和错误处理
+
+
+
+
+
🔧 API接口配置
+
+
接口地址:/api/Extend/LqStudyClass
+
请求方法:GET, POST
+
主要接口:
+
+POST /api/Extend/LqStudyClass/CreateClassWithStudents
+GET /api/Extend/LqStudyClass/GetClassList
+POST /api/Extend/LqStudyClass/AddStudentsToClass
+GET /api/Extend/LqStudyClass/GetStudentListByClassId
+POST /api/Extend/LqStudyClass/AddStudyRecord
+GET /api/Extend/LqStudyClass/GetStudyRecordList
+POST /api/Extend/LqStudyClass/CancelStudyRecord
+
+
+
+
+
+
📁 文件结构
+
+lqStudyClass/
+├── index.vue # 主页面组件
+├── CreateClassForm.vue # 创建班级表单组件
+├── AddStudentForm.vue # 添加学员表单组件
+├── StudentListDialog.vue # 学员列表弹窗组件
+└── StudyRecordDialog.vue # 学习记录管理弹窗组件
+
+api/extend/
+└── lqStudyClass.js # API接口定义
+
+
+
+
+
🎯 核心功能说明
+
+
1. 创建学习班级并添加学员
+
支持一次性创建班级并批量添加学员,包含班级基本信息(名称、老师、时间、备注)和学员详细信息(姓名、手机、员工ID、入学时间、HR归属)。
+
+
2. 班级列表管理
+
提供班级列表展示,支持按班级名称、授课老师、开始时间等条件搜索,支持分页显示。
+
+
3. 学员管理
+
可以查看指定班级下的所有学员信息,支持学员信息搜索和筛选,支持向现有班级添加新学员。
+
+
4. 学习记录管理
+
记录学员的学习情况,包括学习类型、交通费、学习日期、日常状态、是否下店协助等信息,支持记录的添加、查看和作废操作。
+
+
+
+
+
🚀 技术特点
+
+ - 采用Vue 2.6 + Element UI技术栈
+ - 组件化开发,模块清晰
+ - 统一的API调用方式
+ - 完善的表单验证
+ - 响应式设计
+ - 良好的用户体验
+ - 符合项目开发规范
+
+
+
+
+
📊 数据流程
+
+
创建班级流程:
+
+ - 填写班级基本信息(名称、老师、时间等)
+ - 添加学员信息(可批量添加)
+ - 提交表单,后端创建班级和学员记录
+ - 返回创建结果,刷新列表
+
+
+
学员管理流程:
+
+ - 从班级列表选择班级
+ - 查看班级学员列表
+ - 支持搜索和筛选学员
+ - 可添加新学员到班级
+
+
+
学习记录流程:
+
+ - 选择班级查看学习记录
+ - 添加新的学习记录
+ - 支持记录搜索和筛选
+ - 可作废无效记录
+
+
+
+
+
+
✅ 开发状态
+
+ 前端页面:已完成
+ API接口:已对接
+ 路由配置:已配置
+ 功能测试:待测试
+
+
+
+
+
+
diff --git a/antis-ncc-admin/src/views/storeTotalPerformanceStatistics/index.vue b/antis-ncc-admin/src/views/storeTotalPerformanceStatistics/index.vue
index f22abd5..0a5a9c5 100644
--- a/antis-ncc-admin/src/views/storeTotalPerformanceStatistics/index.vue
+++ b/antis-ncc-admin/src/views/storeTotalPerformanceStatistics/index.vue
@@ -61,6 +61,26 @@
+
+
+ {{ formatMoney(scope.row.FirstOrderPerformance) }}
+
+
+
+
+ {{ formatMoney(scope.row.UpgradeOrderPerformance) }}
+
+
+
+
+ {{ formatMoney(scope.row.RefundAmount) }}
+
+
+
+
+ {{ scope.row.RefundCount || 0 }}
+
+
{{ formatDateTime(scope.row.CreateTime) }}
diff --git a/netcore/src/Modularity/Common/NCC.Common/Enum/CommonStatus.cs b/netcore/src/Modularity/Common/NCC.Common/Enum/CommonStatus.cs
deleted file mode 100644
index 315cdbc..0000000
--- a/netcore/src/Modularity/Common/NCC.Common/Enum/CommonStatus.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using NCC.Dependency;
-using System.ComponentModel;
-
-namespace NCC.Common.Enum
-{
- ///
- /// 公共状态
- ///
- [SuppressSniffer]
- public enum CommonStatus
- {
- ///
- /// 正常
- ///
- [Description("正常")]
- ENABLE = 0,
-
- ///
- /// 停用
- ///
- [Description("停用")]
- DISABLE = 1,
-
- ///
- /// 删除
- ///
- [Description("删除")]
- DELETED = 2
- }
-}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogCrInput.cs
new file mode 100644
index 0000000..5674379
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogCrInput.cs
@@ -0,0 +1,59 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqCardTransferLog
+{
+ ///
+ /// 转卡日志创建输入参数
+ ///
+ public class LqCardTransferLogCrInput
+ {
+ ///
+ /// 退卡ID
+ ///
+ [Required(ErrorMessage = "退卡ID不能为空")]
+ public string refundCardId { get; set; }
+
+ ///
+ /// 开卡ID
+ ///
+ [Required(ErrorMessage = "开卡ID不能为空")]
+ public string billingCardId { get; set; }
+
+ ///
+ /// 转卡人会员ID
+ ///
+ [Required(ErrorMessage = "转卡人会员ID不能为空")]
+ public string transferFromMemberId { get; set; }
+
+ ///
+ /// 被转卡人会员ID
+ ///
+ [Required(ErrorMessage = "被转卡人会员ID不能为空")]
+ public string transferToMemberId { get; set; }
+
+ ///
+ /// 转卡总金额
+ ///
+ [Required(ErrorMessage = "转卡总金额不能为空")]
+ [Range(0.01, double.MaxValue, ErrorMessage = "转卡总金额必须大于0")]
+ public decimal transferAmount { get; set; }
+
+ ///
+ /// 转卡时间
+ ///
+ [Required(ErrorMessage = "转卡时间不能为空")]
+ public DateTime transferTime { get; set; }
+
+ ///
+ /// 操作人ID
+ ///
+ [Required(ErrorMessage = "操作人ID不能为空")]
+ public string operatorId { get; set; }
+
+ ///
+ /// 备注信息
+ ///
+ public string remarks { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogInfoOutput.cs
new file mode 100644
index 0000000..dc79b88
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogInfoOutput.cs
@@ -0,0 +1,80 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqCardTransferLog
+{
+ ///
+ /// 转卡日志详情输出参数
+ ///
+ public class LqCardTransferLogInfoOutput
+ {
+ ///
+ /// 主键ID
+ ///
+ public string id { get; set; }
+
+ ///
+ /// 退卡ID
+ ///
+ public string refundCardId { get; set; }
+
+ ///
+ /// 开卡ID
+ ///
+ public string billingCardId { get; set; }
+
+ ///
+ /// 转卡人会员ID
+ ///
+ public string transferFromMemberId { get; set; }
+
+ ///
+ /// 转卡人姓名
+ ///
+ public string transferFromMemberName { get; set; }
+
+ ///
+ /// 被转卡人会员ID
+ ///
+ public string transferToMemberId { get; set; }
+
+ ///
+ /// 被转卡人姓名
+ ///
+ public string transferToMemberName { get; set; }
+
+ ///
+ /// 转卡总金额
+ ///
+ public decimal transferAmount { get; set; }
+
+ ///
+ /// 转卡时间
+ ///
+ public DateTime transferTime { get; set; }
+
+ ///
+ /// 操作人ID
+ ///
+ public string operatorId { get; set; }
+
+ ///
+ /// 备注信息
+ ///
+ public string remarks { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime? createTime { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime? updateTime { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ public int isEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogListOutput.cs
new file mode 100644
index 0000000..008c6bb
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogListOutput.cs
@@ -0,0 +1,80 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqCardTransferLog
+{
+ ///
+ /// 转卡日志列表输出参数
+ ///
+ public class LqCardTransferLogListOutput
+ {
+ ///
+ /// 主键ID
+ ///
+ public string id { get; set; }
+
+ ///
+ /// 退卡ID
+ ///
+ public string refundCardId { get; set; }
+
+ ///
+ /// 开卡ID
+ ///
+ public string billingCardId { get; set; }
+
+ ///
+ /// 转卡人会员ID
+ ///
+ public string transferFromMemberId { get; set; }
+
+ ///
+ /// 转卡人姓名
+ ///
+ public string transferFromMemberName { get; set; }
+
+ ///
+ /// 被转卡人会员ID
+ ///
+ public string transferToMemberId { get; set; }
+
+ ///
+ /// 被转卡人姓名
+ ///
+ public string transferToMemberName { get; set; }
+
+ ///
+ /// 转卡总金额
+ ///
+ public decimal transferAmount { get; set; }
+
+ ///
+ /// 转卡时间
+ ///
+ public DateTime transferTime { get; set; }
+
+ ///
+ /// 操作人ID
+ ///
+ public string operatorId { get; set; }
+
+ ///
+ /// 备注信息
+ ///
+ public string remarks { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime? createTime { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime? updateTime { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ public int isEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogListQueryInput.cs
new file mode 100644
index 0000000..4b68fb1
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogListQueryInput.cs
@@ -0,0 +1,51 @@
+using System;
+using NCC.Common.Filter;
+
+namespace NCC.Extend.Entitys.Dto.LqCardTransferLog
+{
+ ///
+ /// 转卡日志列表查询输入参数
+ ///
+ public class LqCardTransferLogListQueryInput : PageInputBase
+ {
+ ///
+ /// 转卡人会员ID
+ ///
+ public string transferFromMemberId { get; set; }
+
+ ///
+ /// 被转卡人会员ID
+ ///
+ public string transferToMemberId { get; set; }
+
+ ///
+ /// 操作人ID
+ ///
+ public string operatorId { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ public int isEffective { get; set; } = 1;
+
+ ///
+ /// 转卡开始时间
+ ///
+ public DateTime? transferStartTime { get; set; }
+
+ ///
+ /// 转卡结束时间
+ ///
+ public DateTime? transferEndTime { get; set; }
+
+ ///
+ /// 最小转卡金额
+ ///
+ public decimal? minTransferAmount { get; set; }
+
+ ///
+ /// 最大转卡金额
+ ///
+ public decimal? maxTransferAmount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkCrInput.cs
index cf559c9..ba7f7eb 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkCrInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkCrInput.cs
@@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
public decimal? tkje { get; set; }
///
+ /// 实退金额
+ ///
+ public decimal? actualRefundAmount { get; set; }
+
+ ///
/// 手工费用
///
public decimal? sgfy { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkInfoOutput.cs
index d6b4825..f921982 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkInfoOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkInfoOutput.cs
@@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
public decimal? tkje { get; set; }
///
+ /// 实退金额
+ ///
+ public decimal? actualRefundAmount { get; set; }
+
+ ///
/// 手工费用
///
public decimal? sgfy { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs
index aa19208..4aeee69 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs
@@ -53,6 +53,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
public decimal? tkje { get; set; }
///
+ /// 实退金额
+ ///
+ public decimal? actualRefundAmount { get; set; }
+
+ ///
/// 手工费用
///
public decimal? sgfy { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListQueryInput.cs
index 31f41ee..1369ba5 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListQueryInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListQueryInput.cs
@@ -12,72 +12,72 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
/// 退卡编号
///
public string id { get; set; }
-
+
///
/// 门店
///
public string md { get; set; }
-
+
///
/// 门店编号
///
public string mdbh { get; set; }
-
+
///
/// 门店名称
///
public string mdmc { get; set; }
-
+
///
/// 会员
///
public string hy { get; set; }
-
+
///
/// 会员姓名
///
public string hymc { get; set; }
-
+
///
/// 会员账号
///
public string hyzh { get; set; }
-
+
///
/// 顾客类型
///
public string gklx { get; set; }
-
+
///
/// 退卡总金额
///
public decimal? tkje { get; set; }
-
+
///
/// 手工费用
///
public decimal? sgfy { get; set; }
-
+
///
/// 备注
///
public string bz { get; set; }
-
+
///
/// 退卡时间
///
public string tksj { get; set; }
-
+
///
/// 操作人员
///
public string czry { get; set; }
-
+
///
/// 退卡状态
///
public string tkzt { get; set; }
-
+
///
/// 退卡原因
///
@@ -87,6 +87,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
/// 退卡附件
///
public string fileUrl { get; set; }
-
+
+ ///
+ /// 是否有效
+ ///
+ public int isEffective { get; set; } = 0;
+
}
}
\ No newline at end of file
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkUpInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkUpInput.cs
index 1e15120..9ee7290 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkUpInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkUpInput.cs
@@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
public decimal? tkje { get; set; }
///
+ /// 实退金额
+ ///
+ public decimal? actualRefundAmount { get; set; }
+
+ ///
/// 手工费用
///
public decimal? sgfy { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryCrInput.cs
new file mode 100644
index 0000000..351665e
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryCrInput.cs
@@ -0,0 +1,58 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqInventory
+{
+ ///
+ /// 库存创建输入
+ ///
+ public class LqInventoryCrInput
+ {
+ ///
+ /// 产品名称
+ ///
+ [Required(ErrorMessage = "产品名称不能为空")]
+ [StringLength(100, ErrorMessage = "产品名称长度不能超过100个字符")]
+ [Display(Name = "产品名称")]
+ public string ProductName { get; set; }
+
+ ///
+ /// 价格
+ ///
+ [Required(ErrorMessage = "价格不能为空")]
+ [Range(0, double.MaxValue, ErrorMessage = "价格不能小于0")]
+ [Display(Name = "价格")]
+ public decimal Price { get; set; }
+
+ ///
+ /// 数量
+ ///
+ [Range(0, int.MaxValue, ErrorMessage = "数量不能小于0")]
+ [Display(Name = "数量")]
+ public int Quantity { get; set; } = 0;
+
+ ///
+ /// 产品类别
+ ///
+ [Required(ErrorMessage = "产品类别不能为空")]
+ [StringLength(50, ErrorMessage = "产品类别长度不能超过50个字符")]
+ [Display(Name = "产品类别")]
+ public string ProductCategory { get; set; }
+
+ ///
+ /// 归属部门ID
+ ///
+ [Required(ErrorMessage = "归属部门ID不能为空")]
+ [StringLength(50, ErrorMessage = "归属部门ID长度不能超过50个字符")]
+ [Display(Name = "归属部门ID")]
+ public string DepartmentId { get; set; }
+
+ ///
+ /// 标准单位
+ ///
+ [Required(ErrorMessage = "标准单位不能为空")]
+ [StringLength(20, ErrorMessage = "标准单位长度不能超过20个字符")]
+ [Display(Name = "标准单位")]
+ public string StandardUnit { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryInfoOutput.cs
new file mode 100644
index 0000000..f7c7185
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryInfoOutput.cs
@@ -0,0 +1,14 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqInventory
+{
+ ///
+ /// 库存详情输出
+ ///
+ public class LqInventoryInfoOutput : LqInventoryListOutput
+ {
+ // 继承自LqInventoryListOutput,包含所有列表输出字段
+ // 可以根据需要添加额外的详情字段
+ }
+}
\ No newline at end of file
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryListOutput.cs
new file mode 100644
index 0000000..5edfb11
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryListOutput.cs
@@ -0,0 +1,107 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqInventory
+{
+ ///
+ /// 库存列表输出
+ ///
+ public class LqInventoryListOutput
+ {
+ ///
+ /// 库存ID
+ ///
+ [Display(Name = "库存ID")]
+ public string id { get; set; }
+
+ ///
+ /// 产品名称
+ ///
+ [Display(Name = "产品名称")]
+ public string productName { get; set; }
+
+ ///
+ /// 价格
+ ///
+ [Display(Name = "价格")]
+ public decimal price { get; set; }
+
+ ///
+ /// 数量
+ ///
+ [Display(Name = "数量")]
+ public int quantity { get; set; }
+
+ ///
+ /// 产品类别
+ ///
+ [Display(Name = "产品类别")]
+ public string productCategory { get; set; }
+
+ ///
+ /// 归属部门ID
+ ///
+ [Display(Name = "归属部门ID")]
+ public string departmentId { get; set; }
+
+ ///
+ /// 部门名称
+ ///
+ [Display(Name = "部门名称")]
+ public string departmentName { get; set; }
+
+ ///
+ /// 标准单位
+ ///
+ [Display(Name = "标准单位")]
+ public string standardUnit { get; set; }
+
+ ///
+ /// 总价值
+ ///
+ [Display(Name = "总价值")]
+ public decimal totalValue { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ [Display(Name = "创建人ID")]
+ public string createUser { get; set; }
+
+ ///
+ /// 创建人姓名
+ ///
+ [Display(Name = "创建人姓名")]
+ public string createUserName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [Display(Name = "创建时间")]
+ public DateTime createTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ [Display(Name = "更新人ID")]
+ public string updateUser { get; set; }
+
+ ///
+ /// 更新人姓名
+ ///
+ [Display(Name = "更新人姓名")]
+ public string updateUserName { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [Display(Name = "更新时间")]
+ public DateTime? updateTime { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ [Display(Name = "是否有效")]
+ public int isEffective { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryListQueryInput.cs
new file mode 100644
index 0000000..1650106
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryListQueryInput.cs
@@ -0,0 +1,60 @@
+using NCC.Common.Filter;
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqInventory
+{
+ ///
+ /// 库存列表查询输入
+ ///
+ public class LqInventoryListQueryInput : PageInputBase
+ {
+ ///
+ /// 产品名称
+ ///
+ [Display(Name = "产品名称", Description = "根据产品名称筛选")]
+ public string ProductName { get; set; }
+
+ ///
+ /// 产品类别
+ ///
+ [Display(Name = "产品类别", Description = "根据产品类别筛选")]
+ public string ProductCategory { get; set; }
+
+ ///
+ /// 归属部门ID
+ ///
+ [Display(Name = "归属部门ID", Description = "根据归属部门ID筛选")]
+ public string DepartmentId { get; set; }
+
+ ///
+ /// 价格最小值
+ ///
+ [Display(Name = "价格最小值", Description = "价格范围的最小值")]
+ public decimal? PriceMin { get; set; }
+
+ ///
+ /// 价格最大值
+ ///
+ [Display(Name = "价格最大值", Description = "价格范围的最大值")]
+ public decimal? PriceMax { get; set; }
+
+ ///
+ /// 数量最小值
+ ///
+ [Display(Name = "数量最小值", Description = "数量范围的最小值")]
+ public int? QuantityMin { get; set; }
+
+ ///
+ /// 数量最大值
+ ///
+ [Display(Name = "数量最大值", Description = "数量范围的最大值")]
+ public int? QuantityMax { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ [Display(Name = "是否有效", Description = "根据是否有效筛选")]
+ public int? IsEffective { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryUpInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryUpInput.cs
new file mode 100644
index 0000000..d6184e7
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryUpInput.cs
@@ -0,0 +1,19 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqInventory
+{
+ ///
+ /// 库存更新输入
+ ///
+ public class LqInventoryUpInput : LqInventoryCrInput
+ {
+ ///
+ /// 库存ID
+ ///
+ [Required(ErrorMessage = "库存ID不能为空")]
+ [StringLength(50, ErrorMessage = "库存ID长度不能超过50个字符")]
+ [Display(Name = "库存ID")]
+ public string Id { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageCrInput.cs
new file mode 100644
index 0000000..c976f18
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageCrInput.cs
@@ -0,0 +1,49 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
+{
+ ///
+ /// 库存使用记录创建输入
+ ///
+ public class LqInventoryUsageCrInput
+ {
+ ///
+ /// 产品ID
+ ///
+ [Required(ErrorMessage = "产品ID不能为空")]
+ [StringLength(50, ErrorMessage = "产品ID长度不能超过50个字符")]
+ [Display(Name = "产品ID")]
+ public string ProductId { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ [Required(ErrorMessage = "门店ID不能为空")]
+ [StringLength(50, ErrorMessage = "门店ID长度不能超过50个字符")]
+ [Display(Name = "门店ID")]
+ public string StoreId { get; set; }
+
+ ///
+ /// 使用时间
+ ///
+ [Required(ErrorMessage = "使用时间不能为空")]
+ [Display(Name = "使用时间")]
+ public DateTime UsageTime { get; set; }
+
+ ///
+ /// 使用数量
+ ///
+ [Required(ErrorMessage = "使用数量不能为空")]
+ [Range(1, int.MaxValue, ErrorMessage = "使用数量必须大于0")]
+ [Display(Name = "使用数量")]
+ public int UsageQuantity { get; set; }
+
+ ///
+ /// 关联消耗ID
+ ///
+ [StringLength(50, ErrorMessage = "关联消耗ID长度不能超过50个字符")]
+ [Display(Name = "关联消耗ID")]
+ public string RelatedConsumeId { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageInfoOutput.cs
new file mode 100644
index 0000000..8bae91a
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageInfoOutput.cs
@@ -0,0 +1,105 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
+{
+ ///
+ /// 库存使用记录详情输出
+ ///
+ public class LqInventoryUsageInfoOutput
+ {
+ ///
+ /// 使用记录ID
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 产品ID
+ ///
+ public string ProductId { get; set; }
+
+ ///
+ /// 产品名称
+ ///
+ public string ProductName { get; set; }
+
+ ///
+ /// 产品类别
+ ///
+ public string ProductCategory { get; set; }
+
+ ///
+ /// 产品价格
+ ///
+ public decimal ProductPrice { get; set; }
+
+ ///
+ /// 产品标准单位
+ ///
+ public string ProductStandardUnit { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 门店名称
+ ///
+ public string StoreName { get; set; }
+
+ ///
+ /// 使用时间
+ ///
+ public DateTime UsageTime { get; set; }
+
+ ///
+ /// 使用数量
+ ///
+ public int UsageQuantity { get; set; }
+
+ ///
+ /// 关联消耗ID
+ ///
+ public string RelatedConsumeId { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建人姓名
+ ///
+ public string CreateUserName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新人姓名
+ ///
+ public string UpdateUserName { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ public int IsEffective { get; set; }
+
+ ///
+ /// 使用总价值
+ ///
+ public decimal UsageTotalValue { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageListOutput.cs
new file mode 100644
index 0000000..4f30762
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageListOutput.cs
@@ -0,0 +1,100 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
+{
+ ///
+ /// 库存使用记录列表输出
+ ///
+ public class LqInventoryUsageListOutput
+ {
+ ///
+ /// 使用记录ID
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 产品ID
+ ///
+ public string ProductId { get; set; }
+
+ ///
+ /// 产品名称
+ ///
+ public string ProductName { get; set; }
+
+ ///
+ /// 产品类别
+ ///
+ public string ProductCategory { get; set; }
+
+ ///
+ /// 产品价格
+ ///
+ public decimal ProductPrice { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 门店名称
+ ///
+ public string StoreName { get; set; }
+
+ ///
+ /// 使用时间
+ ///
+ public DateTime UsageTime { get; set; }
+
+ ///
+ /// 使用数量
+ ///
+ public int UsageQuantity { get; set; }
+
+ ///
+ /// 关联消耗ID
+ ///
+ public string RelatedConsumeId { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建人姓名
+ ///
+ public string CreateUserName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新人姓名
+ ///
+ public string UpdateUserName { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ public int IsEffective { get; set; }
+
+ ///
+ /// 使用总价值
+ ///
+ public decimal UsageTotalValue { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageListQueryInput.cs
new file mode 100644
index 0000000..23e1ea3
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageListQueryInput.cs
@@ -0,0 +1,55 @@
+using NCC.Common.Filter;
+
+namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
+{
+ ///
+ /// 库存使用记录列表查询输入
+ ///
+ public class LqInventoryUsageListQueryInput : PageInputBase
+ {
+ ///
+ /// 产品ID
+ ///
+ public string ProductId { get; set; }
+
+ ///
+ /// 产品名称
+ ///
+ public string ProductName { get; set; }
+
+ ///
+ /// 产品类别
+ ///
+ public string ProductCategory { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 门店名称
+ ///
+ public string StoreName { get; set; }
+
+ ///
+ /// 使用开始时间
+ ///
+ public System.DateTime? UsageStartTime { get; set; }
+
+ ///
+ /// 使用结束时间
+ ///
+ public System.DateTime? UsageEndTime { get; set; }
+
+ ///
+ /// 关联消耗ID
+ ///
+ public string RelatedConsumeId { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ public int? IsEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageStatisticsInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageStatisticsInput.cs
new file mode 100644
index 0000000..2b4f313
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageStatisticsInput.cs
@@ -0,0 +1,60 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
+{
+ ///
+ /// 库存使用记录统计查询输入
+ ///
+ public class LqInventoryUsageStatisticsInput
+ {
+ ///
+ /// 开始时间
+ ///
+ [Required(ErrorMessage = "开始时间不能为空")]
+ [Display(Name = "开始时间")]
+ public DateTime StartTime { get; set; }
+
+ ///
+ /// 结束时间
+ ///
+ [Required(ErrorMessage = "结束时间不能为空")]
+ [Display(Name = "结束时间")]
+ public DateTime EndTime { get; set; }
+
+ ///
+ /// 产品ID(可选,用于筛选特定产品)
+ ///
+ [StringLength(50, ErrorMessage = "产品ID长度不能超过50个字符")]
+ [Display(Name = "产品ID")]
+ public string ProductId { get; set; }
+
+ ///
+ /// 门店ID(可选,用于筛选特定门店)
+ ///
+ [StringLength(50, ErrorMessage = "门店ID长度不能超过50个字符")]
+ [Display(Name = "门店ID")]
+ public string StoreId { get; set; }
+
+ ///
+ /// 产品类别(可选,用于筛选特定类别)
+ ///
+ [StringLength(50, ErrorMessage = "产品类别长度不能超过50个字符")]
+ [Display(Name = "产品类别")]
+ public string ProductCategory { get; set; }
+
+ ///
+ /// 统计类型(日/周/月)
+ ///
+ [StringLength(10, ErrorMessage = "统计类型长度不能超过10个字符")]
+ [Display(Name = "统计类型")]
+ public string StatisticsType { get; set; } = "日";
+
+ ///
+ /// 排行榜数量(默认10)
+ ///
+ [Range(1, 100, ErrorMessage = "排行榜数量必须在1-100之间")]
+ [Display(Name = "排行榜数量")]
+ public int RankingCount { get; set; } = 10;
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageStatisticsOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageStatisticsOutput.cs
new file mode 100644
index 0000000..b4a269f
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageStatisticsOutput.cs
@@ -0,0 +1,163 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
+{
+ ///
+ /// 产品使用统计输出
+ ///
+ public class ProductUsageStatisticsOutput
+ {
+ ///
+ /// 产品ID
+ ///
+ public string ProductId { get; set; }
+
+ ///
+ /// 产品名称
+ ///
+ public string ProductName { get; set; }
+
+ ///
+ /// 产品类别
+ ///
+ public string ProductCategory { get; set; }
+
+ ///
+ /// 产品价格
+ ///
+ public decimal ProductPrice { get; set; }
+
+ ///
+ /// 使用总数量
+ ///
+ public int TotalUsageQuantity { get; set; }
+
+ ///
+ /// 使用总金额
+ ///
+ public decimal TotalUsageAmount { get; set; }
+
+ ///
+ /// 使用次数
+ ///
+ public int UsageCount { get; set; }
+
+ ///
+ /// 平均每次使用数量
+ ///
+ public decimal AverageUsageQuantity { get; set; }
+ }
+
+ ///
+ /// 门店使用统计输出
+ ///
+ public class StoreUsageStatisticsOutput
+ {
+ ///
+ /// 门店ID
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 门店名称
+ ///
+ public string StoreName { get; set; }
+
+ ///
+ /// 使用总数量
+ ///
+ public int TotalUsageQuantity { get; set; }
+
+ ///
+ /// 使用总金额
+ ///
+ public decimal TotalUsageAmount { get; set; }
+
+ ///
+ /// 使用次数
+ ///
+ public int UsageCount { get; set; }
+
+ ///
+ /// 使用产品种类数
+ ///
+ public int ProductVarietyCount { get; set; }
+ }
+
+ ///
+ /// 使用趋势统计输出
+ ///
+ public class UsageTrendStatisticsOutput
+ {
+ ///
+ /// 统计日期
+ ///
+ public DateTime StatisticsDate { get; set; }
+
+ ///
+ /// 使用总数量
+ ///
+ public int TotalUsageQuantity { get; set; }
+
+ ///
+ /// 使用总金额
+ ///
+ public decimal TotalUsageAmount { get; set; }
+
+ ///
+ /// 使用次数
+ ///
+ public int UsageCount { get; set; }
+
+ ///
+ /// 使用产品种类数
+ ///
+ public int ProductVarietyCount { get; set; }
+ }
+
+ ///
+ /// 产品使用排行榜输出
+ ///
+ public class ProductUsageRankingOutput
+ {
+ ///
+ /// 排名
+ ///
+ public int Ranking { get; set; }
+
+ ///
+ /// 产品ID
+ ///
+ public string ProductId { get; set; }
+
+ ///
+ /// 产品名称
+ ///
+ public string ProductName { get; set; }
+
+ ///
+ /// 产品类别
+ ///
+ public string ProductCategory { get; set; }
+
+ ///
+ /// 使用总数量
+ ///
+ public int TotalUsageQuantity { get; set; }
+
+ ///
+ /// 使用总金额
+ ///
+ public decimal TotalUsageAmount { get; set; }
+
+ ///
+ /// 使用次数
+ ///
+ public int UsageCount { get; set; }
+
+ ///
+ /// 使用门店数
+ ///
+ public int StoreCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageUpInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageUpInput.cs
new file mode 100644
index 0000000..4f889fb
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageUpInput.cs
@@ -0,0 +1,19 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
+{
+ ///
+ /// 库存使用记录更新输入
+ ///
+ public class LqInventoryUsageUpInput : LqInventoryUsageCrInput
+ {
+ ///
+ /// 使用记录ID
+ ///
+ [Required(ErrorMessage = "使用记录ID不能为空")]
+ [StringLength(50, ErrorMessage = "使用记录ID长度不能超过50个字符")]
+ [Display(Name = "使用记录ID")]
+ public string Id { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListQueryInput.cs
index d7a1c3f..8504adb 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListQueryInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListQueryInput.cs
@@ -48,21 +48,20 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
/// 合作机构
///
public string hgjg { get; set; }
-
///
/// 整单业绩
///
- public string zdyj { get; set; }
+ public decimal? zdyj { get; set; }
///
/// 实付业绩
///
- public string sfyj { get; set; }
+ public decimal? sfyj { get; set; }
///
/// 欠款
///
- public string qk { get; set; }
+ public decimal? qk { get; set; }
///
/// 储扣方式
@@ -135,5 +134,10 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
///
public string CreateUser { get; set; }
+ ///
+ /// 是否有效
+ ///
+ public int isEffective { get; set; } = 0;
+
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardInput.cs
new file mode 100644
index 0000000..82c6b98
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardInput.cs
@@ -0,0 +1,95 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
+{
+ ///
+ /// 转卡输入参数
+ ///
+ public class TransferCardInput
+ {
+ ///
+ /// 转出会员ID
+ ///
+ [Required(ErrorMessage = "转出会员ID不能为空")]
+ [StringLength(50, ErrorMessage = "转出会员ID长度不能超过50个字符")]
+ [Display(Name = "转出会员ID")]
+ public string FromMemberId { get; set; }
+
+ ///
+ /// 转入会员ID
+ ///
+ [Required(ErrorMessage = "转入会员ID不能为空")]
+ [StringLength(50, ErrorMessage = "转入会员ID长度不能超过50个字符")]
+ [Display(Name = "转入会员ID")]
+ public string ToMemberId { get; set; }
+
+ ///
+ /// 转出会员签名
+ ///
+ [Required(ErrorMessage = "传出会员签名不能为空")]
+ [Display(Name = "传出会员签名")]
+ public string SignatureFile { get; set; }
+
+ ///
+ /// 转出品项列表
+ ///
+ [Required(ErrorMessage = "转出品项列表不能为空")]
+ [Display(Name = "转出品项列表")]
+ public List TransferItems { get; set; }
+
+ ///
+ /// 转卡备注
+ ///
+ [StringLength(500, ErrorMessage = "转卡备注长度不能超过500个字符")]
+ [Display(Name = "转卡备注")]
+ public string Remarks { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ [Required(ErrorMessage = "门店ID不能为空")]
+ [StringLength(50, ErrorMessage = "门店ID长度不能超过50个字符")]
+ [Display(Name = "门店ID")]
+ public string StoreId { get; set; }
+ }
+
+ ///
+ /// 转卡品项输入参数
+ ///
+ public class TransferItemInput
+ {
+ ///
+ /// 开单品项明细ID
+ ///
+ [Required(ErrorMessage = "开单品项明细ID不能为空")]
+ [StringLength(50, ErrorMessage = "开单品项明细ID长度不能超过50个字符")]
+ [Display(Name = "开单品项明细ID")]
+ public string BillingItemId { get; set; }
+
+ ///
+ /// 转出数量
+ ///
+ [Required(ErrorMessage = "转出数量不能为空")]
+ [Range(1, int.MaxValue, ErrorMessage = "转出数量必须大于0")]
+ [Display(Name = "转出数量")]
+ public int TransferQuantity { get; set; }
+
+ ///
+ /// 品项名称
+ ///
+ [Required(ErrorMessage = "品项名称不能为空")]
+ [StringLength(100, ErrorMessage = "品项名称长度不能超过100个字符")]
+ [Display(Name = "品项名称")]
+ public string ItemName { get; set; }
+
+ ///
+ /// 品项价格
+ ///
+ [Required(ErrorMessage = "品项价格不能为空")]
+ [Range(0, double.MaxValue, ErrorMessage = "品项价格不能为负数")]
+ [Display(Name = "品项价格")]
+ public decimal ItemPrice { get; set; }
+
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardOutput.cs
new file mode 100644
index 0000000..e4aedce
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardOutput.cs
@@ -0,0 +1,60 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
+{
+ ///
+ /// 转卡输出参数
+ ///
+ public class TransferCardOutput
+ {
+ ///
+ /// 转卡是否成功
+ ///
+ public bool Success { get; set; }
+
+ ///
+ /// 转卡记录ID(退卡记录ID)
+ ///
+ public string TransferId { get; set; }
+
+ ///
+ /// 退卡记录ID
+ ///
+ public string RefundId { get; set; }
+
+ ///
+ /// 开卡记录ID
+ ///
+ public string BillingId { get; set; }
+
+ ///
+ /// 转卡总金额
+ ///
+ public decimal TotalAmount { get; set; }
+
+ ///
+ /// 转卡品项数量
+ ///
+ public int TotalQuantity { get; set; }
+
+ ///
+ /// 转出会员姓名
+ ///
+ public string FromMemberName { get; set; }
+
+ ///
+ /// 转入会员姓名
+ ///
+ public string ToMemberName { get; set; }
+
+ ///
+ /// 转卡时间
+ ///
+ public DateTime TransferTime { get; set; }
+
+ ///
+ /// 消息
+ ///
+ public string Message { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/LqDepartmentConsumePerformanceStatisticsListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/LqDepartmentConsumePerformanceStatisticsListOutput.cs
index b849401..97a2da0 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/LqDepartmentConsumePerformanceStatisticsListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/LqDepartmentConsumePerformanceStatisticsListOutput.cs
@@ -62,12 +62,23 @@ namespace NCC.Extend.Entitys.Dto.LqStatistics
///
public decimal HeadCount { get; set; }
+
///
/// 人次(日度去重到店数)
///
public decimal PersonCount { get; set; }
///
+ /// 退款业绩
+ ///
+ public decimal RefundAmount { get; set; }
+
+ ///
+ /// 退款次数
+ ///
+ public int RefundCount { get; set; }
+
+ ///
/// 创建时间
///
public DateTime CreateTime { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/LqStoreTotalPerformanceStatisticsListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/LqStoreTotalPerformanceStatisticsListOutput.cs
index 826a7d9..85ffc47 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/LqStoreTotalPerformanceStatisticsListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/LqStoreTotalPerformanceStatisticsListOutput.cs
@@ -63,6 +63,16 @@ namespace NCC.Extend.Entitys.Dto.LqStatistics
public int UpgradeOrderCount { get; set; }
///
+ /// 退款业绩
+ ///
+ public decimal RefundAmount { get; set; }
+
+ ///
+ /// 退款次数
+ ///
+ public int RefundCount { get; set; }
+
+ ///
/// 创建时间
///
public DateTime CreateTime { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsStoreTotalPerformance/LqStatisticsStoreTotalPerformanceInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsStoreTotalPerformance/LqStatisticsStoreTotalPerformanceInfoOutput.cs
index 7e48a59..5372f11 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsStoreTotalPerformance/LqStatisticsStoreTotalPerformanceInfoOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsStoreTotalPerformance/LqStatisticsStoreTotalPerformanceInfoOutput.cs
@@ -63,6 +63,26 @@ namespace NCC.Extend.Entitys.Dto.LqStatisticsStoreTotalPerformance
public int upgradeOrderCount { get; set; }
///
+ /// 首单业绩
+ ///
+ public decimal firstOrderPerformance { get; set; }
+
+ ///
+ /// 升单业绩
+ ///
+ public decimal upgradeOrderPerformance { get; set; }
+
+ ///
+ /// 退款业绩
+ ///
+ public decimal refundAmount { get; set; }
+
+ ///
+ /// 退款次数
+ ///
+ public int refundCount { get; set; }
+
+ ///
/// 创建时间
///
public DateTime? createTime { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsStoreTotalPerformance/LqStatisticsStoreTotalPerformanceListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsStoreTotalPerformance/LqStatisticsStoreTotalPerformanceListOutput.cs
index 7bb2aac..ae48dcb 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsStoreTotalPerformance/LqStatisticsStoreTotalPerformanceListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsStoreTotalPerformance/LqStatisticsStoreTotalPerformanceListOutput.cs
@@ -73,6 +73,16 @@ namespace NCC.Extend.Entitys.Dto.LqStatisticsStoreTotalPerformance
public decimal upgradeOrderPerformance { get; set; }
///
+ /// 退款业绩
+ ///
+ public decimal refundAmount { get; set; }
+
+ ///
+ /// 退款次数
+ ///
+ public int refundCount { get; set; }
+
+ ///
/// 创建时间
///
public DateTime? createTime { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassAddStudentsInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassAddStudentsInput.cs
new file mode 100644
index 0000000..8546b91
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassAddStudentsInput.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 向学习班级添加学员输入
+ ///
+ public class LqStudyClassAddStudentsInput
+ {
+ ///
+ /// 班级ID
+ ///
+ [Required(ErrorMessage = "班级ID不能为空")]
+ [StringLength(50, ErrorMessage = "班级ID长度不能超过50个字符")]
+ [Display(Name = "班级ID")]
+ public string ClassId { get; set; }
+
+ ///
+ ///
+ [Required(ErrorMessage = "学员列表不能为空")]
+ [Display(Name = "学员列表")]
+ public List Students { get; set; } = new List();
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassCrInput.cs
new file mode 100644
index 0000000..4ed5c43
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassCrInput.cs
@@ -0,0 +1,48 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 学习班级创建输入
+ ///
+ public class LqStudyClassCrInput
+ {
+ ///
+ /// 班级名称
+ ///
+ [Required(ErrorMessage = "班级名称不能为空")]
+ [StringLength(100, ErrorMessage = "班级名称长度不能超过100个字符")]
+ [Display(Name = "班级名称")]
+ public string ClassName { get; set; }
+
+ ///
+ /// 任教老师ID
+ ///
+ [Required(ErrorMessage = "任教老师ID不能为空")]
+ [StringLength(50, ErrorMessage = "任教老师ID长度不能超过50个字符")]
+ [Display(Name = "任教老师ID")]
+ public string TeacherId { get; set; }
+
+ ///
+ /// 开始时间
+ ///
+ [Required(ErrorMessage = "开始时间不能为空")]
+ [Display(Name = "开始时间")]
+ public DateTime StartTime { get; set; }
+
+ ///
+ /// 结束时间
+ ///
+ [Required(ErrorMessage = "结束时间不能为空")]
+ [Display(Name = "结束时间")]
+ public DateTime EndTime { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [StringLength(500, ErrorMessage = "备注长度不能超过500个字符")]
+ [Display(Name = "备注")]
+ public string Remark { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassCreateWithStudentsInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassCreateWithStudentsInput.cs
new file mode 100644
index 0000000..bc8f0bc
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassCreateWithStudentsInput.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 创建学习班级并添加学员输入
+ ///
+ public class LqStudyClassCreateWithStudentsInput
+ {
+ ///
+ /// 班级名称
+ ///
+ [Required(ErrorMessage = "班级名称不能为空")]
+ [StringLength(100, ErrorMessage = "班级名称长度不能超过100个字符")]
+ [Display(Name = "班级名称")]
+ public string ClassName { get; set; }
+
+ ///
+ /// 任教老师ID
+ ///
+ [Required(ErrorMessage = "任教老师ID不能为空")]
+ [StringLength(50, ErrorMessage = "任教老师ID长度不能超过50个字符")]
+ [Display(Name = "任教老师ID")]
+ public string TeacherId { get; set; }
+
+ ///
+ /// 开始时间
+ ///
+ [Required(ErrorMessage = "开始时间不能为空")]
+ [Display(Name = "开始时间")]
+ public DateTime StartTime { get; set; }
+
+ ///
+ /// 结束时间
+ ///
+ [Required(ErrorMessage = "结束时间不能为空")]
+ [Display(Name = "结束时间")]
+ public DateTime EndTime { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [StringLength(500, ErrorMessage = "备注长度不能超过500个字符")]
+ [Display(Name = "备注")]
+ public string Remark { get; set; }
+
+ ///
+ /// 学员列表
+ ///
+ [Display(Name = "学员列表")]
+ public List Students { get; set; } = new List();
+ }
+
+ ///
+ /// 学员创建输入
+ ///
+ public class LqStudyStudentCreateInput
+ {
+ ///
+ /// 员工姓名
+ ///
+ [Required(ErrorMessage = "员工姓名不能为空")]
+ [StringLength(50, ErrorMessage = "员工姓名长度不能超过50个字符")]
+ [Display(Name = "员工姓名")]
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工电话
+ ///
+ [Required(ErrorMessage = "员工电话不能为空")]
+ [StringLength(20, ErrorMessage = "员工电话长度不能超过20个字符")]
+ [Display(Name = "员工电话")]
+ public string EmployeePhone { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [Required(ErrorMessage = "员工ID不能为空")]
+ [StringLength(50, ErrorMessage = "员工ID长度不能超过50个字符")]
+ [Display(Name = "员工ID")]
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 入院时间
+ ///
+ [Required(ErrorMessage = "入院时间不能为空")]
+ [Display(Name = "入院时间")]
+ public DateTime AdmissionTime { get; set; }
+
+ ///
+ /// HR归属
+ ///
+ [StringLength(50, ErrorMessage = "HR归属长度不能超过50个字符")]
+ [Display(Name = "HR归属")]
+ public string HrBelong { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassInfoOutput.cs
new file mode 100644
index 0000000..94a610b
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassInfoOutput.cs
@@ -0,0 +1,95 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 学习班级详情输出
+ ///
+ public class LqStudyClassInfoOutput
+ {
+ ///
+ /// 班级ID
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 班级名称
+ ///
+ public string ClassName { get; set; }
+
+ ///
+ /// 任教老师ID
+ ///
+ public string TeacherId { get; set; }
+
+ ///
+ /// 任教老师姓名
+ ///
+ public string TeacherName { get; set; }
+
+ ///
+ /// 任教老师电话
+ ///
+ public string TeacherPhone { get; set; }
+
+ ///
+ /// 开始时间
+ ///
+ public DateTime StartTime { get; set; }
+
+ ///
+ /// 结束时间
+ ///
+ public DateTime EndTime { get; set; }
+
+ ///
+ /// 备注
+ ///
+ public string Remark { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建人姓名
+ ///
+ public string CreateUserName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新人姓名
+ ///
+ public string UpdateUserName { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ public int IsEffective { get; set; }
+
+ ///
+ /// 学员数量
+ ///
+ public int StudentCount { get; set; }
+
+ ///
+ /// 学习记录数量
+ ///
+ public int RecordCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassListOutput.cs
new file mode 100644
index 0000000..27ff100
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassListOutput.cs
@@ -0,0 +1,101 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 学习班级列表输出
+ ///
+ public class LqStudyClassListOutput
+ {
+ ///
+ /// 班级ID
+ ///
+ [Display(Name = "班级ID")]
+ public string id { get; set; }
+
+ ///
+ /// 班级名称
+ ///
+ [Display(Name = "班级名称")]
+ public string className { get; set; }
+
+ ///
+ /// 任教老师ID
+ ///
+ [Display(Name = "任教老师ID")]
+ public string teacherId { get; set; }
+
+ ///
+ /// 任教老师姓名
+ ///
+ [Display(Name = "任教老师姓名")]
+ public string teacherName { get; set; }
+
+ ///
+ /// 开始时间
+ ///
+ [Display(Name = "开始时间")]
+ public DateTime startTime { get; set; }
+
+ ///
+ /// 结束时间
+ ///
+ [Display(Name = "结束时间")]
+ public DateTime endTime { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [Display(Name = "备注")]
+ public string remark { get; set; }
+
+ ///
+ /// 学员数量
+ ///
+ [Display(Name = "学员数量")]
+ public int studentCount { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ [Display(Name = "创建人ID")]
+ public string createUser { get; set; }
+
+ ///
+ /// 创建人姓名
+ ///
+ [Display(Name = "创建人姓名")]
+ public string createUserName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [Display(Name = "创建时间")]
+ public DateTime createTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ [Display(Name = "更新人ID")]
+ public string updateUser { get; set; }
+
+ ///
+ /// 更新人姓名
+ ///
+ [Display(Name = "更新人姓名")]
+ public string updateUserName { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [Display(Name = "更新时间")]
+ public DateTime? updateTime { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ [Display(Name = "是否有效")]
+ public int isEffective { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassListQueryInput.cs
new file mode 100644
index 0000000..88b2a67
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassListQueryInput.cs
@@ -0,0 +1,42 @@
+using NCC.Common.Filter;
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 学习班级列表查询输入
+ ///
+ public class LqStudyClassListQueryInput : PageInputBase
+ {
+ ///
+ /// 班级名称
+ ///
+ [Display(Name = "班级名称", Description = "根据班级名称筛选")]
+ public string ClassName { get; set; }
+
+ ///
+ /// 任教老师ID
+ ///
+ [Display(Name = "任教老师ID", Description = "根据任教老师ID筛选")]
+ public string TeacherId { get; set; }
+
+ ///
+ /// 开始时间(班级开始时间范围)
+ ///
+ [Display(Name = "开始时间", Description = "班级开始时间的开始范围")]
+ public DateTime? StartTime { get; set; }
+
+ ///
+ /// 结束时间(班级开始时间范围)
+ ///
+ [Display(Name = "结束时间", Description = "班级开始时间的结束范围")]
+ public DateTime? EndTime { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ [Display(Name = "是否有效", Description = "根据是否有效筛选")]
+ public int? IsEffective { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassUpInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassUpInput.cs
new file mode 100644
index 0000000..b411443
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassUpInput.cs
@@ -0,0 +1,19 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 学习班级更新输入
+ ///
+ public class LqStudyClassUpInput : LqStudyClassCrInput
+ {
+ ///
+ /// 班级ID
+ ///
+ [Required(ErrorMessage = "班级ID不能为空")]
+ [StringLength(50, ErrorMessage = "班级ID长度不能超过50个字符")]
+ [Display(Name = "班级ID")]
+ public string Id { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordCreateInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordCreateInput.cs
new file mode 100644
index 0000000..176d944
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordCreateInput.cs
@@ -0,0 +1,83 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 添加学习记录输入
+ ///
+ public class LqStudyRecordCreateInput
+ {
+ ///
+ /// 员工姓名
+ ///
+ [Required(ErrorMessage = "员工姓名不能为空")]
+ [StringLength(50, ErrorMessage = "员工姓名长度不能超过50个字符")]
+ [Display(Name = "员工姓名")]
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [Required(ErrorMessage = "员工ID不能为空")]
+ [StringLength(50, ErrorMessage = "员工ID长度不能超过50个字符")]
+ [Display(Name = "员工ID")]
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 学习类型
+ ///
+ [Required(ErrorMessage = "学习类型不能为空")]
+ [StringLength(50, ErrorMessage = "学习类型长度不能超过50个字符")]
+ [Display(Name = "学习类型")]
+ public string StudyType { get; set; }
+
+ ///
+ /// 交通费
+ ///
+ [Range(0, double.MaxValue, ErrorMessage = "交通费不能为负数")]
+ [Display(Name = "交通费")]
+ public decimal? TransportFee { get; set; }
+
+ ///
+ /// 学习日期
+ ///
+ [Required(ErrorMessage = "学习日期不能为空")]
+ [Display(Name = "学习日期")]
+ public DateTime StudyDate { get; set; }
+
+ ///
+ /// 当日状态
+ ///
+ [StringLength(50, ErrorMessage = "当日状态长度不能超过50个字符")]
+ [Display(Name = "当日状态")]
+ public string DailyStatus { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [StringLength(500, ErrorMessage = "备注长度不能超过500个字符")]
+ [Display(Name = "备注")]
+ public string Remark { get; set; }
+
+ ///
+ /// 是否下店协助(1:是 0:否)
+ ///
+ [Display(Name = "是否下店协助")]
+ public int IsStoreAssist { get; set; } = 0;
+
+ ///
+ /// 下店门店ID
+ ///
+ [StringLength(50, ErrorMessage = "下店门店ID长度不能超过50个字符")]
+ [Display(Name = "下店门店ID")]
+ public string StoreId { get; set; }
+
+ ///
+ /// 下店门店名称
+ ///
+ [StringLength(100, ErrorMessage = "下店门店名称长度不能超过100个字符")]
+ [Display(Name = "下店门店名称")]
+ public string StoreName { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordListOutput.cs
new file mode 100644
index 0000000..e7c9ae9
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordListOutput.cs
@@ -0,0 +1,119 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 学习记录列表输出
+ ///
+ public class LqStudyRecordListOutput
+ {
+ ///
+ /// 学习记录ID
+ ///
+ [Display(Name = "学习记录ID")]
+ public string id { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ [Display(Name = "员工姓名")]
+ public string employeeName { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [Display(Name = "员工ID")]
+ public string employeeId { get; set; }
+
+ ///
+ /// 学习类型
+ ///
+ [Display(Name = "学习类型")]
+ public string studyType { get; set; }
+
+ ///
+ /// 交通费
+ ///
+ [Display(Name = "交通费")]
+ public decimal? transportFee { get; set; }
+
+ ///
+ /// 学习日期
+ ///
+ [Display(Name = "学习日期")]
+ public DateTime studyDate { get; set; }
+
+ ///
+ /// 当日状态
+ ///
+ [Display(Name = "当日状态")]
+ public string dailyStatus { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [Display(Name = "备注")]
+ public string remark { get; set; }
+
+ ///
+ /// 是否下店协助
+ ///
+ [Display(Name = "是否下店协助")]
+ public int isStoreAssist { get; set; }
+
+ ///
+ /// 下店门店ID
+ ///
+ [Display(Name = "下店门店ID")]
+ public string storeId { get; set; }
+
+ ///
+ /// 下店门店名称
+ ///
+ [Display(Name = "下店门店名称")]
+ public string storeName { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ [Display(Name = "创建人ID")]
+ public string createUser { get; set; }
+
+ ///
+ /// 创建人姓名
+ ///
+ [Display(Name = "创建人姓名")]
+ public string createUserName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [Display(Name = "创建时间")]
+ public DateTime createTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ [Display(Name = "更新人ID")]
+ public string updateUser { get; set; }
+
+ ///
+ /// 更新人姓名
+ ///
+ [Display(Name = "更新人姓名")]
+ public string updateUserName { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [Display(Name = "更新时间")]
+ public DateTime? updateTime { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ [Display(Name = "是否有效")]
+ public int isEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordListQueryInput.cs
new file mode 100644
index 0000000..a53d743
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordListQueryInput.cs
@@ -0,0 +1,66 @@
+using NCC.Common.Filter;
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 学习记录列表查询输入
+ ///
+ public class LqStudyRecordListQueryInput : PageInputBase
+ {
+ ///
+ /// 员工姓名
+ ///
+ [Display(Name = "员工姓名", Description = "根据员工姓名筛选")]
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [Display(Name = "员工ID", Description = "根据员工ID筛选")]
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 学习类型
+ ///
+ [Display(Name = "学习类型", Description = "根据学习类型筛选")]
+ public string StudyType { get; set; }
+
+ ///
+ /// 学习日期开始
+ ///
+ [Display(Name = "学习日期开始", Description = "学习日期的开始范围")]
+ public DateTime? StudyDateStart { get; set; }
+
+ ///
+ /// 学习日期结束
+ ///
+ [Display(Name = "学习日期结束", Description = "学习日期的结束范围")]
+ public DateTime? StudyDateEnd { get; set; }
+
+ ///
+ /// 当日状态
+ ///
+ [Display(Name = "当日状态", Description = "根据当日状态筛选")]
+ public string DailyStatus { get; set; }
+
+ ///
+ /// 是否下店协助
+ ///
+ [Display(Name = "是否下店协助", Description = "根据是否下店协助筛选")]
+ public int? IsStoreAssist { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ [Display(Name = "门店ID", Description = "根据门店ID筛选")]
+ public string StoreId { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ [Display(Name = "是否有效", Description = "根据是否有效筛选")]
+ public int? IsEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyStudentListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyStudentListOutput.cs
new file mode 100644
index 0000000..1301263
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyStudentListOutput.cs
@@ -0,0 +1,101 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 学习学员列表输出
+ ///
+ public class LqStudyStudentListOutput
+ {
+ ///
+ /// 学员ID
+ ///
+ [Display(Name = "学员ID")]
+ public string id { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ [Display(Name = "员工姓名")]
+ public string employeeName { get; set; }
+
+ ///
+ /// 员工电话
+ ///
+ [Display(Name = "员工电话")]
+ public string employeePhone { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [Display(Name = "员工ID")]
+ public string employeeId { get; set; }
+
+ ///
+ /// 入院时间
+ ///
+ [Display(Name = "入院时间")]
+ public DateTime admissionTime { get; set; }
+
+ ///
+ /// 班级ID
+ ///
+ [Display(Name = "班级ID")]
+ public string classId { get; set; }
+
+ ///
+ /// 所属班级
+ ///
+ [Display(Name = "所属班级")]
+ public string className { get; set; }
+
+ ///
+ /// HR归属
+ ///
+ [Display(Name = "HR归属")]
+ public string hrBelong { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ [Display(Name = "创建人ID")]
+ public string createUser { get; set; }
+
+ ///
+ /// 创建人姓名
+ ///
+ [Display(Name = "创建人姓名")]
+ public string createUserName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [Display(Name = "创建时间")]
+ public DateTime createTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ [Display(Name = "更新人ID")]
+ public string updateUser { get; set; }
+
+ ///
+ /// 更新人姓名
+ ///
+ [Display(Name = "更新人姓名")]
+ public string updateUserName { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [Display(Name = "更新时间")]
+ public DateTime? updateTime { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ [Display(Name = "是否有效")]
+ public int isEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyStudentListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyStudentListQueryInput.cs
new file mode 100644
index 0000000..f636a09
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyStudentListQueryInput.cs
@@ -0,0 +1,49 @@
+using NCC.Common.Filter;
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyClass
+{
+ ///
+ /// 学习学员列表查询输入
+ ///
+ public class LqStudyStudentListQueryInput : PageInputBase
+ {
+ ///
+ /// 班级ID
+ ///
+ [Required(ErrorMessage = "班级ID不能为空")]
+ [Display(Name = "班级ID", Description = "根据班级ID筛选学员")]
+ public string ClassId { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ [Display(Name = "员工姓名", Description = "根据员工姓名筛选")]
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工电话
+ ///
+ [Display(Name = "员工电话", Description = "根据员工电话筛选")]
+ public string EmployeePhone { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [Display(Name = "员工ID", Description = "根据员工ID筛选")]
+ public string EmployeeId { get; set; }
+
+ ///
+ /// HR归属
+ ///
+ [Display(Name = "HR归属", Description = "根据HR归属筛选")]
+ public string HrBelong { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ [Display(Name = "是否有效", Description = "根据是否有效筛选")]
+ public int? IsEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordCrInput.cs
new file mode 100644
index 0000000..cfef67e
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordCrInput.cs
@@ -0,0 +1,84 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyRecord
+{
+ ///
+ /// 学习记录创建输入
+ ///
+ public class LqStudyRecordCrInput
+ {
+ ///
+ /// 员工姓名
+ ///
+ [Required(ErrorMessage = "员工姓名不能为空")]
+ [StringLength(50, ErrorMessage = "员工姓名长度不能超过50个字符")]
+ [Display(Name = "员工姓名")]
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [Required(ErrorMessage = "员工ID不能为空")]
+ [StringLength(50, ErrorMessage = "员工ID长度不能超过50个字符")]
+ [Display(Name = "员工ID")]
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 学习类型
+ ///
+ [Required(ErrorMessage = "学习类型不能为空")]
+ [StringLength(50, ErrorMessage = "学习类型长度不能超过50个字符")]
+ [Display(Name = "学习类型")]
+ public string StudyType { get; set; }
+
+ ///
+ /// 交通费
+ ///
+ [Range(0, double.MaxValue, ErrorMessage = "交通费不能小于0")]
+ [Display(Name = "交通费")]
+ public decimal? TransportFee { get; set; }
+
+ ///
+ /// 学习日期
+ ///
+ [Required(ErrorMessage = "学习日期不能为空")]
+ [Display(Name = "学习日期")]
+ public DateTime StudyDate { get; set; }
+
+ ///
+ /// 当日状态
+ ///
+ [Required(ErrorMessage = "当日状态不能为空")]
+ [StringLength(50, ErrorMessage = "当日状态长度不能超过50个字符")]
+ [Display(Name = "当日状态")]
+ public string DailyStatus { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [StringLength(1000, ErrorMessage = "备注长度不能超过1000个字符")]
+ [Display(Name = "备注")]
+ public string Remark { get; set; }
+
+ ///
+ /// 是否下店协助(1:是 0:否)
+ ///
+ [Display(Name = "是否下店协助")]
+ public int IsStoreAssist { get; set; } = 0;
+
+ ///
+ /// 下店门店ID
+ ///
+ [StringLength(50, ErrorMessage = "下店门店ID长度不能超过50个字符")]
+ [Display(Name = "下店门店ID")]
+ public string StoreId { get; set; }
+
+ ///
+ /// 下店门店名称
+ ///
+ [StringLength(100, ErrorMessage = "下店门店名称长度不能超过100个字符")]
+ [Display(Name = "下店门店名称")]
+ public string StoreName { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordInfoOutput.cs
new file mode 100644
index 0000000..f2a15a7
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordInfoOutput.cs
@@ -0,0 +1,100 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyRecord
+{
+ ///
+ /// 学习记录详情输出
+ ///
+ public class LqStudyRecordInfoOutput
+ {
+ ///
+ /// 学习记录ID
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 学习类型
+ ///
+ public string StudyType { get; set; }
+
+ ///
+ /// 交通费
+ ///
+ public decimal? TransportFee { get; set; }
+
+ ///
+ /// 学习日期
+ ///
+ public DateTime StudyDate { get; set; }
+
+ ///
+ /// 当日状态
+ ///
+ public string DailyStatus { get; set; }
+
+ ///
+ /// 备注
+ ///
+ public string Remark { get; set; }
+
+ ///
+ /// 是否下店协助(1:是 0:否)
+ ///
+ public int IsStoreAssist { get; set; }
+
+ ///
+ /// 下店门店ID
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 下店门店名称
+ ///
+ public string StoreName { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建人姓名
+ ///
+ public string CreateUserName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新人姓名
+ ///
+ public string UpdateUserName { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ public int IsEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordListOutput.cs
new file mode 100644
index 0000000..1ff0f1f
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordListOutput.cs
@@ -0,0 +1,100 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyRecord
+{
+ ///
+ /// 学习记录列表输出
+ ///
+ public class LqStudyRecordListOutput
+ {
+ ///
+ /// 学习记录ID
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 学习类型
+ ///
+ public string StudyType { get; set; }
+
+ ///
+ /// 交通费
+ ///
+ public decimal? TransportFee { get; set; }
+
+ ///
+ /// 学习日期
+ ///
+ public DateTime StudyDate { get; set; }
+
+ ///
+ /// 当日状态
+ ///
+ public string DailyStatus { get; set; }
+
+ ///
+ /// 备注
+ ///
+ public string Remark { get; set; }
+
+ ///
+ /// 是否下店协助(1:是 0:否)
+ ///
+ public int IsStoreAssist { get; set; }
+
+ ///
+ /// 下店门店ID
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 下店门店名称
+ ///
+ public string StoreName { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建人姓名
+ ///
+ public string CreateUserName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新人姓名
+ ///
+ public string UpdateUserName { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ public int IsEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordListQueryInput.cs
new file mode 100644
index 0000000..a8526ba
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordListQueryInput.cs
@@ -0,0 +1,55 @@
+using NCC.Common.Filter;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyRecord
+{
+ ///
+ /// 学习记录列表查询输入
+ ///
+ public class LqStudyRecordListQueryInput : PageInputBase
+ {
+ ///
+ /// 员工姓名
+ ///
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 学习类型
+ ///
+ public string StudyType { get; set; }
+
+ ///
+ /// 学习开始日期
+ ///
+ public System.DateTime? StudyStartDate { get; set; }
+
+ ///
+ /// 学习结束日期
+ ///
+ public System.DateTime? StudyEndDate { get; set; }
+
+ ///
+ /// 当日状态
+ ///
+ public string DailyStatus { get; set; }
+
+ ///
+ /// 是否下店协助
+ ///
+ public int? IsStoreAssist { get; set; }
+
+ ///
+ /// 下店门店ID
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ public int? IsEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordUpInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordUpInput.cs
new file mode 100644
index 0000000..a9a998b
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordUpInput.cs
@@ -0,0 +1,19 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyRecord
+{
+ ///
+ /// 学习记录更新输入
+ ///
+ public class LqStudyRecordUpInput : LqStudyRecordCrInput
+ {
+ ///
+ /// 学习记录ID
+ ///
+ [Required(ErrorMessage = "学习记录ID不能为空")]
+ [StringLength(50, ErrorMessage = "学习记录ID长度不能超过50个字符")]
+ [Display(Name = "学习记录ID")]
+ public string Id { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentCrInput.cs
new file mode 100644
index 0000000..23694f1
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentCrInput.cs
@@ -0,0 +1,65 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyStudent
+{
+ ///
+ /// 学习学员创建输入
+ ///
+ public class LqStudyStudentCrInput
+ {
+ ///
+ /// 员工姓名
+ ///
+ [Required(ErrorMessage = "员工姓名不能为空")]
+ [StringLength(50, ErrorMessage = "员工姓名长度不能超过50个字符")]
+ [Display(Name = "员工姓名")]
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工电话
+ ///
+ [Required(ErrorMessage = "员工电话不能为空")]
+ [StringLength(20, ErrorMessage = "员工电话长度不能超过20个字符")]
+ [Display(Name = "员工电话")]
+ public string EmployeePhone { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [Required(ErrorMessage = "员工ID不能为空")]
+ [StringLength(50, ErrorMessage = "员工ID长度不能超过50个字符")]
+ [Display(Name = "员工ID")]
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 入院时间
+ ///
+ [Required(ErrorMessage = "入院时间不能为空")]
+ [Display(Name = "入院时间")]
+ public DateTime AdmissionTime { get; set; }
+
+ ///
+ /// 班级ID
+ ///
+ [Required(ErrorMessage = "班级ID不能为空")]
+ [StringLength(50, ErrorMessage = "班级ID长度不能超过50个字符")]
+ [Display(Name = "班级ID")]
+ public string ClassId { get; set; }
+
+ ///
+ /// 所属班级
+ ///
+ [Required(ErrorMessage = "所属班级不能为空")]
+ [StringLength(100, ErrorMessage = "所属班级长度不能超过100个字符")]
+ [Display(Name = "所属班级")]
+ public string ClassName { get; set; }
+
+ ///
+ /// HR归属
+ ///
+ [StringLength(50, ErrorMessage = "HR归属长度不能超过50个字符")]
+ [Display(Name = "HR归属")]
+ public string HrBelong { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentInfoOutput.cs
new file mode 100644
index 0000000..fe4b122
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentInfoOutput.cs
@@ -0,0 +1,100 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyStudent
+{
+ ///
+ /// 学习学员详情输出
+ ///
+ public class LqStudyStudentInfoOutput
+ {
+ ///
+ /// 学员ID
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工电话
+ ///
+ public string EmployeePhone { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 入院时间
+ ///
+ public DateTime AdmissionTime { get; set; }
+
+ ///
+ /// 班级ID
+ ///
+ public string ClassId { get; set; }
+
+ ///
+ /// 所属班级
+ ///
+ public string ClassName { get; set; }
+
+ ///
+ /// HR归属
+ ///
+ public string HrBelong { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建人姓名
+ ///
+ public string CreateUserName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新人姓名
+ ///
+ public string UpdateUserName { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ public int IsEffective { get; set; }
+
+ ///
+ /// 学习记录数量
+ ///
+ public int RecordCount { get; set; }
+
+ ///
+ /// 总交通费
+ ///
+ public decimal TotalTransportFee { get; set; }
+
+ ///
+ /// 下店协助次数
+ ///
+ public int StoreAssistCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentListOutput.cs
new file mode 100644
index 0000000..3fdeb1e
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentListOutput.cs
@@ -0,0 +1,90 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyStudent
+{
+ ///
+ /// 学习学员列表输出
+ ///
+ public class LqStudyStudentListOutput
+ {
+ ///
+ /// 学员ID
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工电话
+ ///
+ public string EmployeePhone { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 入院时间
+ ///
+ public DateTime AdmissionTime { get; set; }
+
+ ///
+ /// 班级ID
+ ///
+ public string ClassId { get; set; }
+
+ ///
+ /// 所属班级
+ ///
+ public string ClassName { get; set; }
+
+ ///
+ /// HR归属
+ ///
+ public string HrBelong { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建人姓名
+ ///
+ public string CreateUserName { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新人姓名
+ ///
+ public string UpdateUserName { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ public int IsEffective { get; set; }
+
+ ///
+ /// 学习记录数量
+ ///
+ public int RecordCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentListQueryInput.cs
new file mode 100644
index 0000000..631e404
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentListQueryInput.cs
@@ -0,0 +1,55 @@
+using NCC.Common.Filter;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyStudent
+{
+ ///
+ /// 学习学员列表查询输入
+ ///
+ public class LqStudyStudentListQueryInput : PageInputBase
+ {
+ ///
+ /// 员工姓名
+ ///
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工电话
+ ///
+ public string EmployeePhone { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 班级ID
+ ///
+ public string ClassId { get; set; }
+
+ ///
+ /// 所属班级
+ ///
+ public string ClassName { get; set; }
+
+ ///
+ /// HR归属
+ ///
+ public string HrBelong { get; set; }
+
+ ///
+ /// 入院开始时间
+ ///
+ public System.DateTime? AdmissionStartTime { get; set; }
+
+ ///
+ /// 入院结束时间
+ ///
+ public System.DateTime? AdmissionEndTime { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ public int? IsEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentUpInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentUpInput.cs
new file mode 100644
index 0000000..aef3dd5
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentUpInput.cs
@@ -0,0 +1,19 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStudyStudent
+{
+ ///
+ /// 学习学员更新输入
+ ///
+ public class LqStudyStudentUpInput : LqStudyStudentCrInput
+ {
+ ///
+ /// 学员ID
+ ///
+ [Required(ErrorMessage = "学员ID不能为空")]
+ [StringLength(50, ErrorMessage = "学员ID长度不能超过50个字符")]
+ [Display(Name = "学员ID")]
+ public string Id { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs
index 55d0219..6c8a987 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs
@@ -59,6 +59,7 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk
///
public string xfje { get; set; }
+
///
/// 手工费用
///
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListQueryInput.cs
index 8455b70..d612c3f 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListQueryInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListQueryInput.cs
@@ -74,5 +74,10 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk
///
public string czry { get; set; }
+ ///
+ /// 是否有效
+ ///
+ public int isEffective { get; set; } = 0;
+
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXmzl/LqXmzlStatisticsInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXmzl/LqXmzlStatisticsInput.cs
new file mode 100644
index 0000000..d939edb
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXmzl/LqXmzlStatisticsInput.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqXmzl
+{
+ ///
+ /// 品项维度统计输入参数
+ ///
+ public class LqXmzlStatisticsInput
+ {
+ ///
+ /// 开始时间
+ ///
+ public DateTime? StartTime { get; set; }
+
+ ///
+ /// 结束时间
+ ///
+ public DateTime? EndTime { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 品项分类
+ ///
+ public string Category { get; set; }
+
+ ///
+ /// 品项ID(单个品项统计)
+ ///
+ public string ItemId { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXmzl/LqXmzlStatisticsOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXmzl/LqXmzlStatisticsOutput.cs
new file mode 100644
index 0000000..58f52d6
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXmzl/LqXmzlStatisticsOutput.cs
@@ -0,0 +1,90 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqXmzl
+{
+ ///
+ /// 品项维度统计输出参数
+ ///
+ public class LqXmzlStatisticsOutput
+ {
+ ///
+ /// 品项ID
+ ///
+ public string ItemId { get; set; }
+
+ ///
+ /// 品项名称
+ ///
+ public string ItemName { get; set; }
+
+ ///
+ /// 品项编号
+ ///
+ public string ItemNumber { get; set; }
+
+ ///
+ /// 开卡业绩
+ ///
+ public decimal BillingAmount { get; set; }
+
+ ///
+ /// 开卡业绩占比
+ ///
+ public decimal BillingAmountRatio { get; set; }
+
+ ///
+ /// 购买总人数
+ ///
+ public int TotalBuyers { get; set; }
+
+ ///
+ /// 品项占比
+ ///
+ public decimal ItemRatio { get; set; }
+
+ ///
+ /// 复购人数
+ ///
+ public int RepeatBuyers { get; set; }
+
+ ///
+ /// 复购率
+ ///
+ public decimal RepeatBuyRate { get; set; }
+
+ ///
+ /// 消耗业绩
+ ///
+ public decimal ConsumeAmount { get; set; }
+
+ ///
+ /// 消耗占比
+ ///
+ public decimal ConsumeAmountRatio { get; set; }
+
+ ///
+ /// 消耗购买次数
+ ///
+ public int ConsumePurchaseCount { get; set; }
+
+ ///
+ /// 消耗赠送次数
+ ///
+ public int ConsumeGiftCount { get; set; }
+
+ ///
+ /// 消耗体验次数
+ ///
+ public int ConsumeExperienceCount { get; set; }
+
+ ///
+ /// 退卡业绩
+ ///
+ public decimal RefundAmount { get; set; }
+
+ ///
+ /// 退卡次数
+ ///
+ public int RefundCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_card_transfer_log/LqCardTransferLogEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_card_transfer_log/LqCardTransferLogEntity.cs
new file mode 100644
index 0000000..d2515d8
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_card_transfer_log/LqCardTransferLogEntity.cs
@@ -0,0 +1,87 @@
+using System;
+using NCC.Common.Const;
+using SqlSugar;
+
+namespace NCC.Extend.Entitys.lq_card_transfer_log
+{
+ ///
+ /// 转卡日志
+ ///
+ [SugarTable("lq_card_transfer_log")]
+ [Tenant(ClaimConst.TENANT_ID)]
+ public class LqCardTransferLogEntity
+ {
+ ///
+ /// 主键ID
+ ///
+ [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
+ public string Id { get; set; }
+
+ ///
+ /// 退卡ID
+ ///
+ [SugarColumn(ColumnName = "F_RefundCardId")]
+ public string RefundCardId { get; set; }
+
+ ///
+ /// 开卡ID
+ ///
+ [SugarColumn(ColumnName = "F_BillingCardId")]
+ public string BillingCardId { get; set; }
+
+ ///
+ /// 转卡人会员ID
+ ///
+ [SugarColumn(ColumnName = "F_TransferFromMemberId")]
+ public string TransferFromMemberId { get; set; }
+
+ ///
+ /// 被转卡人会员ID
+ ///
+ [SugarColumn(ColumnName = "F_TransferToMemberId")]
+ public string TransferToMemberId { get; set; }
+
+ ///
+ /// 转卡总金额
+ ///
+ [SugarColumn(ColumnName = "F_TransferAmount")]
+ public decimal TransferAmount { get; set; }
+
+ ///
+ /// 转卡时间
+ ///
+ [SugarColumn(ColumnName = "F_TransferTime")]
+ public DateTime TransferTime { get; set; }
+
+ ///
+ /// 操作人ID
+ ///
+ [SugarColumn(ColumnName = "F_OperatorId")]
+ public string OperatorId { get; set; }
+
+
+ ///
+ /// 备注信息
+ ///
+ [SugarColumn(ColumnName = "F_Remarks")]
+ public string Remarks { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "F_CreateTime")]
+ public DateTime? CreateTime { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnName = "F_UpdateTime")]
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效
+ ///
+ [SugarColumn(ColumnName = "F_IsEffective")]
+ public int IsEffective { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_hytk/LqHytkHytkEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_hytk/LqHytkHytkEntity.cs
index 6905bc1..745854c 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_hytk/LqHytkHytkEntity.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_hytk/LqHytkHytkEntity.cs
@@ -67,6 +67,12 @@ namespace NCC.Extend.Entitys.lq_hytk_hytk
public decimal? Tkje { get; set; }
///
+ /// 实退金额
+ ///
+ [SugarColumn(ColumnName = "F_ActualRefundAmount")]
+ public decimal? ActualRefundAmount { get; set; }
+
+ ///
/// 手工费用
///
[SugarColumn(ColumnName = "sgfy")]
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_inventory/LqInventoryEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_inventory/LqInventoryEntity.cs
new file mode 100644
index 0000000..075781b
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_inventory/LqInventoryEntity.cs
@@ -0,0 +1,86 @@
+using System;
+using NCC.Common.Const;
+using SqlSugar;
+
+namespace NCC.Extend.Entitys.lq_inventory
+{
+ ///
+ /// 库存表
+ ///
+ [SugarTable("lq_inventory")]
+ [Tenant(ClaimConst.TENANT_ID)]
+ public class LqInventoryEntity
+ {
+ ///
+ /// 库存ID
+ ///
+ [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
+ public string Id { get; set; }
+
+ ///
+ /// 产品名称
+ ///
+ [SugarColumn(ColumnName = "F_ProductName")]
+ public string ProductName { get; set; }
+
+ ///
+ /// 价格
+ ///
+ [SugarColumn(ColumnName = "F_Price")]
+ public decimal Price { get; set; }
+
+ ///
+ /// 数量
+ ///
+ [SugarColumn(ColumnName = "F_Quantity")]
+ public int Quantity { get; set; } = 0;
+
+ ///
+ /// 产品类别
+ ///
+ [SugarColumn(ColumnName = "F_ProductCategory")]
+ public string ProductCategory { get; set; }
+
+ ///
+ /// 归属部门ID
+ ///
+ [SugarColumn(ColumnName = "F_DepartmentId")]
+ public string DepartmentId { get; set; }
+
+ ///
+ /// 标准单位
+ ///
+ [SugarColumn(ColumnName = "F_StandardUnit")]
+ public string StandardUnit { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ [SugarColumn(ColumnName = "F_CreateUser")]
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "F_CreateTime")]
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ [SugarColumn(ColumnName = "F_UpdateUser")]
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnName = "F_UpdateTime")]
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ [SugarColumn(ColumnName = "F_IsEffective")]
+ public int IsEffective { get; set; } = 1;
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_inventory_usage/LqInventoryUsageEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_inventory_usage/LqInventoryUsageEntity.cs
new file mode 100644
index 0000000..745b1a9
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_inventory_usage/LqInventoryUsageEntity.cs
@@ -0,0 +1,80 @@
+using System;
+using NCC.Common.Const;
+using SqlSugar;
+
+namespace NCC.Extend.Entitys.lq_inventory_usage
+{
+ ///
+ /// 库存使用记录表
+ ///
+ [SugarTable("lq_inventory_usage")]
+ [Tenant(ClaimConst.TENANT_ID)]
+ public class LqInventoryUsageEntity
+ {
+ ///
+ /// 使用记录ID
+ ///
+ [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
+ public string Id { get; set; }
+
+ ///
+ /// 产品ID
+ ///
+ [SugarColumn(ColumnName = "F_ProductId")]
+ public string ProductId { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ [SugarColumn(ColumnName = "F_StoreId")]
+ public string StoreId { get; set; }
+
+ ///
+ /// 使用时间
+ ///
+ [SugarColumn(ColumnName = "F_UsageTime")]
+ public DateTime UsageTime { get; set; }
+
+ ///
+ /// 使用数量
+ ///
+ [SugarColumn(ColumnName = "F_UsageQuantity")]
+ public int UsageQuantity { get; set; }
+
+ ///
+ /// 关联消耗ID
+ ///
+ [SugarColumn(ColumnName = "F_RelatedConsumeId")]
+ public string RelatedConsumeId { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ [SugarColumn(ColumnName = "F_CreateUser")]
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "F_CreateTime")]
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ [SugarColumn(ColumnName = "F_UpdateUser")]
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnName = "F_UpdateTime")]
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ [SugarColumn(ColumnName = "F_IsEffective")]
+ public int IsEffective { get; set; } = 1;
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_statistics_store_total_performance/LqStatisticsStoreTotalPerformanceEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_statistics_store_total_performance/LqStatisticsStoreTotalPerformanceEntity.cs
index a29d054..2508ed3 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_statistics_store_total_performance/LqStatisticsStoreTotalPerformanceEntity.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_statistics_store_total_performance/LqStatisticsStoreTotalPerformanceEntity.cs
@@ -90,6 +90,18 @@ namespace NCC.Extend.Entitys.lq_statistics_store_total_performance
public decimal UpgradeOrderPerformance { get; set; }
///
+ /// 退款业绩
+ ///
+ [SugarColumn(ColumnName = "F_RefundAmount")]
+ public decimal RefundAmount { get; set; }
+
+ ///
+ /// 退款次数
+ ///
+ [SugarColumn(ColumnName = "F_RefundCount")]
+ public int RefundCount { get; set; }
+
+ ///
/// 创建时间
///
[SugarColumn(ColumnName = "F_CreateTime")]
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_class/LqStudyClassEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_class/LqStudyClassEntity.cs
new file mode 100644
index 0000000..5e0805e
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_class/LqStudyClassEntity.cs
@@ -0,0 +1,80 @@
+using System;
+using NCC.Common.Const;
+using SqlSugar;
+
+namespace NCC.Extend.Entitys.lq_study_class
+{
+ ///
+ /// 学习班级表
+ ///
+ [SugarTable("lq_study_class")]
+ [Tenant(ClaimConst.TENANT_ID)]
+ public class LqStudyClassEntity
+ {
+ ///
+ /// 班级ID
+ ///
+ [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
+ public string Id { get; set; }
+
+ ///
+ /// 班级名称
+ ///
+ [SugarColumn(ColumnName = "F_ClassName")]
+ public string ClassName { get; set; }
+
+ ///
+ /// 任教老师ID
+ ///
+ [SugarColumn(ColumnName = "F_TeacherId")]
+ public string TeacherId { get; set; }
+
+ ///
+ /// 开始时间
+ ///
+ [SugarColumn(ColumnName = "F_StartTime")]
+ public DateTime StartTime { get; set; }
+
+ ///
+ /// 结束时间
+ ///
+ [SugarColumn(ColumnName = "F_EndTime")]
+ public DateTime EndTime { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnName = "F_Remark")]
+ public string Remark { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ [SugarColumn(ColumnName = "F_CreateUser")]
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "F_CreateTime")]
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ [SugarColumn(ColumnName = "F_UpdateUser")]
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnName = "F_UpdateTime")]
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ [SugarColumn(ColumnName = "F_IsEffective")]
+ public int IsEffective { get; set; } = 1;
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_record/LqStudyRecordEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_record/LqStudyRecordEntity.cs
new file mode 100644
index 0000000..eb4cd0d
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_record/LqStudyRecordEntity.cs
@@ -0,0 +1,110 @@
+using System;
+using NCC.Common.Const;
+using SqlSugar;
+
+namespace NCC.Extend.Entitys.lq_study_record
+{
+ ///
+ /// 学习记录表
+ ///
+ [SugarTable("lq_study_record")]
+ [Tenant(ClaimConst.TENANT_ID)]
+ public class LqStudyRecordEntity
+ {
+ ///
+ /// 学习记录ID
+ ///
+ [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
+ public string Id { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ [SugarColumn(ColumnName = "F_EmployeeName")]
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [SugarColumn(ColumnName = "F_EmployeeId")]
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 学习类型
+ ///
+ [SugarColumn(ColumnName = "F_StudyType")]
+ public string StudyType { get; set; }
+
+ ///
+ /// 交通费
+ ///
+ [SugarColumn(ColumnName = "F_TransportFee")]
+ public decimal? TransportFee { get; set; }
+
+ ///
+ /// 学习日期
+ ///
+ [SugarColumn(ColumnName = "F_StudyDate")]
+ public DateTime StudyDate { get; set; }
+
+ ///
+ /// 当日状态
+ ///
+ [SugarColumn(ColumnName = "F_DailyStatus")]
+ public string DailyStatus { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnName = "F_Remark")]
+ public string Remark { get; set; }
+
+ ///
+ /// 是否下店协助(1:是 0:否)
+ ///
+ [SugarColumn(ColumnName = "F_IsStoreAssist")]
+ public int IsStoreAssist { get; set; } = 0;
+
+ ///
+ /// 下店门店ID
+ ///
+ [SugarColumn(ColumnName = "F_StoreId")]
+ public string StoreId { get; set; }
+
+ ///
+ /// 下店门店名称
+ ///
+ [SugarColumn(ColumnName = "F_StoreName")]
+ public string StoreName { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ [SugarColumn(ColumnName = "F_CreateUser")]
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "F_CreateTime")]
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ [SugarColumn(ColumnName = "F_UpdateUser")]
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnName = "F_UpdateTime")]
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ [SugarColumn(ColumnName = "F_IsEffective")]
+ public int IsEffective { get; set; } = 1;
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_student/LqStudyStudentEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_student/LqStudyStudentEntity.cs
new file mode 100644
index 0000000..e9be16c
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_student/LqStudyStudentEntity.cs
@@ -0,0 +1,98 @@
+using System;
+using NCC.Common.Const;
+using SqlSugar;
+
+namespace NCC.Extend.Entitys.lq_study_student
+{
+ ///
+ /// 学习学员表
+ ///
+ [SugarTable("lq_study_student")]
+ [Tenant(ClaimConst.TENANT_ID)]
+ public class LqStudyStudentEntity
+ {
+ ///
+ /// 学员ID
+ ///
+ [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
+ public string Id { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ [SugarColumn(ColumnName = "F_EmployeeName")]
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工电话
+ ///
+ [SugarColumn(ColumnName = "F_EmployeePhone")]
+ public string EmployeePhone { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [SugarColumn(ColumnName = "F_EmployeeId")]
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 入院时间
+ ///
+ [SugarColumn(ColumnName = "F_AdmissionTime")]
+ public DateTime AdmissionTime { get; set; }
+
+ ///
+ /// 班级ID
+ ///
+ [SugarColumn(ColumnName = "F_ClassId")]
+ public string ClassId { get; set; }
+
+ ///
+ /// 所属班级
+ ///
+ [SugarColumn(ColumnName = "F_ClassName")]
+ public string ClassName { get; set; }
+
+ ///
+ /// HR归属
+ ///
+ [SugarColumn(ColumnName = "F_HrBelong")]
+ public string HrBelong { get; set; }
+
+ ///
+ /// 创建人ID
+ ///
+ [SugarColumn(ColumnName = "F_CreateUser")]
+ public string CreateUser { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "F_CreateTime")]
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新人ID
+ ///
+ [SugarColumn(ColumnName = "F_UpdateUser")]
+ public string UpdateUser { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnName = "F_UpdateTime")]
+ public DateTime? UpdateTime { get; set; }
+
+ ///
+ /// 是否有效(1:有效 0:无效)
+ ///
+ [SugarColumn(ColumnName = "F_IsEffective")]
+ public int IsEffective { get; set; } = 1;
+
+ ///
+ /// 删除标记(0:未删除 1:已删除)
+ ///
+ [SugarColumn(ColumnName = "F_DeleteMark")]
+ public int? DeleteMark { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/ILqCardTransferLogService.cs b/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/ILqCardTransferLogService.cs
new file mode 100644
index 0000000..20a802b
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/ILqCardTransferLogService.cs
@@ -0,0 +1,12 @@
+using NCC.Extend.Entitys.Dto.LqCardTransferLog;
+
+namespace NCC.Extend.Interfaces
+{
+ ///
+ /// 转卡日志服务接口
+ ///
+ public interface ILqCardTransferLogService
+ {
+ // 接口方法将在Service实现中定义
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqInventory/ILqInventoryService.cs b/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqInventory/ILqInventoryService.cs
new file mode 100644
index 0000000..9fe839c
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqInventory/ILqInventoryService.cs
@@ -0,0 +1,13 @@
+using System.Threading.Tasks;
+using NCC.Extend.Entitys.Dto.LqInventory;
+using NCC.Common.Filter;
+
+namespace NCC.Extend.Interfaces.LqInventory
+{
+ ///
+ /// 库存服务接口
+ ///
+ public interface ILqInventoryService
+ {
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqInventoryUsage/ILqInventoryUsageService.cs b/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqInventoryUsage/ILqInventoryUsageService.cs
new file mode 100644
index 0000000..45a3cf4
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqInventoryUsage/ILqInventoryUsageService.cs
@@ -0,0 +1,62 @@
+using System.Threading.Tasks;
+using NCC.Extend.Entitys.Dto.LqInventoryUsage;
+using NCC.Common.Filter;
+
+namespace NCC.Extend.Interfaces.LqInventoryUsage
+{
+ ///
+ /// 库存使用记录服务接口
+ ///
+ public interface ILqInventoryUsageService
+ {
+ ///
+ /// 添加库存使用记录
+ ///
+ /// 创建输入
+ ///
+ Task CreateAsync(LqInventoryUsageCrInput input);
+
+ ///
+ /// 作废库存使用记录
+ ///
+ /// 使用记录ID
+ /// 作废备注
+ ///
+ Task CancelAsync(string id, string remarks = null);
+
+ ///
+ /// 获取使用记录列表
+ ///
+ /// 查询输入
+ ///
+ Task GetListAsync(LqInventoryUsageListQueryInput input);
+
+ ///
+ /// 统计时间周期内每个产品的使用数量
+ ///
+ /// 统计查询输入
+ ///
+ Task GetProductUsageStatisticsAsync(LqInventoryUsageStatisticsInput input);
+
+ ///
+ /// 统计时间周期内每个门店的使用情况
+ ///
+ /// 统计查询输入
+ ///
+ Task GetStoreUsageStatisticsAsync(LqInventoryUsageStatisticsInput input);
+
+ ///
+ /// 统计时间周期内使用趋势
+ ///
+ /// 统计查询输入
+ ///
+ Task GetUsageTrendStatisticsAsync(LqInventoryUsageStatisticsInput input);
+
+ ///
+ /// 统计产品使用排行榜
+ ///
+ /// 统计查询输入
+ ///
+ Task GetProductUsageRankingAsync(LqInventoryUsageStatisticsInput input);
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqStudyClass/ILqStudyClassService.cs b/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqStudyClass/ILqStudyClassService.cs
new file mode 100644
index 0000000..453c3ad
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqStudyClass/ILqStudyClassService.cs
@@ -0,0 +1,54 @@
+using System.Threading.Tasks;
+using NCC.Extend.Entitys.Dto.LqStudyClass;
+using NCC.Common.Filter;
+
+namespace NCC.Extend.Interfaces.LqStudyClass
+{
+ ///
+ /// 学习班级服务接口
+ ///
+ public interface ILqStudyClassService
+ {
+ ///
+ /// 创建学习班级并添加学员
+ ///
+ /// 创建输入
+ ///
+ Task CreateClassWithStudentsAsync(LqStudyClassCreateWithStudentsInput input);
+
+ ///
+ /// 向现有班级添加学员
+ ///
+ /// 添加学员输入
+ ///
+ Task AddStudentsToClassAsync(LqStudyClassAddStudentsInput input);
+
+ ///
+ /// 获取所有班级列表
+ ///
+ /// 查询输入
+ ///
+ Task GetClassListAsync(LqStudyClassListQueryInput input);
+
+ ///
+ /// 获取班级下所有学员信息
+ ///
+ /// 查询输入
+ ///
+ Task GetStudentListByClassIdAsync(LqStudyStudentListQueryInput input);
+
+ ///
+ /// 添加学习记录
+ ///
+ /// 学习记录输入
+ ///
+ Task AddStudyRecordAsync(LqStudyRecordCreateInput input);
+
+ ///
+ /// 获取学习记录列表
+ ///
+ /// 查询输入
+ ///
+ Task GetStudyRecordListAsync(LqStudyRecordListQueryInput input);
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqCardTransferLogService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqCardTransferLogService.cs
new file mode 100644
index 0000000..ac0f8d4
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqCardTransferLogService.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using NCC.Common.Core.Manager;
+using NCC.Common.Filter;
+using NCC.Dependency;
+using NCC.DynamicApiController;
+using NCC.Extend.Entitys.Dto.LqCardTransferLog;
+using NCC.Extend.Entitys.lq_card_transfer_log;
+using NCC.Extend.Interfaces;
+using NCC.FriendlyException;
+using SqlSugar;
+
+namespace NCC.Extend.LqCardTransferLog
+{
+ ///
+ /// 转卡日志服务
+ ///
+ [ApiDescriptionSettings(Tag = "绿纤转卡日志服务", Name = "LqCardTransferLog", Order = 100)]
+ [Route("api/Extend/[controller]")]
+ public class LqCardTransferLogService : IDynamicApiController, ILqCardTransferLogService, ITransient
+ {
+ private readonly ISqlSugarClient _db;
+ private readonly IUserManager _userManager;
+ private readonly ILogger _logger;
+
+ public LqCardTransferLogService(ISqlSugarClient db, IUserManager userManager, ILogger logger)
+ {
+ _db = db;
+ _userManager = userManager;
+ _logger = logger;
+ }
+
+ #region 添加转卡日志
+ ///
+ /// 添加转卡日志
+ ///
+ /// 转卡日志创建输入参数
+ /// 创建结果
+ [HttpPost("add")]
+ public async Task AddTransferLog([FromBody] LqCardTransferLogCrInput input)
+ {
+ try
+ {
+ if (input == null)
+ {
+ throw NCCException.Oh("输入参数不能为空");
+ }
+
+ var entity = new LqCardTransferLogEntity
+ {
+ Id = Guid.NewGuid().ToString(),
+ RefundCardId = input.refundCardId,
+ BillingCardId = input.billingCardId,
+ TransferFromMemberId = input.transferFromMemberId,
+ TransferToMemberId = input.transferToMemberId,
+ TransferAmount = input.transferAmount,
+ TransferTime = input.transferTime,
+ OperatorId = input.operatorId,
+ Remarks = input.remarks ?? "",
+ CreateTime = DateTime.Now,
+ IsEffective = 1
+ };
+
+ var result = await _db.Insertable(entity).ExecuteCommandAsync();
+
+ return new
+ {
+ Success = true,
+ Message = "转卡日志创建成功",
+ Data = new { Id = entity.Id }
+ };
+ }
+ catch (Exception ex)
+ {
+ throw NCCException.Oh($"创建转卡日志失败: {ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 获取转卡日志列表
+ ///
+ /// 获取转卡日志列表
+ ///
+ /// 查询输入参数
+ /// 转卡日志列表
+ [HttpGet("")]
+ public async Task GetList([FromQuery] LqCardTransferLogListQueryInput input)
+ {
+ try
+ {
+ var result = await _db.Queryable()
+ .WhereIF(input.isEffective != 0, x => x.IsEffective == input.isEffective)
+ .WhereIF(!string.IsNullOrEmpty(input.transferFromMemberId), x => x.TransferFromMemberId == input.transferFromMemberId)
+ .WhereIF(!string.IsNullOrEmpty(input.transferToMemberId), x => x.TransferToMemberId == input.transferToMemberId)
+ .WhereIF(!string.IsNullOrEmpty(input.operatorId), x => x.OperatorId == input.operatorId)
+ .WhereIF(input.transferStartTime.HasValue, x => x.TransferTime >= input.transferStartTime.Value)
+ .WhereIF(input.transferEndTime.HasValue, x => x.TransferTime <= input.transferEndTime.Value)
+ .WhereIF(input.minTransferAmount.HasValue, x => x.TransferAmount >= input.minTransferAmount.Value)
+ .WhereIF(input.maxTransferAmount.HasValue, x => x.TransferAmount <= input.maxTransferAmount.Value)
+ .WhereIF(!string.IsNullOrEmpty(input.keyword), x => x.Remarks.Contains(input.keyword))
+ .Select(x => new LqCardTransferLogListOutput
+ {
+ id = x.Id,
+ refundCardId = x.RefundCardId,
+ billingCardId = x.BillingCardId,
+ transferFromMemberId = x.TransferFromMemberId,
+ transferToMemberId = x.TransferToMemberId,
+ transferAmount = x.TransferAmount,
+ transferTime = x.TransferTime,
+ operatorId = x.OperatorId,
+ remarks = x.Remarks,
+ createTime = x.CreateTime,
+ updateTime = x.UpdateTime,
+ isEffective = x.IsEffective
+ })
+ .OrderBy(x => x.transferTime, OrderByType.Desc)
+ .ToPagedListAsync(input.currentPage, input.pageSize);
+
+ return PageResult.SqlSugarPageResult(result);
+ }
+ catch (Exception ex)
+ {
+ throw NCCException.Oh($"获取转卡日志列表失败: {ex.Message}");
+ }
+ }
+ #endregion
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs
index b5e80d6..fad3d6d 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs
@@ -96,6 +96,7 @@ namespace NCC.Extend.LqHytkHytk
.WhereIF(queryTksj != null, p => p.Tksj >= new DateTime(startTksj.ToDate().Year, startTksj.ToDate().Month, startTksj.ToDate().Day, 0, 0, 0))
.WhereIF(queryTksj != null, p => p.Tksj <= new DateTime(endTksj.ToDate().Year, endTksj.ToDate().Month, endTksj.ToDate().Day, 23, 59, 59))
.WhereIF(!string.IsNullOrEmpty(input.czry), p => p.Czry.Equals(input.czry))
+ .WhereIF(input.isEffective != 0, p => p.IsEffective == input.isEffective)
.Select(it => new LqHytkHytkListOutput
{
id = it.Id,
@@ -116,6 +117,7 @@ namespace NCC.Extend.LqHytkHytk
fileUrl = it.FileUrl,
isEffective = it.IsEffective,
cancelRemark = it.CancelRemark,
+ actualRefundAmount = it.ActualRefundAmount
})
.MergeTable()
.OrderBy(sidx + " " + input.sort)
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqInventoryService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqInventoryService.cs
new file mode 100644
index 0000000..1aa2892
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqInventoryService.cs
@@ -0,0 +1,290 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using NCC.Common.Core.Manager;
+using NCC.Common.Enum;
+using NCC.Common.Filter;
+using NCC.Dependency;
+using NCC.DynamicApiController;
+using NCC.Extend.Entitys.Dto.LqInventory;
+using NCC.Extend.Entitys.Enum;
+using NCC.Extend.Entitys.lq_inventory;
+using NCC.Extend.Interfaces.LqInventory;
+using NCC.FriendlyException;
+using NCC.System.Entitys.Permission;
+using SqlSugar;
+using Yitter.IdGenerator;
+
+namespace NCC.Extend
+{
+ ///
+ /// 库存服务
+ ///
+ [ApiDescriptionSettings(Tag = "绿纤库存管理", Name = "LqInventory", Order = 200)]
+ [Route("api/Extend/LqInventory")]
+ public class LqInventoryService : IDynamicApiController, ITransient, ILqInventoryService
+ {
+ private readonly IUserManager _userManager;
+ private readonly ILogger _logger;
+ private readonly ISqlSugarClient _db;
+
+ ///
+ /// 构造函数
+ ///
+ /// 用户管理器
+ /// 日志记录器
+ /// 数据库客户端
+ public LqInventoryService(IUserManager userManager, ILogger logger, ISqlSugarClient db)
+ {
+ _userManager = userManager;
+ _logger = logger;
+ _db = db;
+ }
+
+ #region 创建库存
+ ///
+ /// 创建库存
+ ///
+ /// 创建输入
+ /// 创建结果
+ [HttpPost("Create")]
+ public async Task CreateAsync([FromBody] LqInventoryCrInput input)
+ {
+ try
+ {
+ // 检查产品名称是否已存在
+ var existingProduct = await _db.Queryable()
+ .Where(x => x.ProductName == input.ProductName && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .FirstAsync();
+ if (existingProduct != null)
+ {
+ throw NCCException.Oh($"产品名称'{input.ProductName}'已存在");
+ }
+
+ // 创建库存记录
+ var inventoryEntity = new LqInventoryEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ ProductName = input.ProductName,
+ Price = input.Price,
+ Quantity = input.Quantity,
+ ProductCategory = input.ProductCategory,
+ DepartmentId = input.DepartmentId,
+ StandardUnit = input.StandardUnit,
+ CreateUser = _userManager.UserId,
+ CreateTime = DateTime.Now,
+ IsEffective = StatusEnum.有效.GetHashCode()
+ };
+
+ var isOk = await _db.Insertable(inventoryEntity).ExecuteCommandAsync();
+ if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "创建库存失败");
+ throw NCCException.Oh($"创建失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 更新库存
+ ///
+ /// 更新库存
+ ///
+ /// 更新输入
+ /// 更新结果
+ [HttpPut("Update")]
+ public async Task UpdateAsync([FromBody] LqInventoryUpInput input)
+ {
+ try
+ {
+ // 检查库存记录是否存在
+ var existingInventory = await _db.Queryable()
+ .Where(x => x.Id == input.Id && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .FirstAsync();
+
+ if (existingInventory == null)
+ {
+ throw NCCException.Oh("库存记录不存在或已失效");
+ }
+
+ // 检查产品名称是否与其他记录重复
+ var duplicateProduct = await _db.Queryable()
+ .Where(x => x.ProductName == input.ProductName && x.Id != input.Id && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .FirstAsync();
+
+ if (duplicateProduct != null)
+ {
+ throw NCCException.Oh($"产品名称'{input.ProductName}'已存在");
+ }
+
+ // 更新库存记录
+ existingInventory.ProductName = input.ProductName;
+ existingInventory.Price = input.Price;
+ existingInventory.Quantity = input.Quantity;
+ existingInventory.ProductCategory = input.ProductCategory;
+ existingInventory.DepartmentId = input.DepartmentId;
+ existingInventory.StandardUnit = input.StandardUnit;
+ existingInventory.UpdateUser = _userManager.UserId;
+ existingInventory.UpdateTime = DateTime.Now;
+
+ var isOk = await _db.Updateable(existingInventory).ExecuteCommandAsync();
+ if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "更新库存失败");
+ throw NCCException.Oh($"更新失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 获取库存列表
+ ///
+ /// 获取库存列表
+ ///
+ /// 查询输入
+ /// 库存列表
+ [HttpGet("GetList")]
+ public async Task GetListAsync([FromQuery] LqInventoryListQueryInput input)
+ {
+ try
+ {
+ var sidx = input.sidx == null ? "id" : input.sidx;
+
+ // 查询库存信息
+ var data = await _db.Queryable()
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ProductName), x => x.ProductName.Contains(input.ProductName))
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ProductCategory), x => x.ProductCategory.Contains(input.ProductCategory))
+ .WhereIF(!string.IsNullOrWhiteSpace(input.DepartmentId), x => x.DepartmentId == input.DepartmentId)
+ .WhereIF(input.PriceMin.HasValue, x => x.Price >= input.PriceMin.Value)
+ .WhereIF(input.PriceMax.HasValue, x => x.Price <= input.PriceMax.Value)
+ .WhereIF(input.QuantityMin.HasValue, x => x.Quantity >= input.QuantityMin.Value)
+ .WhereIF(input.QuantityMax.HasValue, x => x.Quantity <= input.QuantityMax.Value)
+ .WhereIF(input.IsEffective.HasValue, x => x.IsEffective == input.IsEffective.Value)
+ .Select(x => new LqInventoryListOutput
+ {
+ id = x.Id,
+ productName = x.ProductName,
+ price = x.Price,
+ quantity = x.Quantity,
+ productCategory = x.ProductCategory,
+ departmentId = x.DepartmentId,
+ departmentName = "",
+ standardUnit = x.StandardUnit,
+ totalValue = x.Price * x.Quantity,
+ createUser = x.CreateUser,
+ createUserName = "",
+ createTime = x.CreateTime,
+ updateUser = x.UpdateUser,
+ updateUserName = "",
+ updateTime = x.UpdateTime,
+ isEffective = x.IsEffective
+ })
+ .MergeTable()
+ .OrderBy(sidx + " " + input.sort)
+ .ToPagedListAsync(input.currentPage, input.pageSize);
+
+ // 补充用户名称信息
+ foreach (var item in data.list)
+ {
+ if (!string.IsNullOrEmpty(item.departmentId))
+ {
+ var deptUser = await _db.Queryable().Where(u => u.Id == item.departmentId).FirstAsync();
+ item.departmentName = deptUser?.RealName ?? "";
+ }
+ if (!string.IsNullOrEmpty(item.createUser))
+ {
+ var createUser = await _db.Queryable().Where(u => u.Id == item.createUser).FirstAsync();
+ item.createUserName = createUser?.RealName ?? "";
+ }
+ if (!string.IsNullOrEmpty(item.updateUser))
+ {
+ var updateUser = await _db.Queryable().Where(u => u.Id == item.updateUser).FirstAsync();
+ item.updateUserName = updateUser?.RealName ?? "";
+ }
+ }
+ return PageResult.SqlSugarPageResult(data);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取库存列表失败");
+ throw NCCException.Oh($"获取库存列表失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 获取库存详情
+ ///
+ /// 获取库存详情
+ ///
+ /// 库存ID
+ /// 库存详情
+ [HttpGet("GetInfo")]
+ public async Task GetInfoAsync([FromQuery] string id)
+ {
+ try
+ {
+ if (string.IsNullOrWhiteSpace(id))
+ {
+ throw NCCException.Oh("库存ID不能为空");
+ }
+ // 查询库存信息
+ var inventory = await _db.Queryable().Where(x => x.Id == id).FirstAsync();
+
+ if (inventory == null)
+ {
+ throw NCCException.Oh("库存记录不存在");
+ }
+
+ var result = new LqInventoryInfoOutput
+ {
+ id = inventory.Id,
+ productName = inventory.ProductName,
+ price = inventory.Price,
+ quantity = inventory.Quantity,
+ productCategory = inventory.ProductCategory,
+ departmentId = inventory.DepartmentId,
+ departmentName = "",
+ standardUnit = inventory.StandardUnit,
+ totalValue = inventory.Price * inventory.Quantity,
+ createUser = inventory.CreateUser,
+ createUserName = "",
+ createTime = inventory.CreateTime,
+ updateUser = inventory.UpdateUser,
+ updateUserName = "",
+ updateTime = inventory.UpdateTime,
+ isEffective = inventory.IsEffective
+ };
+
+ // 补充用户名称信息
+ if (!string.IsNullOrEmpty(result.departmentId))
+ {
+ var deptUser = await _db.Queryable().Where(u => u.Id == result.departmentId).FirstAsync();
+ result.departmentName = deptUser?.RealName ?? "";
+ }
+ if (!string.IsNullOrEmpty(result.createUser))
+ {
+ var createUser = await _db.Queryable().Where(u => u.Id == result.createUser).FirstAsync();
+ result.createUserName = createUser?.RealName ?? "";
+ }
+ if (!string.IsNullOrEmpty(result.updateUser))
+ {
+ var updateUser = await _db.Queryable().Where(u => u.Id == result.updateUser).FirstAsync();
+ result.updateUserName = updateUser?.RealName ?? "";
+ }
+
+ return result;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取库存详情失败");
+ throw NCCException.Oh($"获取库存详情失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqInventoryUsageService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqInventoryUsageService.cs
new file mode 100644
index 0000000..f4a181f
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqInventoryUsageService.cs
@@ -0,0 +1,497 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using NCC.Common.Core.Manager;
+using NCC.Common.Enum;
+using NCC.Common.Filter;
+using NCC.Dependency;
+using NCC.DynamicApiController;
+using NCC.Extend.Entitys.Dto.LqInventoryUsage;
+using NCC.Extend.Entitys.Enum;
+using NCC.Extend.Entitys.lq_inventory;
+using NCC.Extend.Entitys.lq_inventory_usage;
+using NCC.Extend.Interfaces.LqInventoryUsage;
+using NCC.FriendlyException;
+using NCC.System.Entitys.Permission;
+using SqlSugar;
+using Yitter.IdGenerator;
+
+namespace NCC.Extend
+{
+ ///
+ /// 库存使用记录服务
+ ///
+ [ApiDescriptionSettings(Tag = "绿纤库存使用记录管理", Name = "LqInventoryUsage", Order = 200)]
+ [Route("api/Extend/LqInventoryUsage")]
+ public class LqInventoryUsageService : IDynamicApiController, ITransient, ILqInventoryUsageService
+ {
+ private readonly IUserManager _userManager;
+ private readonly ILogger _logger;
+ private readonly ISqlSugarClient _db;
+
+ ///
+ /// 构造函数
+ ///
+ /// 用户管理器
+ /// 日志记录器
+ /// 数据库客户端
+ public LqInventoryUsageService(IUserManager userManager, ILogger logger, ISqlSugarClient db)
+ {
+ _userManager = userManager;
+ _logger = logger;
+ _db = db;
+ }
+
+ #region 添加库存使用记录
+ ///
+ /// 添加库存使用记录
+ ///
+ /// 创建输入
+ /// 创建结果
+ [HttpPost("Create")]
+ public async Task CreateAsync([FromBody] LqInventoryUsageCrInput input)
+ {
+ try
+ {
+ // 验证产品是否存在
+ var product = await _db.Queryable().Where(x => x.Id == input.ProductId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
+
+ if (product == null)
+ {
+ throw NCCException.Oh("产品不存在或已失效");
+ }
+
+ // 检查库存数量是否足够
+ if (product.Quantity < input.UsageQuantity)
+ {
+ throw NCCException.Oh($"库存不足,当前库存:{product.Quantity},需要数量:{input.UsageQuantity}");
+ }
+
+ _db.Ado.BeginTran();
+
+ // 创建使用记录
+ var usageEntity = new LqInventoryUsageEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ ProductId = input.ProductId,
+ StoreId = input.StoreId,
+ UsageTime = input.UsageTime,
+ UsageQuantity = input.UsageQuantity,
+ RelatedConsumeId = input.RelatedConsumeId,
+ CreateUser = _userManager.UserId,
+ CreateTime = DateTime.Now,
+ IsEffective = StatusEnum.有效.GetHashCode()
+ };
+
+ var isOk = await _db.Insertable(usageEntity).ExecuteCommandAsync();
+ if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000);
+
+ // 更新库存数量
+ product.Quantity -= input.UsageQuantity;
+ product.UpdateUser = _userManager.UserId;
+ product.UpdateTime = DateTime.Now;
+ var updateOk = await _db.Updateable(product).ExecuteCommandAsync();
+ if (!(updateOk > 0)) throw NCCException.Oh(ErrorCode.COM1001);
+ _db.Ado.CommitTran();
+ }
+ catch (Exception ex)
+ {
+ _db.Ado.RollbackTran();
+ _logger.LogError(ex, "添加库存使用记录失败");
+ throw NCCException.Oh($"添加失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 作废库存使用记录
+ ///
+ /// 作废库存使用记录
+ ///
+ /// 使用记录ID
+ /// 作废备注
+ /// 作废结果
+ [HttpPut("Cancel")]
+ public async Task CancelAsync([FromQuery] string id, [FromQuery] string remarks = null)
+ {
+ try
+ {
+ if (string.IsNullOrWhiteSpace(id))
+ {
+ throw NCCException.Oh("使用记录ID不能为空");
+ }
+
+ // 检查使用记录是否存在
+ var usageRecord = await _db.Queryable().Where(x => x.Id == id && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
+
+ if (usageRecord == null)
+ {
+ throw NCCException.Oh("使用记录不存在或已失效");
+ }
+
+ _db.Ado.BeginTran();
+
+ // 作废使用记录
+ usageRecord.IsEffective = StatusEnum.无效.GetHashCode();
+ usageRecord.UpdateUser = _userManager.UserId;
+ usageRecord.UpdateTime = DateTime.Now;
+
+ var isOk = await _db.Updateable(usageRecord).ExecuteCommandAsync();
+ if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1003);
+ // 恢复库存数量
+ var product = await _db.Queryable().Where(x => x.Id == usageRecord.ProductId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
+ if (product != null)
+ {
+ product.Quantity += usageRecord.UsageQuantity;
+ product.UpdateUser = _userManager.UserId;
+ product.UpdateTime = DateTime.Now;
+ var updateOk = await _db.Updateable(product).ExecuteCommandAsync();
+ if (!(updateOk > 0)) throw NCCException.Oh(ErrorCode.COM1001);
+ }
+
+ _db.Ado.CommitTran();
+ }
+ catch (Exception ex)
+ {
+ _db.Ado.RollbackTran();
+ _logger.LogError(ex, "作废库存使用记录失败");
+ throw NCCException.Oh($"作废失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 获取使用记录列表
+ ///
+ /// 获取使用记录列表
+ ///
+ /// 查询输入
+ /// 使用记录列表
+ [HttpGet("GetList")]
+ public async Task GetListAsync([FromQuery] LqInventoryUsageListQueryInput input)
+ {
+ try
+ {
+ var sidx = input.sidx == null ? "id" : input.sidx;
+
+ // 查询使用记录信息
+ var data = await _db.Queryable()
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ProductId), x => x.ProductId == input.ProductId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), x => x.StoreId == input.StoreId)
+ .WhereIF(input.UsageStartTime.HasValue, x => x.UsageTime >= input.UsageStartTime.Value)
+ .WhereIF(input.UsageEndTime.HasValue, x => x.UsageTime <= input.UsageEndTime.Value)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.RelatedConsumeId), x => x.RelatedConsumeId == input.RelatedConsumeId)
+ .WhereIF(input.IsEffective.HasValue, x => x.IsEffective == input.IsEffective.Value)
+ .Select(x => new LqInventoryUsageListOutput
+ {
+ Id = x.Id,
+ ProductId = x.ProductId,
+ ProductName = "",
+ ProductCategory = "",
+ ProductPrice = 0,
+ StoreId = x.StoreId,
+ StoreName = "",
+ UsageTime = x.UsageTime,
+ UsageQuantity = x.UsageQuantity,
+ RelatedConsumeId = x.RelatedConsumeId,
+ CreateUser = x.CreateUser,
+ CreateUserName = "",
+ CreateTime = x.CreateTime,
+ UpdateUser = x.UpdateUser,
+ UpdateUserName = "",
+ UpdateTime = x.UpdateTime,
+ IsEffective = x.IsEffective
+ })
+ .MergeTable()
+ .OrderBy(sidx + " " + input.sort)
+ .ToPagedListAsync(input.currentPage, input.pageSize);
+
+ // 补充产品信息和用户信息
+ foreach (var item in data.list)
+ {
+ if (!string.IsNullOrEmpty(item.ProductId))
+ {
+ var product = await _db.Queryable().Where(p => p.Id == item.ProductId).FirstAsync();
+ if (product != null)
+ {
+ item.ProductName = product.ProductName;
+ item.ProductCategory = product.ProductCategory;
+ item.ProductPrice = product.Price;
+ }
+ }
+ if (!string.IsNullOrEmpty(item.StoreId))
+ {
+ var store = await _db.Queryable().Where(u => u.Id == item.StoreId).FirstAsync();
+ item.StoreName = store?.RealName ?? "";
+ }
+ if (!string.IsNullOrEmpty(item.CreateUser))
+ {
+ var createUser = await _db.Queryable().Where(u => u.Id == item.CreateUser).FirstAsync();
+ item.CreateUserName = createUser?.RealName ?? "";
+ }
+ if (!string.IsNullOrEmpty(item.UpdateUser))
+ {
+ var updateUser = await _db.Queryable().Where(u => u.Id == item.UpdateUser).FirstAsync();
+ item.UpdateUserName = updateUser?.RealName ?? "";
+ }
+ }
+
+ // 应用产品名称和分类的过滤条件
+ if (!string.IsNullOrWhiteSpace(input.ProductName) || !string.IsNullOrWhiteSpace(input.ProductCategory))
+ {
+ data.list = data.list.Where(x =>
+ (string.IsNullOrWhiteSpace(input.ProductName) || x.ProductName.Contains(input.ProductName)) &&
+ (string.IsNullOrWhiteSpace(input.ProductCategory) || x.ProductCategory.Contains(input.ProductCategory))
+ ).ToList();
+ }
+
+ // 应用门店名称的过滤条件
+ if (!string.IsNullOrWhiteSpace(input.StoreName))
+ {
+ data.list = data.list.Where(x => x.StoreName.Contains(input.StoreName)).ToList();
+ }
+ return PageResult.SqlSugarPageResult(data);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取使用记录列表失败");
+ throw NCCException.Oh($"获取使用记录列表失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 统计时间周期内每个产品的使用数量
+ ///
+ /// 统计时间周期内每个产品的使用数量
+ ///
+ /// 统计查询输入
+ /// 产品使用统计
+ [HttpPost("GetProductUsageStatistics")]
+ public async Task GetProductUsageStatisticsAsync([FromBody] LqInventoryUsageStatisticsInput input)
+ {
+ try
+ {
+ var data = await _db.Queryable()
+ .LeftJoin((usage, product) => usage.ProductId == product.Id)
+ .Where((usage, product) => usage.UsageTime >= input.StartTime && usage.UsageTime <= input.EndTime)
+ .Where((usage, product) => usage.IsEffective == StatusEnum.有效.GetHashCode())
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ProductId), (usage, product) => usage.ProductId == input.ProductId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), (usage, product) => usage.StoreId == input.StoreId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ProductCategory), (usage, product) => product.ProductCategory == input.ProductCategory)
+ .GroupBy((usage, product) => new { usage.ProductId, product.ProductName, product.ProductCategory, product.Price })
+ .Select((usage, product) => new ProductUsageStatisticsOutput
+ {
+ ProductId = usage.ProductId,
+ ProductName = product.ProductName,
+ ProductCategory = product.ProductCategory,
+ ProductPrice = product.Price,
+ TotalUsageQuantity = SqlFunc.AggregateSum(usage.UsageQuantity),
+ TotalUsageAmount = SqlFunc.AggregateSum(usage.UsageQuantity * product.Price),
+ UsageCount = SqlFunc.AggregateCount(usage.Id),
+ AverageUsageQuantity = SqlFunc.AggregateAvg(usage.UsageQuantity)
+ })
+ .ToListAsync();
+
+ return new
+ {
+ success = true,
+ data = data,
+ total = data.Count,
+ message = "产品使用统计查询成功"
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取产品使用统计失败");
+ throw NCCException.Oh($"获取产品使用统计失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 统计时间周期内每个门店的使用情况
+ ///
+ /// 统计时间周期内每个门店的使用情况
+ ///
+ /// 统计查询输入
+ /// 门店使用统计
+ [HttpPost("GetStoreUsageStatistics")]
+ public async Task GetStoreUsageStatisticsAsync([FromBody] LqInventoryUsageStatisticsInput input)
+ {
+ try
+ {
+ var data = await _db.Queryable()
+ .LeftJoin((usage, product) => usage.ProductId == product.Id)
+ .LeftJoin((usage, product, store) => usage.StoreId == store.Id)
+ .Where((usage, product, store) => usage.UsageTime >= input.StartTime && usage.UsageTime <= input.EndTime)
+ .Where((usage, product, store) => usage.IsEffective == StatusEnum.有效.GetHashCode())
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ProductId), (usage, product, store) => usage.ProductId == input.ProductId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), (usage, product, store) => usage.StoreId == input.StoreId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ProductCategory), (usage, product, store) => product.ProductCategory == input.ProductCategory)
+ .GroupBy((usage, product, store) => new { usage.StoreId, store.RealName })
+ .Select((usage, product, store) => new StoreUsageStatisticsOutput
+ {
+ StoreId = usage.StoreId,
+ StoreName = store.RealName,
+ TotalUsageQuantity = SqlFunc.AggregateSum(usage.UsageQuantity),
+ TotalUsageAmount = SqlFunc.AggregateSum(usage.UsageQuantity * product.Price),
+ UsageCount = SqlFunc.AggregateCount(usage.Id),
+ ProductVarietyCount = SqlFunc.AggregateCount(usage.ProductId)
+ })
+ .ToListAsync();
+
+ return new
+ {
+ success = true,
+ data = data,
+ total = data.Count,
+ message = "门店使用统计查询成功"
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取门店使用统计失败");
+ throw NCCException.Oh($"获取门店使用统计失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 统计时间周期内使用趋势
+ ///
+ /// 统计时间周期内使用趋势
+ ///
+ /// 统计查询输入
+ /// 使用趋势统计
+ [HttpPost("GetUsageTrendStatistics")]
+ public async Task GetUsageTrendStatisticsAsync([FromBody] LqInventoryUsageStatisticsInput input)
+ {
+ try
+ {
+ // 先获取基础数据
+ var baseData = await _db.Queryable()
+ .LeftJoin((usage, product) => usage.ProductId == product.Id)
+ .Where((usage, product) => usage.UsageTime >= input.StartTime && usage.UsageTime <= input.EndTime)
+ .Where((usage, product) => usage.IsEffective == StatusEnum.有效.GetHashCode())
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ProductId), (usage, product) => usage.ProductId == input.ProductId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), (usage, product) => usage.StoreId == input.StoreId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ProductCategory), (usage, product) => product.ProductCategory == input.ProductCategory)
+ .Select((usage, product) => new
+ {
+ UsageTime = usage.UsageTime,
+ UsageQuantity = usage.UsageQuantity,
+ UsageAmount = usage.UsageQuantity * product.Price,
+ ProductId = usage.ProductId
+ })
+ .ToListAsync();
+
+ // 根据统计类型分组
+ var groupedData = input.StatisticsType switch
+ {
+ "日" => baseData.GroupBy(x => x.UsageTime.Date)
+ .Select(g => new UsageTrendStatisticsOutput
+ {
+ StatisticsDate = g.Key,
+ TotalUsageQuantity = g.Sum(x => x.UsageQuantity),
+ TotalUsageAmount = g.Sum(x => x.UsageAmount),
+ UsageCount = g.Count(),
+ ProductVarietyCount = g.Select(x => x.ProductId).Distinct().Count()
+ })
+ .OrderBy(x => x.StatisticsDate)
+ .ToList(),
+ "月" => baseData.GroupBy(x => new { x.UsageTime.Year, x.UsageTime.Month })
+ .Select(g => new UsageTrendStatisticsOutput
+ {
+ StatisticsDate = new DateTime(g.Key.Year, g.Key.Month, 1),
+ TotalUsageQuantity = g.Sum(x => x.UsageQuantity),
+ TotalUsageAmount = g.Sum(x => x.UsageAmount),
+ UsageCount = g.Count(),
+ ProductVarietyCount = g.Select(x => x.ProductId).Distinct().Count()
+ })
+ .OrderBy(x => x.StatisticsDate)
+ .ToList(),
+ _ => baseData.GroupBy(x => x.UsageTime.Date)
+ .Select(g => new UsageTrendStatisticsOutput
+ {
+ StatisticsDate = g.Key,
+ TotalUsageQuantity = g.Sum(x => x.UsageQuantity),
+ TotalUsageAmount = g.Sum(x => x.UsageAmount),
+ UsageCount = g.Count(),
+ ProductVarietyCount = g.Select(x => x.ProductId).Distinct().Count()
+ })
+ .OrderBy(x => x.StatisticsDate)
+ .ToList()
+ };
+
+ return new
+ {
+ success = true,
+ data = groupedData,
+ total = groupedData.Count,
+ message = "使用趋势统计查询成功"
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取使用趋势统计失败");
+ throw NCCException.Oh($"获取使用趋势统计失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 统计产品使用排行榜
+ ///
+ /// 统计产品使用排行榜
+ ///
+ /// 统计查询输入
+ /// 产品使用排行榜
+ [HttpPost("GetProductUsageRanking")]
+ public async Task GetProductUsageRankingAsync([FromBody] LqInventoryUsageStatisticsInput input)
+ {
+ try
+ {
+ var data = await _db.Queryable()
+ .LeftJoin((usage, product) => usage.ProductId == product.Id)
+ .Where((usage, product) => usage.UsageTime >= input.StartTime && usage.UsageTime <= input.EndTime)
+ .Where((usage, product) => usage.IsEffective == StatusEnum.有效.GetHashCode())
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ProductId), (usage, product) => usage.ProductId == input.ProductId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), (usage, product) => usage.StoreId == input.StoreId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ProductCategory), (usage, product) => product.ProductCategory == input.ProductCategory)
+ .GroupBy((usage, product) => new { usage.ProductId, product.ProductName, product.ProductCategory })
+ .Select((usage, product) => new ProductUsageRankingOutput
+ {
+ ProductId = usage.ProductId,
+ ProductName = product.ProductName,
+ ProductCategory = product.ProductCategory,
+ TotalUsageQuantity = SqlFunc.AggregateSum(usage.UsageQuantity),
+ TotalUsageAmount = SqlFunc.AggregateSum(usage.UsageQuantity * product.Price),
+ UsageCount = SqlFunc.AggregateCount(usage.Id),
+ StoreCount = SqlFunc.AggregateCount(usage.StoreId)
+ })
+ .OrderBy("TotalUsageQuantity desc")
+ .Take(input.RankingCount)
+ .ToListAsync();
+
+ // 添加排名
+ for (int i = 0; i < data.Count; i++)
+ {
+ data[i].Ranking = i + 1;
+ }
+
+ return new
+ {
+ success = true,
+ data = data,
+ total = data.Count,
+ message = "产品使用排行榜查询成功"
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取产品使用排行榜失败");
+ throw NCCException.Oh($"获取产品使用排行榜失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
index 9504739..869a939 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
@@ -5,6 +5,7 @@ using System.Net.Http;
using System.Threading.Tasks;
using Mapster;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
using NCC.ClayObject;
using NCC.Common.Configuration;
using NCC.Common.Core.Manager;
@@ -22,6 +23,8 @@ using NCC.Extend.Entitys.Dto.LqKdKdjlb;
using NCC.Extend.Entitys.Enum;
using NCC.Extend.Entitys.lq_hytk_hytk;
using NCC.Extend.Entitys.lq_hytk_mx;
+using NCC.Extend.Entitys.lq_hytk_jksyj;
+using NCC.Extend.Entitys.lq_hytk_kjbsyj;
using NCC.Extend.Entitys.lq_jinsanjiao_user;
using NCC.Extend.Entitys.lq_kd_deductinfo;
using NCC.Extend.Entitys.lq_xh_hyhk;
@@ -40,6 +43,8 @@ using NCC.System.Entitys.Permission;
using SqlSugar;
using Yitter.IdGenerator;
using NCC.Extend.Entitys.lq_package_info;
+using NCC.Extend.Entitys.lq_mdxx;
+using NCC.Extend.Entitys.lq_card_transfer_log;
namespace NCC.Extend.LqKdKdjlb
{
@@ -58,6 +63,7 @@ namespace NCC.Extend.LqKdKdjlb
private readonly IUserManager _userManager;
private readonly WeChatBotService _weChatBotService;
private readonly LqKdKdjlbStringGenerator _stringGenerator;
+ private readonly ILogger _logger;
///
/// 初始化一个类型的新实例
@@ -69,7 +75,8 @@ namespace NCC.Extend.LqKdKdjlb
ISqlSugarRepository lqKdPxmxRepository,
IUserManager userManager,
WeChatBotService weChatBotService,
- LqKdKdjlbStringGenerator stringGenerator
+ LqKdKdjlbStringGenerator stringGenerator,
+ ILogger logger
)
{
_lqKdKdjlbRepository = lqKdKdjlbRepository;
@@ -80,6 +87,7 @@ namespace NCC.Extend.LqKdKdjlb
_userManager = userManager;
_weChatBotService = weChatBotService;
_stringGenerator = stringGenerator;
+ _logger = logger;
}
#region 获取开单记录表
@@ -210,9 +218,9 @@ namespace NCC.Extend.LqKdKdjlb
.WhereIF(queryKdrq != null, p => p.Kdrq <= new DateTime(endKdrq.ToDate().Year, endKdrq.ToDate().Month, endKdrq.ToDate().Day, 23, 59, 59))
.WhereIF(!string.IsNullOrEmpty(input.gjlx), p => p.Gjlx.Equals(input.gjlx))
.WhereIF(!string.IsNullOrEmpty(input.hgjg), p => p.Hgjg.Equals(input.hgjg))
- .WhereIF(!string.IsNullOrEmpty(input.zdyj), p => p.Zdyj.Equals(input.zdyj))
- .WhereIF(!string.IsNullOrEmpty(input.sfyj), p => p.Sfyj.Equals(input.sfyj))
- .WhereIF(!string.IsNullOrEmpty(input.qk), p => p.Qk.Equals(input.qk))
+ .WhereIF(input.zdyj != null, p => p.Zdyj > input.zdyj)
+ .WhereIF(input.sfyj != null, p => p.Sfyj > input.sfyj)
+ .WhereIF(input.qk != null, p => p.Qk > input.qk)
.WhereIF(!string.IsNullOrEmpty(input.ckfs), p => p.Ckfs.Equals(input.ckfs))
.WhereIF(!string.IsNullOrEmpty(input.fkfs), p => p.Fkfs.Equals(input.fkfs))
.WhereIF(!string.IsNullOrEmpty(input.fkyy), p => p.Fkyy.Equals(input.fkyy))
@@ -227,6 +235,7 @@ namespace NCC.Extend.LqKdKdjlb
.WhereIF(!string.IsNullOrEmpty(input.kdhysjh), p => p.Kdhysjh.Contains(input.kdhysjh))
.WhereIF(!string.IsNullOrEmpty(input.F_FIleUrl), p => p.F_FIleUrl.Contains(input.F_FIleUrl))
.WhereIF(!string.IsNullOrEmpty(input.CreateUser), p => p.CreateUser.Equals(input.CreateUser))
+ .WhereIF(input.isEffective != 0, p => p.IsEffective == input.isEffective)
.Select(it => new LqKdKdjlbListOutput
{
id = it.Id,
@@ -775,9 +784,9 @@ namespace NCC.Extend.LqKdKdjlb
.WhereIF(queryKdrq != null, p => p.Kdrq <= new DateTime(endKdrq.ToDate().Year, endKdrq.ToDate().Month, endKdrq.ToDate().Day, 23, 59, 59))
.WhereIF(!string.IsNullOrEmpty(input.gjlx), p => p.Gjlx.Equals(input.gjlx))
.WhereIF(!string.IsNullOrEmpty(input.hgjg), p => p.Hgjg.Equals(input.hgjg))
- .WhereIF(!string.IsNullOrEmpty(input.zdyj), p => p.Zdyj.Equals(input.zdyj))
- .WhereIF(!string.IsNullOrEmpty(input.sfyj), p => p.Sfyj.Equals(input.sfyj))
- .WhereIF(!string.IsNullOrEmpty(input.qk), p => p.Qk.Equals(input.qk))
+ .WhereIF(input.zdyj != null, p => p.Zdyj > input.zdyj)
+ .WhereIF(input.sfyj != null, p => p.Sfyj > input.sfyj)
+ .WhereIF(input.qk != null, p => p.Qk > input.qk)
.WhereIF(!string.IsNullOrEmpty(input.ckfs), p => p.Ckfs.Equals(input.ckfs))
.WhereIF(!string.IsNullOrEmpty(input.fkfs), p => p.Fkfs.Equals(input.fkfs))
.WhereIF(!string.IsNullOrEmpty(input.fkyy), p => p.Fkyy.Equals(input.fkyy))
@@ -791,6 +800,7 @@ namespace NCC.Extend.LqKdKdjlb
.WhereIF(!string.IsNullOrEmpty(input.kdhyc), p => p.Kdhyc.Contains(input.kdhyc))
.WhereIF(!string.IsNullOrEmpty(input.kdhysjh), p => p.Kdhysjh.Contains(input.kdhysjh))
.WhereIF(!string.IsNullOrEmpty(input.F_FIleUrl), p => p.F_FIleUrl.Contains(input.F_FIleUrl))
+ .WhereIF(input.isEffective != 0, p => p.IsEffective == input.isEffective)
.Select(it => new LqKdKdjlbListOutput
{
id = it.Id,
@@ -2310,6 +2320,396 @@ namespace NCC.Extend.LqKdKdjlb
}
#endregion
+ #region 会员转卡操作
+ ///
+ /// 会员转卡操作
+ ///
+ ///
+ /// 转卡是指一个会员把自己剩余的某些品项,转给另外一个会员
+ /// 转卡会员转出的品项,就做退卡操作
+ /// 被转卡会员收到的品项,做开卡操作
+ /// 系统会自动从原开单记录中获取健康师和科技部老师的业绩数据
+ ///
+ /// 示例请求:
+ /// ```json
+ /// {
+ /// "fromMemberId": "member001",
+ /// "toMemberId": "member002",
+ /// "storeId": "store001",
+ /// "signatureFile": "base64签名数据",
+ /// "remarks": "转卡备注信息",
+ /// "transferItems": [
+ /// {
+ /// "billingItemId": "pxmx001",
+ /// "transferQuantity": 5,
+ /// "itemName": "美容项目A",
+ /// "itemPrice": 100.00
+ /// }
+ /// ]
+ /// }
+ /// ```
+ ///
+ /// 参数说明:
+ /// - fromMemberId: 转出会员ID(必填)
+ /// - toMemberId: 转入会员ID(必填)
+ /// - storeId: 门店ID(必填)
+ /// - signatureFile: 转出会员签名文件(必填)
+ /// - remarks: 转卡备注信息(可选)
+ /// - transferItems: 转出品项列表(必填)
+ /// - billingItemId: 开单品项明细ID(必填)
+ /// - transferQuantity: 转出数量(必填,大于0)
+ /// - itemName: 品项名称(必填)
+ /// - itemPrice: 品项价格(必填,大于等于0)
+ ///
+ /// 业务规则:
+ /// - 转出和转入会员必须存在且有效
+ /// - 转出品项的剩余数量必须足够
+ /// - 系统会自动从原开单记录中获取健康师和科技部老师业绩数据
+ /// - 转卡操作会同时创建退卡记录和开卡记录
+ /// - 所有操作在事务中执行,确保数据一致性
+ ///
+ /// 转卡输入参数
+ /// 转卡结果
+ /// 转卡成功
+ /// 参数错误或业务规则验证失败
+ /// 服务器错误
+ [HttpPost("TransferCard")]
+ public async Task TransferCard([FromBody] TransferCardInput input)
+ {
+ if (input == null)
+ {
+ throw NCCException.Oh("转卡参数不能为空");
+ }
+ var userInfo = await _userManager.GetUserInfo();
+ var transferTime = DateTime.Now;
+ try
+ {
+ // 开启事务
+ _db.BeginTran();
+ // 1. 验证转出和转入会员是否存在
+ var fromMember = await _db.Queryable().Where(x => x.Id == input.FromMemberId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
+ if (fromMember == null)
+ {
+ throw NCCException.Oh("转出会员不存在或已失效");
+ }
+ var toMember = await _db.Queryable().Where(x => x.Id == input.ToMemberId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
+ if (toMember == null)
+ {
+ throw NCCException.Oh("转入会员不存在或已失效");
+ }
+ // 2. 验证转出品项的余额是否足够
+ foreach (var item in input.TransferItems)
+ {
+ var billingItem = await _db.Queryable().Where(x => x.Id == item.BillingItemId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
+ if (billingItem == null)
+ {
+ throw NCCException.Oh($"品项明细不存在:{item.ItemName}");
+ }
+ // 查询剩余数量
+ var remainingCount = await GetItemRemainingCount(item.BillingItemId);
+ if (remainingCount < item.TransferQuantity)
+ {
+ throw NCCException.Oh($"品项 {item.ItemName} 剩余数量不足,当前剩余:{remainingCount},需要转出:{item.TransferQuantity}");
+ }
+ }
+
+ // 3. 创建退卡记录(转出方)
+ var refundId = YitIdHelper.NextId().ToString();
+ var totalRefundAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity);
+ var StoreEntity = await _db.Queryable().Where(p => p.Id == input.StoreId).FirstAsync();
+ var refundEntity = new LqHytkHytkEntity
+ {
+ Id = refundId,
+ F_CreateTime = transferTime,
+ F_CreateUser = userInfo.userId,
+ IsEffective = StatusEnum.有效.GetHashCode(),
+ Czry = userInfo.userId,
+ Hy = input.FromMemberId,
+ Hymc = fromMember.Khmc,
+ Md = input.StoreId,
+ Mdmc = StoreEntity.Dm,
+ Mdbh = StoreEntity.Mdbm,
+ SignatureFile = input.SignatureFile,
+ Hyzh = input.FromMemberId,
+ Gklx = fromMember.Khlx,
+ Tksj = DateTime.Now,
+ Tkje = totalRefundAmount,
+ ActualRefundAmount = totalRefundAmount, // 转卡时实退金额等于退卡总金额
+ Tkyy = "转卡",
+ Bz = $"转卡给会员:{toMember.Khmc},{input.Remarks}"
+ };
+ await _db.Insertable(refundEntity).ExecuteCommandAsync();
+
+ // 4. 创建退卡品项明细和业绩记录
+ var refundMxEntities = new List();
+ var refundJksyjEntities = new List();
+
+ var refundKjbsyjEntities = new List();
+
+ foreach (var item in input.TransferItems)
+ {
+ var refundPxmxEntity = await _db.Queryable().Where(p => p.Id == item.BillingItemId).FirstAsync();
+ //计算品项扣除总金额
+ var totalItemDeduction = item.ItemPrice * item.TransferQuantity;
+ //保存退卡明细表
+ var refundMxEntity = new LqHytkMxEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ RefundInfoId = refundId,
+ BillingItemId = item.BillingItemId,
+ CreateTime = transferTime,
+ CreateUser = userInfo.userId,
+ Px = refundPxmxEntity.Px,
+ Pxmc = item.ItemName,
+ Pxjg = item.ItemPrice,
+ Tkje = totalItemDeduction,
+ ProjectNumber = item.TransferQuantity,
+ SourceType = refundPxmxEntity.SourceType,
+ TotalPrice = totalItemDeduction,
+ IsEffective = StatusEnum.有效.GetHashCode()
+ };
+ refundMxEntities.Add(refundMxEntity);
+ var refundKdyjEntities = _db.Queryable().Where(p => p.Kdpxid == item.BillingItemId).ToList();
+ //保存退卡健康师业绩表
+ foreach (var jks in refundKdyjEntities)
+ {
+ //获取健康师当月金三角id
+ var monthString = DateTime.Now.ToString("yyyyMM");
+ var GetMonTeamResult = await _db.Queryable().Where(p => p.UserId == jks.Jkszh && p.Month == monthString).ToListAsync();
+ var GetMonTeam = GetMonTeamResult.FirstOrDefault();
+ if (GetMonTeam == null)
+ {
+ throw NCCException.Oh($"健康师 {jks.Jksxm} 在 {monthString} 月份的金三角团队中不存在,请先配置金三角团队信息");
+ }
+ //获取本月
+ refundJksyjEntities.Add(new LqHytkJksyjEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ Gltkbh = refundId,
+ Jks = jks.Jks,
+ Jksxm = jks.Jksxm,
+ Jkszh = jks.Jkszh,
+ Jksyj = (totalItemDeduction / refundKdyjEntities.Count()),
+ Tksj = DateTime.Now,
+ F_jsjid = GetMonTeam.JsjId,
+ F_tkpxid = refundMxEntity.Id,
+ F_tkpxNumber = item.TransferQuantity,
+ F_CreateTime = transferTime,
+ F_CreateUser = userInfo.userId,
+ CardReturn = refundMxEntity.Id,
+ IsEffective = StatusEnum.有效.GetHashCode()
+ });
+ }
+ //查询科技部老师的业绩
+ var TechTeacherEntities = _db.Queryable().Where(p => p.Kdpxid == item.BillingItemId).ToList();
+ // 创建退卡科技部老师业绩记录
+ foreach (var kjbs in TechTeacherEntities)
+ {
+ refundKjbsyjEntities.Add(new LqHytkKjbsyjEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ Gltkbh = refundId,
+ Kjbls = kjbs.Kjbls,
+ Kjblsxm = kjbs.Kjblsxm,
+ Kjblszh = kjbs.Kjblszh,
+ Kjblsyj = (totalItemDeduction / TechTeacherEntities.Count()),
+ Tksj = transferTime,
+ F_tkpxid = refundMxEntity.Id,
+ F_LaborCost = kjbs.LaborCost,
+ F_tkpxNumber = item.TransferQuantity,
+ F_CreateTime = transferTime,
+ F_CreateUser = userInfo.userId,
+ CardReturn = refundMxEntity.Id,
+ IsEffective = StatusEnum.有效.GetHashCode()
+ });
+ }
+ }
+
+ await _db.Insertable(refundMxEntities).ExecuteCommandAsync();
+ if (refundJksyjEntities.Any())
+ {
+ await _db.Insertable(refundJksyjEntities).ExecuteCommandAsync();
+ }
+ if (refundKjbsyjEntities.Any())
+ {
+ await _db.Insertable(refundKjbsyjEntities).ExecuteCommandAsync();
+ }
+
+ // 5. 创建开卡记录(转入方)
+ var billingId = YitIdHelper.NextId().ToString();
+ var billingEntity = new LqKdKdjlbEntity
+ {
+ Id = billingId,
+ CreateTime = transferTime,
+ UpdateTime = transferTime,
+ IsEffective = StatusEnum.有效.GetHashCode(),
+ CreateUser = userInfo.userId,
+ Kdhy = input.ToMemberId,
+ Djmd = input.StoreId,
+ Kdrq = DateTime.Now,
+ Gjlx = toMember.Khlx,
+ Fkfs = "转卡",
+ Sfskdd = "否",
+ Zdyj = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity),
+ Sfyj = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity),
+ Bz = $"从会员 {fromMember.Khmc} 转入,{input.Remarks}"
+ };
+ await _db.Insertable(billingEntity).ExecuteCommandAsync();
+ // 6. 创建开单品项明细和业绩记录
+ var billingPxmxEntities = new List();
+ var billingJksyjEntities = new List();
+ var billingKjbsyjEntities = new List();
+
+ foreach (var item in input.TransferItems)
+ {
+ var refundPxmxEntity = await _db.Queryable().Where(p => p.Id == item.BillingItemId).FirstAsync();
+ var billingPxmxEntity = new LqKdPxmxEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ Glkdbh = billingId,
+ Px = refundPxmxEntity.Px,
+ Pxmc = item.ItemName,
+ Pxjg = item.ItemPrice,
+ MemberId = input.ToMemberId,
+ CreateTIme = transferTime,
+ ProjectNumber = item.TransferQuantity,
+ IsEnabled = StatusEnum.有效.GetHashCode(),
+ SourceType = refundPxmxEntity.SourceType,
+ TotalPrice = item.ItemPrice * item.TransferQuantity,
+ ActualPrice = item.ItemPrice * item.TransferQuantity,
+ IsEffective = StatusEnum.有效.GetHashCode(),
+ Remark = $"从会员 {fromMember.Khmc} 转入"
+ };
+ billingPxmxEntities.Add(billingPxmxEntity);
+
+ foreach (var jks in refundJksyjEntities)
+ {
+ billingJksyjEntities.Add(new LqKdJksyjEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ Glkdbh = billingId,
+ Jks = jks.Jks,
+ Jksxm = jks.Jksxm,
+ Jkszh = jks.Jkszh,
+ Jksyj = jks.Jksyj.ToString(),
+ Yjsj = transferTime,
+ Jsj_id = jks.F_jsjid,
+ Kdpxid = billingPxmxEntity.Id,
+ IsEffective = StatusEnum.有效.GetHashCode()
+ });
+ }
+
+ foreach (var kjbs in refundKjbsyjEntities)
+ {
+ billingKjbsyjEntities.Add(new LqKdKjbsyjEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ Glkdbh = billingId,
+ Kjbls = kjbs.Kjbls,
+ Kjblsxm = kjbs.Kjblsxm,
+ Kjblszh = kjbs.Kjblszh,
+ Kjblsyj = kjbs.Kjblsyj.ToString(),
+ Yjsj = transferTime,
+ Kdpxid = billingPxmxEntity.Id,
+ IsEffective = StatusEnum.有效.GetHashCode()
+ });
+ }
+ }
+ //记录转卡日志
+ var transferLogEntity = new LqCardTransferLogEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ RefundCardId = refundId,
+ BillingCardId = billingId,
+ TransferFromMemberId = input.FromMemberId,
+ TransferToMemberId = input.ToMemberId,
+ TransferAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity),
+ TransferTime = transferTime,
+ OperatorId = userInfo.userId,
+ Remarks = input.Remarks,
+ CreateTime = DateTime.Now,
+ IsEffective = StatusEnum.有效.GetHashCode()
+
+ };
+ await _db.Insertable(transferLogEntity).ExecuteCommandAsync();
+
+ await _db.Insertable(billingPxmxEntities).ExecuteCommandAsync();
+ if (billingJksyjEntities.Any())
+ {
+ await _db.Insertable(billingJksyjEntities).ExecuteCommandAsync();
+ }
+ if (billingKjbsyjEntities.Any())
+ {
+ await _db.Insertable(billingKjbsyjEntities).ExecuteCommandAsync();
+ }
+ // 提交事务
+ _db.CommitTran();
+
+ return new TransferCardOutput
+ {
+ Success = true,
+ TransferId = refundId,
+ RefundId = refundId,
+ BillingId = billingId,
+ TotalAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity),
+ TotalQuantity = input.TransferItems.Sum(x => x.TransferQuantity),
+ FromMemberName = fromMember.Khmc,
+ ToMemberName = toMember.Khmc,
+ TransferTime = transferTime,
+ Message = "转卡操作成功"
+ };
+ }
+ catch (Exception ex)
+ {
+ _db.RollbackTran();
+ _logger.LogError(ex, "转卡操作失败:{Message}", ex.Message);
+ throw NCCException.Oh($"转卡操作失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 获取品项剩余数量
+ ///
+ /// 获取品项剩余数量
+ ///
+ /// 开单品项明细ID
+ /// 剩余数量
+ private async Task GetItemRemainingCount(string billingItemId)
+ {
+ try
+ {
+ // 查询购买数量
+ var purchasedCount = await _db.Queryable()
+ .Where(x => x.Id == billingItemId && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .SumAsync(x => x.ProjectNumber);
+
+ // 查询消费数量
+ var consumedCount = await _db.Queryable()
+ .Where(x => x.BillingItemId == billingItemId && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .SumAsync(x => x.ProjectNumber);
+
+ // 查询退卡数量
+ var refundedCount = await _db.Queryable()
+ .Where(x => x.BillingItemId == billingItemId && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .SumAsync(x => x.ProjectNumber);
+
+ // 查询储扣数量
+ var deductCount = await _db.Queryable()
+ .Where(x => x.DeductId == billingItemId && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .SumAsync(x => x.ProjectNumber) ?? 0;
+
+ // 计算剩余数量
+ var remainingCount = (int)(purchasedCount - consumedCount - refundedCount - deductCount);
+ return Math.Max(0, remainingCount); // 确保不为负数
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取品项剩余数量失败,品项ID:{BillingItemId}", billingItemId);
+ throw NCCException.Oh($"获取品项剩余数量失败:{ex.Message}");
+ }
+ }
+ #endregion
+
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
index 26e3daf..92e2070 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
@@ -2472,7 +2472,7 @@ namespace NCC.Extend.LqStatistics
/// 保存门店总业绩统计数据
///
///
- /// 统计门店的总业绩、欠款金额、总单业绩、储扣总金额、品项数量、首开单数量、升单数量
+ /// 统计门店的总业绩、欠款金额、总单业绩、储扣总金额、品项数量、首开单数量、升单数量、退款业绩、退款次数
///
/// 示例请求:
/// ```json
@@ -2483,6 +2483,17 @@ namespace NCC.Extend.LqStatistics
///
/// 参数说明:
/// - statisticsMonth: 统计月份,格式为YYYYMM
+ ///
+ /// 统计指标:
+ /// - 总业绩: 开单记录的总业绩金额
+ /// - 欠款金额: 开单记录的欠款总额
+ /// - 总单业绩: 开单记录的实付业绩
+ /// - 储扣总金额: 储扣记录的金额总和
+ /// - 品项数量: 开单品项的总数量
+ /// - 首开单数量: 首次开单的数量
+ /// - 升单数量: 升单的数量
+ /// - 退款业绩: 退款记录的总金额
+ /// - 退款次数: 退款记录的总次数
///
/// 统计输入参数
/// 保存结果
@@ -2515,7 +2526,9 @@ namespace NCC.Extend.LqStatistics
store_data.F_FirstOrderCount,
store_data.F_UpgradeOrderCount,
store_data.F_FirstOrderPerformance,
- store_data.F_UpgradeOrderPerformance
+ store_data.F_UpgradeOrderPerformance,
+ COALESCE(refund_data.F_RefundAmount, 0) as F_RefundAmount,
+ COALESCE(refund_data.F_RefundCount, 0) as F_RefundCount
FROM (
SELECT
kd.djmd as F_StoreId,
@@ -2544,7 +2557,17 @@ namespace NCC.Extend.LqStatistics
WHERE kd.F_IsEffective = 1
AND DATE_FORMAT(kd.kdrq, '%Y%m') = @statisticsMonth
GROUP BY kd.djmd
- ) item_data ON store_data.F_StoreId = item_data.F_StoreId";
+ ) item_data ON store_data.F_StoreId = item_data.F_StoreId
+ LEFT JOIN (
+ SELECT
+ hytk.md as F_StoreId,
+ COALESCE(SUM(hytk.tkje), 0) as F_RefundAmount,
+ COUNT(DISTINCT hytk.F_Id) as F_RefundCount
+ FROM lq_hytk_hytk hytk
+ WHERE hytk.F_IsEffective = 1
+ AND DATE_FORMAT(hytk.tksj, '%Y%m') = @statisticsMonth
+ GROUP BY hytk.md
+ ) refund_data ON store_data.F_StoreId = refund_data.F_StoreId";
var storePerformanceData = await _db.Ado.SqlQueryAsync(storePerformanceSql, new { statisticsMonth });
@@ -2563,6 +2586,8 @@ namespace NCC.Extend.LqStatistics
UpgradeOrderCount = Convert.ToInt32(data.F_UpgradeOrderCount ?? 0),
FirstOrderPerformance = Convert.ToDecimal(data.F_FirstOrderPerformance ?? 0),
UpgradeOrderPerformance = Convert.ToDecimal(data.F_UpgradeOrderPerformance ?? 0),
+ RefundAmount = Convert.ToDecimal(data.F_RefundAmount ?? 0),
+ RefundCount = Convert.ToInt32(data.F_RefundCount ?? 0),
CreateTime = DateTime.Now
}).ToList();
@@ -3302,6 +3327,8 @@ namespace NCC.Extend.LqStatistics
ItemQuantity = it.ItemQuantity,
FirstOrderCount = it.FirstOrderCount,
UpgradeOrderCount = it.UpgradeOrderCount,
+ RefundAmount = it.RefundAmount,
+ RefundCount = it.RefundCount,
CreateTime = it.CreateTime.HasValue ? it.CreateTime.Value : DateTime.Now
}).ToList();
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqStudyClassService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqStudyClassService.cs
new file mode 100644
index 0000000..18e738d
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqStudyClassService.cs
@@ -0,0 +1,411 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using NCC.Common.Core.Manager;
+using NCC.Common.Enum;
+using NCC.Common.Filter;
+using NCC.Dependency;
+using NCC.DynamicApiController;
+using NCC.Extend.Entitys.Dto.LqStudyClass;
+using NCC.Extend.Entitys.lq_study_class;
+using NCC.Extend.Entitys.lq_study_student;
+using NCC.Extend.Entitys.lq_study_record;
+using NCC.Extend.Interfaces.LqStudyClass;
+using NCC.FriendlyException;
+using NCC.System.Entitys.Permission;
+using SqlSugar;
+using Yitter.IdGenerator;
+using NCC.Extend.Entitys.Enum;
+
+namespace NCC.Extend
+{
+ ///
+ /// 学习班级服务
+ ///
+ [ApiDescriptionSettings(Tag = "绿纤学习班级管理", Name = "LqStudyClass", Order = 200)]
+ [Route("api/Extend/LqStudyClass")]
+ public class LqStudyClassService : IDynamicApiController, ITransient, ILqStudyClassService
+ {
+ private readonly IUserManager _userManager;
+ private readonly ILogger _logger;
+ private readonly ISqlSugarClient _db;
+
+ ///
+ /// 构造函数
+ ///
+ /// 用户管理器
+ /// 日志记录器
+ /// 数据库客户端
+ public LqStudyClassService(IUserManager userManager, ILogger logger, ISqlSugarClient db)
+ {
+ _userManager = userManager;
+ _logger = logger;
+ _db = db;
+ }
+
+ #region 创建学习班级并添加学员
+ ///
+ /// 创建学习班级并添加学员
+ ///
+ /// 创建输入
+ /// 创建结果
+ [HttpPost("CreateClassWithStudents")]
+ public async Task CreateClassWithStudentsAsync([FromBody] LqStudyClassCreateWithStudentsInput input)
+ {
+ try
+ {
+ _db.Ado.BeginTran();
+
+ // 创建班级
+ var classId = YitIdHelper.NextId().ToString();
+ var classEntity = new LqStudyClassEntity
+ {
+ Id = classId,
+ ClassName = input.ClassName,
+ TeacherId = input.TeacherId,
+ StartTime = input.StartTime,
+ EndTime = input.EndTime,
+ Remark = input.Remark,
+ CreateUser = _userManager.UserId,
+ CreateTime = DateTime.Now,
+ IsEffective = StatusEnum.有效.GetHashCode()
+ };
+
+ await _db.Insertable(classEntity).ExecuteCommandAsync();
+
+ // 创建学员
+ var studentEntities = new List();
+ foreach (var student in input.Students)
+ {
+ var studentEntity = new LqStudyStudentEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ EmployeeName = student.EmployeeName,
+ EmployeePhone = student.EmployeePhone,
+ EmployeeId = student.EmployeeId,
+ AdmissionTime = student.AdmissionTime,
+ ClassId = classId,
+ ClassName = input.ClassName,
+ HrBelong = student.HrBelong,
+ CreateUser = _userManager.UserId,
+ CreateTime = DateTime.Now,
+ IsEffective = StatusEnum.有效.GetHashCode()
+ };
+ studentEntities.Add(studentEntity);
+ }
+
+ if (studentEntities.Any())
+ {
+ await _db.Insertable(studentEntities).ExecuteCommandAsync();
+ }
+
+ _db.Ado.CommitTran();
+
+ return new
+ {
+ success = true,
+ data = new
+ {
+ classId = classId,
+ className = input.ClassName,
+ studentCount = studentEntities.Count,
+ message = $"成功创建班级'{input.ClassName}'并添加{studentEntities.Count}名学员"
+ },
+ message = "创建成功"
+ };
+ }
+ catch (Exception ex)
+ {
+ _db.Ado.RollbackTran();
+ _logger.LogError(ex, "创建学习班级并添加学员失败");
+ throw NCCException.Oh($"创建失败:{ex.Message}");
+ }
+ }
+
+ #endregion
+
+ #region 向现有班级添加学员
+ ///
+ /// 向现有班级添加学员
+ ///
+ /// 添加学员输入
+ /// 添加结果
+ [HttpPost("AddStudentsToClass")]
+ public async Task AddStudentsToClassAsync([FromBody] LqStudyClassAddStudentsInput input)
+ {
+ try
+ {
+ // 验证班级是否存在
+ var classInfo = await _db.Queryable()
+ .Where(x => x.Id == input.ClassId && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .FirstAsync();
+
+ if (classInfo == null)
+ {
+ throw NCCException.Oh("班级不存在或已失效");
+ }
+
+ _db.Ado.BeginTran();
+
+ // 创建学员
+ var studentEntities = new List();
+ foreach (var student in input.Students)
+ {
+ var studentEntity = new LqStudyStudentEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ EmployeeName = student.EmployeeName,
+ EmployeePhone = student.EmployeePhone,
+ EmployeeId = student.EmployeeId,
+ AdmissionTime = student.AdmissionTime,
+ ClassId = input.ClassId,
+ ClassName = classInfo.ClassName,
+ HrBelong = student.HrBelong,
+ CreateUser = _userManager.UserId,
+ CreateTime = DateTime.Now,
+ IsEffective = StatusEnum.有效.GetHashCode()
+ };
+ studentEntities.Add(studentEntity);
+ }
+
+ if (studentEntities.Any())
+ {
+ await _db.Insertable(studentEntities).ExecuteCommandAsync();
+ }
+
+ _db.Ado.CommitTran();
+
+ return new
+ {
+ classId = input.ClassId,
+ className = classInfo.ClassName,
+ addedStudentCount = studentEntities.Count,
+ message = $"成功向班级'{classInfo.ClassName}'添加{studentEntities.Count}名学员"
+ };
+ }
+ catch (Exception ex)
+ {
+ _db.Ado.RollbackTran();
+ _logger.LogError(ex, "向班级添加学员失败");
+ throw NCCException.Oh($"添加失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 获取所有班级列表
+ ///
+ /// 获取所有班级列表
+ ///
+ /// 查询输入
+ /// 班级列表
+ [HttpGet("GetClassList")]
+ public async Task GetClassListAsync([FromQuery] LqStudyClassListQueryInput input)
+ {
+ try
+ {
+ var sidx = input.sidx == null ? "id" : input.sidx;
+
+ // 查询班级信息
+ var data = await _db.Queryable()
+ .WhereIF(!string.IsNullOrWhiteSpace(input.ClassName), x => x.ClassName.Contains(input.ClassName))
+ .WhereIF(!string.IsNullOrWhiteSpace(input.TeacherId), x => x.TeacherId == input.TeacherId)
+ .WhereIF(input.StartTime.HasValue, x => x.StartTime >= input.StartTime.Value)
+ .WhereIF(input.EndTime.HasValue, x => x.StartTime <= input.EndTime.Value)
+ .WhereIF(input.IsEffective.HasValue, x => x.IsEffective == input.IsEffective.Value)
+ .Select(x => new LqStudyClassListOutput
+ {
+ id = x.Id,
+ className = x.ClassName,
+ teacherId = x.TeacherId,
+ teacherName = SqlFunc.Subqueryable().Where(u => u.Id == x.TeacherId).Select(u => u.RealName),
+ startTime = x.StartTime,
+ endTime = x.EndTime,
+ remark = x.Remark,
+ })
+ .MergeTable()
+ .OrderBy(sidx + " " + input.sort)
+ .ToPagedListAsync(input.currentPage, input.pageSize);
+ return PageResult.SqlSugarPageResult(data);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取班级列表失败");
+ throw NCCException.Oh($"获取班级列表失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 获取班级下所有学员信息
+ ///
+ /// 获取班级下所有学员信息(分页)
+ ///
+ /// 查询输入
+ /// 学员列表
+ [HttpGet("GetStudentListByClassId")]
+ public async Task GetStudentListByClassIdAsync([FromQuery] LqStudyStudentListQueryInput input)
+ {
+ try
+ {
+ var sidx = input.sidx == null ? "id" : input.sidx;
+ // 查询学员信息
+ var data = await _db.Queryable()
+ .Where(x => x.ClassId == input.ClassId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeeName), x => x.EmployeeName.Contains(input.EmployeeName))
+ .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeePhone), x => x.EmployeePhone.Contains(input.EmployeePhone))
+ .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeeId), x => x.EmployeeId == input.EmployeeId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.HrBelong), x => x.HrBelong.Contains(input.HrBelong))
+ .WhereIF(input.IsEffective.HasValue, x => x.IsEffective == input.IsEffective.Value)
+ .Select(x => new LqStudyStudentListOutput
+ {
+ id = x.Id,
+ employeeName = SqlFunc.Subqueryable().Where(u => u.Id == x.EmployeeId).Select(u => u.RealName),
+ employeePhone = SqlFunc.Subqueryable().Where(u => u.Id == x.EmployeeId).Select(u => u.MobilePhone),
+ employeeId = x.EmployeeId,
+ admissionTime = x.AdmissionTime,
+ classId = x.ClassId,
+ className = x.ClassName
+ })
+ .MergeTable()
+ .OrderBy(sidx + " " + input.sort)
+ .ToPagedListAsync(input.currentPage, input.pageSize);
+ return PageResult.SqlSugarPageResult(data);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取班级学员列表失败");
+ throw NCCException.Oh($"获取班级学员列表失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 学习记录管理
+ ///
+ /// 添加学习记录
+ ///
+ /// 学习记录输入
+ /// 添加结果
+ [HttpPost("AddStudyRecord")]
+ public async Task AddStudyRecordAsync([FromBody] LqStudyRecordCreateInput input)
+ {
+ // 验证员工是否存在
+ var employee = await _db.Queryable()
+ .Where(x => x.Id == input.EmployeeId && x.RealName == input.EmployeeName)
+ .FirstAsync();
+
+ if (employee == null)
+ {
+ throw NCCException.Oh("员工不存在,请检查员工ID和姓名是否正确");
+ }
+
+ // 如果选择下店协助,验证门店信息
+ if (input.IsStoreAssist == 1)
+ {
+ if (string.IsNullOrWhiteSpace(input.StoreId) || string.IsNullOrWhiteSpace(input.StoreName))
+ {
+ throw NCCException.Oh("选择下店协助时,门店ID和门店名称不能为空");
+ }
+ }
+ // 创建学习记录
+ var recordEntity = new LqStudyRecordEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ EmployeeName = input.EmployeeName,
+ EmployeeId = input.EmployeeId,
+ StudyType = input.StudyType,
+ TransportFee = input.TransportFee,
+ StudyDate = input.StudyDate,
+ DailyStatus = input.DailyStatus,
+ Remark = input.Remark,
+ IsStoreAssist = input.IsStoreAssist,
+ StoreId = input.IsStoreAssist == 1 ? input.StoreId : null,
+ StoreName = input.IsStoreAssist == 1 ? input.StoreName : null,
+ CreateUser = _userManager.UserId,
+ CreateTime = DateTime.Now,
+ IsEffective = 1
+ };
+ var isOk = await _db.Insertable(recordEntity).ExecuteCommandAsync();
+ if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000);
+ }
+ #endregion
+
+ #region 获取学习记录列表
+ ///
+ /// 获取学习记录列表
+ ///
+ /// 查询输入
+ /// 学习记录列表
+ [HttpGet("GetStudyRecordList")]
+ public async Task GetStudyRecordListAsync([FromQuery] LqStudyRecordListQueryInput input)
+ {
+ try
+ {
+ var sidx = input.sidx == null ? "id" : input.sidx;
+
+ // 查询学习记录信息
+ var data = await _db.Queryable()
+ .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeeName), x => x.EmployeeName.Contains(input.EmployeeName))
+ .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeeId), x => x.EmployeeId == input.EmployeeId)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.StudyType), x => x.StudyType.Contains(input.StudyType))
+ .WhereIF(input.StudyDateStart.HasValue, x => x.StudyDate >= input.StudyDateStart.Value)
+ .WhereIF(input.StudyDateEnd.HasValue, x => x.StudyDate <= input.StudyDateEnd.Value)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.DailyStatus), x => x.DailyStatus.Contains(input.DailyStatus))
+ .WhereIF(input.IsStoreAssist.HasValue, x => x.IsStoreAssist == input.IsStoreAssist.Value)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), x => x.StoreId == input.StoreId)
+ .WhereIF(input.IsEffective.HasValue, x => x.IsEffective == input.IsEffective.Value)
+ .Select(x => new LqStudyRecordListOutput
+ {
+ id = x.Id,
+ employeeName = x.EmployeeName,
+ employeeId = x.EmployeeId,
+ studyType = x.StudyType,
+ transportFee = x.TransportFee,
+ studyDate = x.StudyDate,
+ dailyStatus = x.DailyStatus,
+ remark = x.Remark,
+ isStoreAssist = x.IsStoreAssist,
+ storeId = x.StoreId,
+ storeName = x.StoreName,
+ createUser = x.CreateUser,
+ createUserName = SqlFunc.Subqueryable().Where(u => u.Id == x.CreateUser).Select(u => u.RealName),
+ createTime = x.CreateTime,
+ updateUser = x.UpdateUser,
+ updateUserName = SqlFunc.Subqueryable().Where(u => u.Id == x.UpdateUser).Select(u => u.RealName),
+ updateTime = x.UpdateTime,
+ isEffective = x.IsEffective
+ })
+ .MergeTable()
+ .OrderBy(sidx + " " + input.sort)
+ .ToPagedListAsync(input.currentPage, input.pageSize);
+ return PageResult.SqlSugarPageResult(data);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取学习记录列表失败");
+ throw NCCException.Oh($"获取学习记录列表失败:{ex.Message}");
+ }
+ }
+ #endregion
+
+ #region 作废学习记录
+ ///
+ /// 作废学习记录
+ ///
+ /// 学习记录ID
+ /// 作废结果
+ [HttpPost("CancelStudyRecord")]
+ public async Task CancelStudyRecordAsync([FromBody] string id)
+ {
+ var record = await _db.Queryable().Where(x => x.Id == id).FirstAsync();
+ if (record == null) throw NCCException.Oh("学习记录不存在");
+ record.IsEffective = StatusEnum.无效.GetHashCode();
+ record.UpdateTime = DateTime.Now;
+ record.UpdateUser = _userManager.UserId;
+ var isOk = await _db.Updateable(record).ExecuteCommandAsync();
+ if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000);
+ }
+ #endregion
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
index 8c81539..7fbe557 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
@@ -531,7 +531,7 @@ namespace NCC.Extend.LqTkjlb
#region 漏斗统计
///
- /// 获取拓客活动漏斗统计数据
+ /// 获取拓客活动漏斗统计数据(优化版本)
///
/// 活动ID
/// 漏斗统计数据
@@ -540,31 +540,49 @@ namespace NCC.Extend.LqTkjlb
{
try
{
+ // 优化版本:使用子查询减少JOIN复杂度
var sql = @"
SELECT
md.F_Id as store_id,
md.dm as store_name,
- COUNT(DISTINCT tk.F_Id) as tk_count, -- 拓客数量
- COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as yy_count, -- 预约人数(已确认)
- COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as hk_count, -- 耗卡人数
- COALESCE(SUM(CASE WHEN xh.F_Id IS NOT NULL THEN xh.xfje END), 0) as hk_amount, -- 耗卡金额
- ROUND(
- COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 /
- COUNT(DISTINCT tk.F_Id), 2
- ) as yy_conversion_rate, -- 预约转化率(预约人数/拓客数量)
- ROUND(
- COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 /
- COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END), 2
- ) as hk_conversion_rate -- 耗卡转化率(耗卡人数/预约人数)
- FROM lq_tkjlb tk
- JOIN lq_mdxx md ON tk.F_StoreId = md.F_Id
- LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk
- AND yy.F_Status = '已确认'
- LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy
- AND xh.F_IsEffective = 1
- WHERE tk.F_EventId = @eventId
- GROUP BY md.F_Id, md.dm
- ORDER BY tk_count DESC";
+ tk_stats.tk_count,
+ tk_stats.yaoy_count,
+ tk_stats.yy_count,
+ tk_stats.hk_count,
+ tk_stats.kd_count,
+ tk_stats.hk_amount,
+ tk_stats.kd_amount,
+ CASE
+ WHEN tk_stats.tk_count > 0
+ THEN ROUND(tk_stats.yy_count * 100.0 / tk_stats.tk_count, 2)
+ ELSE 0
+ END as yy_conversion_rate,
+ CASE
+ WHEN tk_stats.yy_count > 0
+ THEN ROUND(tk_stats.hk_count * 100.0 / tk_stats.yy_count, 2)
+ ELSE 0
+ END as hk_conversion_rate
+ FROM lq_mdxx md
+ LEFT JOIN (
+ SELECT
+ tk.F_StoreId,
+ COUNT(DISTINCT tk.F_Id) as tk_count,
+ COUNT(DISTINCT yy.F_Id) as yaoy_count,
+ COUNT(DISTINCT yyjl.F_Id) as yy_count,
+ COUNT(DISTINCT xh.F_Id) as hk_count,
+ COUNT(DISTINCT kd.F_Id) as kd_count,
+ COALESCE(SUM(xh.xfje), 0) as hk_amount,
+ COALESCE(SUM(kd.sfyj), 0) as kd_amount
+ FROM lq_tkjlb tk
+ LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId
+ LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认'
+ LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1
+ LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1
+ WHERE tk.F_EventId = @eventId
+ GROUP BY tk.F_StoreId
+ ) tk_stats ON md.F_Id = tk_stats.F_StoreId
+ WHERE tk_stats.F_StoreId IS NOT NULL
+ ORDER BY tk_stats.tk_count DESC";
var result = await _db.Ado.SqlQueryAsync(sql, new { eventId });
@@ -582,7 +600,7 @@ namespace NCC.Extend.LqTkjlb
}
///
- /// 获取拓客活动总体漏斗统计
+ /// 获取拓客活动总体漏斗统计(优化版本)
///
/// 活动ID
/// 总体漏斗统计数据
@@ -593,24 +611,39 @@ namespace NCC.Extend.LqTkjlb
{
var sql = @"
SELECT
- COUNT(DISTINCT tk.F_Id) as total_tk_count, -- 总拓客数量
- COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as total_yy_count, -- 总预约人数
- COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as total_hk_count, -- 总耗卡人数
- COALESCE(SUM(CASE WHEN xh.F_Id IS NOT NULL THEN xh.xfje END), 0) as total_hk_amount, -- 总耗卡金额
- ROUND(
- COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 /
- COUNT(DISTINCT tk.F_Id), 2
- ) as overall_yy_conversion_rate, -- 总体预约转化率
- ROUND(
- COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 /
- COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END), 2
- ) as overall_hk_conversion_rate -- 总体耗卡转化率
- FROM lq_tkjlb tk
- LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk
- AND yy.F_Status = '已确认'
- LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy
- AND xh.F_IsEffective = 1
- WHERE tk.F_EventId = @eventId";
+ SUM(tk_count) as total_tk_count,
+ SUM(yaoy_count) as total_yaoy_count,
+ SUM(yy_count) as total_yy_count,
+ SUM(hk_count) as total_hk_count,
+ SUM(kd_count) as total_kd_count,
+ SUM(hk_amount) as total_hk_amount,
+ SUM(kd_amount) as total_kd_amount,
+ CASE
+ WHEN SUM(tk_count) > 0
+ THEN ROUND(SUM(yy_count) * 100.0 / SUM(tk_count), 2)
+ ELSE 0
+ END as overall_yy_conversion_rate,
+ CASE
+ WHEN SUM(yy_count) > 0
+ THEN ROUND(SUM(hk_count) * 100.0 / SUM(yy_count), 2)
+ ELSE 0
+ END as overall_hk_conversion_rate
+ FROM (
+ SELECT
+ COUNT(DISTINCT tk.F_Id) as tk_count,
+ COUNT(DISTINCT yy.F_Id) as yaoy_count,
+ COUNT(DISTINCT yyjl.F_Id) as yy_count,
+ COUNT(DISTINCT xh.F_Id) as hk_count,
+ COUNT(DISTINCT kd.F_Id) as kd_count,
+ COALESCE(SUM(xh.xfje), 0) as hk_amount,
+ COALESCE(SUM(kd.sfyj), 0) as kd_amount
+ FROM lq_tkjlb tk
+ LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId
+ LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认'
+ LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1
+ LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1
+ WHERE tk.F_EventId = @eventId
+ ) stats";
var result = await _db.Ado.SqlQueryAsync(sql, new { eventId });
@@ -626,10 +659,202 @@ namespace NCC.Extend.LqTkjlb
throw NCCException.Oh("获取总体漏斗统计数据失败:" + ex.Message);
}
}
+
+ ///
+ /// 获取拓客活动漏斗统计数据(高性能版本 - 分步查询)
+ ///
+ /// 活动ID
+ /// 漏斗统计数据
+ [HttpGet("GetFunnelStatisticsFast/{eventId}")]
+ public async Task GetFunnelStatisticsFast(string eventId)
+ {
+ try
+ {
+ // 第一步:获取拓客基础数据
+ var tkSql = @"
+ SELECT
+ tk.F_StoreId,
+ md.dm as store_name,
+ COUNT(DISTINCT tk.F_Id) as tk_count
+ FROM lq_tkjlb tk
+ JOIN lq_mdxx md ON tk.F_StoreId = md.F_Id
+ WHERE tk.F_EventId = @eventId
+ GROUP BY tk.F_StoreId, md.dm";
+
+ var tkData = await _db.Ado.SqlQueryAsync(tkSql, new { eventId });
+ var tkDict = tkData.ToDictionary(x => (string)x.F_StoreId, x => x);
+
+ // 第二步:获取邀约数据(按会员ID去重)
+ var yaoySql = @"
+ SELECT
+ tk.F_StoreId,
+ COUNT(DISTINCT tk.F_MemberId) as yaoy_count
+ FROM lq_tkjlb tk
+ LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId
+ WHERE tk.F_EventId = @eventId AND yy.F_Id IS NOT NULL
+ GROUP BY tk.F_StoreId";
+
+ var yaoyData = await _db.Ado.SqlQueryAsync(yaoySql, new { eventId });
+ var yaoyDict = yaoyData.ToDictionary(x => (string)x.F_StoreId, x => (int)x.yaoy_count);
+
+ // 第三步:获取预约数据(按会员ID去重)
+ var yySql = @"
+ SELECT
+ tk.F_StoreId,
+ COUNT(DISTINCT tk.F_MemberId) as yy_count
+ FROM lq_tkjlb tk
+ LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认'
+ WHERE tk.F_EventId = @eventId AND yyjl.F_Id IS NOT NULL
+ GROUP BY tk.F_StoreId";
+
+ var yyData = await _db.Ado.SqlQueryAsync(yySql, new { eventId });
+ var yyDict = yyData.ToDictionary(x => (string)x.F_StoreId, x => (int)x.yy_count);
+
+ // 第四步:获取耗卡数据(按会员ID去重,但金额不去重)
+ var hkSql = @"
+ SELECT
+ tk.F_StoreId,
+ COUNT(DISTINCT tk.F_MemberId) as hk_count,
+ COALESCE(SUM(xh.xfje), 0) as hk_amount
+ FROM lq_tkjlb tk
+ LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1
+ WHERE tk.F_EventId = @eventId AND xh.F_Id IS NOT NULL
+ GROUP BY tk.F_StoreId";
+
+ var hkData = await _db.Ado.SqlQueryAsync(hkSql, new { eventId });
+ var hkDict = hkData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.hk_count, amount = (decimal)x.hk_amount });
+
+ // 第五步:获取开单数据(按会员ID去重,但金额不去重)
+ var kdSql = @"
+ SELECT
+ tk.F_StoreId,
+ COUNT(DISTINCT tk.F_MemberId) as kd_count,
+ COALESCE(SUM(kd.sfyj), 0) as kd_amount
+ FROM lq_tkjlb tk
+ LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1
+ WHERE tk.F_EventId = @eventId AND kd.F_Id IS NOT NULL
+ GROUP BY tk.F_StoreId";
+
+ var kdData = await _db.Ado.SqlQueryAsync(kdSql, new { eventId });
+ var kdDict = kdData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.kd_count, amount = (decimal)x.kd_amount });
+
+ // 合并结果
+ var result = tkDict.Values.Select(tk => new
+ {
+ store_id = tk.F_StoreId,
+ store_name = tk.store_name,
+ tk_count = (int)tk.tk_count,
+ yaoy_count = yaoyDict.ContainsKey(tk.F_StoreId) ? yaoyDict[tk.F_StoreId] : 0,
+ yy_count = yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0,
+ hk_count = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].count : 0,
+ kd_count = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].count : 0,
+ hk_amount = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].amount : 0m,
+ kd_amount = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].amount : 0m,
+ yy_conversion_rate = (int)tk.tk_count > 0 ? Math.Round((yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0) * 100.0 / (int)tk.tk_count, 2) : 0,
+ hk_conversion_rate = (yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0) > 0 ? Math.Round((hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].count : 0) * 100.0 / (yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0), 2) : 0
+ }).OrderByDescending(x => x.tk_count).ToList();
+
+ return new
+ {
+ success = true,
+ data = result,
+ message = "获取漏斗统计数据成功(高性能版本)"
+ };
+ }
+ catch (Exception ex)
+ {
+ throw NCCException.Oh("获取漏斗统计数据失败:" + ex.Message);
+ }
+ }
#endregion
#region 门店顾客详情
///
+ /// 生成门店顾客详情查询SQL
+ ///
+ /// 是否分页
+ /// SQL语句
+ private string GetStoreCustomerDetailsSql(bool isPaged = false)
+ {
+ var baseSql = @"
+ SELECT
+ tk.F_Id as tk_id, -- 拓客记录ID
+ tk.F_CustomerPhone as customer_phone, -- 顾客手机号
+ tk.F_MemberId as member_id, -- 会员ID
+ tk.F_CustomerName as customer_name, -- 顾客姓名
+ tk.F_CreateTime as tk_time, -- 拓客时间
+ -- 邀约信息
+ yaoy.F_Id as yaoy_id, -- 邀约ID
+ yaoy.F_CreateTime as yaoy_time, -- 邀约时间
+ yaoy.F_Status as yaoy_status, -- 邀约状态
+ -- 预约信息
+ yy.F_Id as yy_id, -- 预约ID
+ yy.F_Status as yy_status, -- 预约状态
+ yy.F_CreateTime as yy_time, -- 预约时间
+ yy.yysj as appointment_time, -- 预约到店时间
+ -- 耗卡信息(聚合)
+ xh_summary.total_consume_amount, -- 耗卡总金额
+ xh_summary.consume_count, -- 耗卡次数
+ xh_summary.first_consume_time, -- 首次耗卡时间
+ xh_summary.last_consume_time, -- 最后耗卡时间
+ -- 开卡信息(聚合)
+ kd_summary.total_billing_amount, -- 开卡总金额
+ kd_summary.total_debt_amount, -- 总欠款金额
+ kd_summary.billing_count, -- 开卡次数
+ kd_summary.first_billing_time, -- 首次开卡时间
+ kd_summary.last_billing_time, -- 最后开卡时间
+ -- 状态描述
+ CASE
+ WHEN yaoy.F_Id IS NOT NULL THEN '已邀约'
+ ELSE '未邀约'
+ END as invitation_status, -- 邀约状态描述
+ CASE
+ WHEN yy.F_Id IS NOT NULL THEN '已预约'
+ ELSE '未预约'
+ END as appointment_status, -- 预约状态描述
+ CASE
+ WHEN xh_summary.total_consume_amount > 0 THEN '已耗卡'
+ ELSE '未耗卡'
+ END as consume_status, -- 耗卡状态描述
+ CASE
+ WHEN kd_summary.total_billing_amount > 0 THEN '已开卡'
+ ELSE '未开卡'
+ END as billing_status -- 开卡状态描述
+ FROM lq_tkjlb tk
+ LEFT JOIN lq_yaoyjl yaoy ON tk.F_MemberId = yaoy.yykh
+ AND yaoy.F_StoreId = tk.F_StoreId
+ LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk
+ AND yy.F_Status = '已确认'
+ LEFT JOIN (
+ SELECT
+ hy as member_id,
+ SUM(xfje) as total_consume_amount,
+ COUNT(*) as consume_count,
+ MIN(F_CreateTime) as first_consume_time,
+ MAX(F_CreateTime) as last_consume_time
+ FROM lq_xh_hyhk
+ WHERE F_IsEffective = 1
+ GROUP BY hy
+ ) xh_summary ON tk.F_MemberId = xh_summary.member_id
+ LEFT JOIN (
+ SELECT
+ kdhy as member_id,
+ SUM(sfyj) as total_billing_amount,
+ SUM(qk) as total_debt_amount,
+ COUNT(*) as billing_count,
+ MIN(F_CreateTime) as first_billing_time,
+ MAX(F_CreateTime) as last_billing_time
+ FROM lq_kd_kdjlb
+ WHERE F_IsEffective = 1
+ GROUP BY kdhy
+ ) kd_summary ON tk.F_MemberId = kd_summary.member_id
+ WHERE tk.F_EventId = @eventId
+ AND tk.F_StoreId = @storeId
+ ORDER BY tk.F_CreateTime DESC";
+ return isPaged ? baseSql + " LIMIT @offset, @pageSize" : baseSql;
+ }
+
+ ///
/// 获取门店拓客活动顾客详情
///
/// 活动ID
@@ -640,37 +865,7 @@ namespace NCC.Extend.LqTkjlb
{
try
{
- var sql = @"
- SELECT
- tk.F_Id as tk_id, -- 拓客记录ID
- tk.F_CustomerPhone as customer_phone, -- 顾客手机号
- tk.F_MemberId as member_id, -- 会员ID
- tk.F_CustomerName as customer_name, -- 顾客姓名
- tk.F_CreateTime as tk_time, -- 拓客时间
- yy.F_Id as yy_id, -- 预约ID
- yy.F_Status as yy_status, -- 预约状态
- yy.F_CreateTime as yy_time, -- 预约时间
- yy.yysj as appointment_time, -- 预约到店时间
- xh.F_Id as xh_id, -- 耗卡ID
- xh.F_CreateTime as xh_time, -- 耗卡时间
- xh.xfje as consume_amount, -- 耗卡金额
- CASE
- WHEN yy.F_Id IS NOT NULL THEN '已预约'
- ELSE '未预约'
- END as appointment_status, -- 预约状态描述
- CASE
- WHEN xh.F_Id IS NOT NULL THEN '已耗卡'
- ELSE '未耗卡'
- END as consume_status -- 耗卡状态描述
- FROM lq_tkjlb tk
- LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk
- AND yy.F_Status = '已确认'
- LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy
- AND xh.F_IsEffective = 1
- WHERE tk.F_EventId = @eventId
- AND tk.F_StoreId = @storeId
- ORDER BY tk.F_CreateTime DESC";
-
+ var sql = GetStoreCustomerDetailsSql(false);
var result = await _db.Ado.SqlQueryAsync(sql, new { eventId, storeId });
return new
@@ -699,44 +894,12 @@ namespace NCC.Extend.LqTkjlb
{
try
{
- var sql = @"
- SELECT
- tk.F_Id as tk_id, -- 拓客记录ID
- tk.F_CustomerPhone as customer_phone, -- 顾客手机号
- tk.F_MemberId as member_id, -- 会员ID
- tk.F_CustomerName as customer_name, -- 顾客姓名
- tk.F_CreateTime as tk_time, -- 拓客时间
- yy.F_Id as yy_id, -- 预约ID
- yy.F_Status as yy_status, -- 预约状态
- yy.F_CreateTime as yy_time, -- 预约时间
- yy.yysj as appointment_time, -- 预约到店时间
- xh.F_Id as xh_id, -- 耗卡ID
- xh.F_CreateTime as xh_time, -- 耗卡时间
- xh.xfje as consume_amount, -- 耗卡金额
- CASE
- WHEN yy.F_Id IS NOT NULL THEN '已预约'
- ELSE '未预约'
- END as appointment_status, -- 预约状态描述
- CASE
- WHEN xh.F_Id IS NOT NULL THEN '已耗卡'
- ELSE '未耗卡'
- END as consume_status -- 耗卡状态描述
- FROM lq_tkjlb tk
- LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk
- AND yy.F_Status = '已确认'
- LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy
- AND xh.F_IsEffective = 1
- WHERE tk.F_EventId = @eventId
- AND tk.F_StoreId = @storeId
- ORDER BY tk.F_CreateTime DESC
- LIMIT @offset, @pageSize";
-
+ var sql = GetStoreCustomerDetailsSql(true);
var countSql = @"
SELECT COUNT(*) as total
FROM lq_tkjlb tk
WHERE tk.F_EventId = @eventId
AND tk.F_StoreId = @storeId";
-
var offset = (pageIndex - 1) * pageSize;
var result = await _db.Ado.SqlQueryAsync(sql, new { eventId, storeId, offset, pageSize });
var totalResult = await _db.Ado.SqlQueryAsync(countSql, new { eventId, storeId });
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
index 8e6f6cd..56bbc87 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
@@ -193,6 +193,7 @@ namespace NCC.Extend.LqXhHyhk
.WhereIF(queryHksj != null, p => p.Hksj >= new DateTime(startHksj.ToDate().Year, startHksj.ToDate().Month, startHksj.ToDate().Day, 0, 0, 0))
.WhereIF(queryHksj != null, p => p.Hksj <= new DateTime(endHksj.ToDate().Year, endHksj.ToDate().Month, endHksj.ToDate().Day, 23, 59, 59))
.WhereIF(!string.IsNullOrEmpty(input.czry), p => p.Czry.Equals(input.czry))
+ .WhereIF(input.isEffective != 0, p => p.IsEffective == input.isEffective)
.Select(it => new LqXhHyhkListOutput
{
id = it.Id,
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqXmzlService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqXmzlService.cs
index e1d1d90..3024f22 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqXmzlService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqXmzlService.cs
@@ -15,6 +15,12 @@ using System.Linq;
using System.Threading.Tasks;
using NCC.Extend.Entitys.lq_xmzl;
using NCC.Extend.Entitys.Dto.LqXmzl;
+using NCC.Extend.Entitys.lq_kd_pxmx;
+using NCC.Extend.Entitys.lq_xh_pxmx;
+using NCC.Extend.Entitys.lq_hytk_mx;
+using NCC.Extend.Entitys.lq_kd_kdjlb;
+using NCC.Extend.Entitys.lq_xh_hyhk;
+using NCC.Extend.Entitys.lq_hytk_hytk;
using Yitter.IdGenerator;
using NCC.Common.Helper;
using NCC.JsonSerialization;
@@ -28,7 +34,7 @@ namespace NCC.Extend.LqXmzl
///
/// 项目资料服务
///
- [ApiDescriptionSettings(Tag = "绿纤项目资料服务", Name = "LqXmzl", Order = 200)]
+ [ApiDescriptionSettings(Tag = "绿纤品项资料服务", Name = "LqXmzl", Order = 200)]
[Route("api/Extend/[controller]")]
public class LqXmzlService : ILqXmzlService, IDynamicApiController, ITransient
{
@@ -46,7 +52,7 @@ namespace NCC.Extend.LqXmzl
_userManager = userManager;
}
- #region 获取项目资料
+ #region 获取品项资料
///
/// 获取项目资料
@@ -62,9 +68,9 @@ namespace NCC.Extend.LqXmzl
}
#endregion
- #region 获取项目资料列表
+ #region 获取品项资料列表
///
- /// 获取项目资料列表
+ /// 获取品项资料列表
///
/// 请求参数
///
@@ -114,9 +120,9 @@ namespace NCC.Extend.LqXmzl
}
#endregion
- #region 新建项目资料
+ #region 新建品项资料
///
- /// 新建项目资料
+ /// 新建品项资料
///
/// 参数
///
@@ -131,9 +137,9 @@ namespace NCC.Extend.LqXmzl
}
#endregion
- #region 获取项目资料无分页列表
+ #region 获取品项资料无分页列表
///
- /// 获取项目资料无分页列表
+ /// 获取品项资料无分页列表
///
/// 请求参数
///
@@ -177,9 +183,9 @@ namespace NCC.Extend.LqXmzl
}
#endregion
- #region 导出项目资料
+ #region 导出品项资料
///
- /// 导出项目资料
+ /// 导出品项资料
///
/// 请求参数
///
@@ -225,9 +231,9 @@ namespace NCC.Extend.LqXmzl
}
#endregion
- #region 批量删除项目资料
+ #region 批量删除品项资料
///
- /// 批量删除项目资料
+ /// 批量删除品项资料
///
/// 主键数组
///
@@ -257,9 +263,9 @@ namespace NCC.Extend.LqXmzl
}
#endregion
- #region 更新项目资料
+ #region 更新品项资料
///
- /// 更新项目资料
+ /// 更新品项资料
///
/// 主键
/// 参数
@@ -273,9 +279,9 @@ namespace NCC.Extend.LqXmzl
}
#endregion
- #region 删除项目资料
+ #region 删除品项资料
///
- /// 删除项目资料
+ /// 删除品项资料
///
/// 主键
///
@@ -292,13 +298,13 @@ namespace NCC.Extend.LqXmzl
///
/// 字段名称,支持:fl1、fl2、fl3、fl4、fl、qt1、beautyType、sourceType
/// 去重后的字段数据
- [HttpPost("GetDistinctFieldData")]
- public async Task GetDistinctFieldData([FromBody] string fieldName)
+ [HttpGet("GetDistinctFieldData")]
+ public async Task GetDistinctFieldData([FromQuery] string fieldName)
{
try
{
// 验证字段名称
- var validFields = new[] { "fl1", "fl2", "fl3", "fl4", "fl", "qt1", "beautyType", "sourceType" };
+ var validFields = new[] { "fl1", "fl2", "fl3", "fl4", "fl", "qt1", "qt2", "beautyType", "sourceType" };
if (!validFields.Contains(fieldName))
{
throw NCCException.Oh($"无效的字段名称: {fieldName}。支持的字段: {string.Join(", ", validFields)}");
@@ -350,6 +356,13 @@ namespace NCC.Extend.LqXmzl
.Distinct()
.ToListAsync();
break;
+ case "qt2":
+ distinctValues = await _db.Queryable()
+ .Where(p => !string.IsNullOrEmpty(p.Qt2))
+ .Select(p => p.Qt2)
+ .Distinct()
+ .ToListAsync();
+ break;
case "beautyType":
distinctValues = await _db.Queryable()
.Where(p => !string.IsNullOrEmpty(p.BeautyType))
@@ -379,6 +392,309 @@ namespace NCC.Extend.LqXmzl
}
#endregion
+ #region 品项维度统计
+ ///
+ /// 品项维度统计
+ ///
+ ///
+ /// 按品项维度统计开卡、消耗、退卡等数据
+ /// 包括业绩、人数、占比、复购率等指标
+ ///
+ /// 示例请求:
+ /// ```json
+ /// {
+ /// "startTime": "2024-01-01",
+ /// "endTime": "2024-12-31",
+ /// "storeId": "store001",
+ /// "category": "美容",
+ /// "itemId": "item001"
+ /// }
+ /// ```
+ ///
+ /// 参数说明:
+ /// - startTime: 开始时间(可选)
+ /// - endTime: 结束时间(可选)
+ /// - storeId: 门店ID(可选)
+ /// - category: 品项分类(可选)
+ /// - itemId: 品项ID(可选,单个品项统计)
+ ///
+ /// 统计输入参数
+ /// 品项维度统计数据
+ /// 统计成功
+ /// 参数错误
+ /// 服务器错误
+ [HttpPost("GetItemStatistics")]
+ public async Task GetItemStatistics([FromBody] LqXmzlStatisticsInput input)
+ {
+ try
+ {
+ // 第一步:获取品项基础信息
+ var itemsQuery = _db.Queryable()
+ .Where(x => x.IsEffective == 1);
+
+ if (!string.IsNullOrEmpty(input.ItemId))
+ {
+ itemsQuery = itemsQuery.Where(x => x.Id == input.ItemId);
+ }
+
+ if (!string.IsNullOrEmpty(input.Category))
+ {
+ itemsQuery = itemsQuery.Where(x => x.Fl1 == input.Category || x.Fl2 == input.Category || x.Fl == input.Category);
+ }
+
+ var items = await itemsQuery.ToListAsync();
+
+ if (!items.Any())
+ {
+ return new
+ {
+ success = true,
+ data = new List(),
+ message = "未找到符合条件的品项"
+ };
+ }
+
+ var itemIds = items.Select(x => x.Id).ToList();
+
+ // 第二步:开卡数据统计
+ var billingStats = await GetBillingStatistics(itemIds, input);
+
+ // 第三步:消耗数据统计
+ var consumeStats = await GetConsumeStatistics(itemIds, input);
+
+ // 第四步:退卡数据统计
+ var refundStats = await GetRefundStatistics(itemIds, input);
+
+ // 第五步:计算总数据用于占比计算
+ var totalBillingAmount = billingStats.Sum(x => x.BillingAmount);
+ var totalConsumeAmount = consumeStats.Sum(x => x.ConsumeAmount);
+ var totalBuyers = billingStats.Sum(x => x.TotalBuyers);
+
+ // 第六步:合并数据并计算占比
+ var result = new List();
+
+ foreach (var item in items)
+ {
+ var billingData = billingStats.FirstOrDefault(x => x.ItemId == item.Id);
+ var consumeData = consumeStats.FirstOrDefault(x => x.ItemId == item.Id);
+ var refundData = refundStats.FirstOrDefault(x => x.ItemId == item.Id);
+
+ var output = new LqXmzlStatisticsOutput
+ {
+ ItemId = item.Id,
+ ItemName = item.Xmmc,
+ ItemNumber = item.Xmbh,
+ BillingAmount = billingData?.BillingAmount ?? 0,
+ BillingAmountRatio = totalBillingAmount > 0 ? (billingData?.BillingAmount ?? 0) / totalBillingAmount : 0,
+ TotalBuyers = billingData?.TotalBuyers ?? 0,
+ ItemRatio = totalBuyers > 0 ? (billingData?.TotalBuyers ?? 0) / (decimal)totalBuyers : 0,
+ RepeatBuyers = billingData?.RepeatBuyers ?? 0,
+ RepeatBuyRate = (billingData?.TotalBuyers ?? 0) > 0 ? (billingData?.RepeatBuyers ?? 0) / (decimal)(billingData?.TotalBuyers ?? 1) : 0,
+ ConsumeAmount = consumeData?.ConsumeAmount ?? 0,
+ ConsumeAmountRatio = totalConsumeAmount > 0 ? (consumeData?.ConsumeAmount ?? 0) / totalConsumeAmount : 0,
+ ConsumePurchaseCount = consumeData?.ConsumePurchaseCount ?? 0,
+ ConsumeGiftCount = consumeData?.ConsumeGiftCount ?? 0,
+ ConsumeExperienceCount = consumeData?.ConsumeExperienceCount ?? 0,
+ RefundAmount = refundData?.RefundAmount ?? 0,
+ RefundCount = refundData?.RefundCount ?? 0
+ };
+
+ result.Add(output);
+ }
+
+ return new
+ {
+ success = true,
+ data = result,
+ message = "品项维度统计成功"
+ };
+ }
+ catch (Exception ex)
+ {
+ throw NCCException.Oh($"品项维度统计失败:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 获取开卡统计数据
+ ///
+ private async Task> GetBillingStatistics(List itemIds, LqXmzlStatisticsInput input)
+ {
+ var query = _db.Queryable()
+ .Where(x => itemIds.Contains(x.Px) && x.IsEffective == 1);
+
+ // 时间过滤
+ if (input.StartTime.HasValue)
+ {
+ query = query.Where(x => x.CreateTIme >= input.StartTime.Value);
+ }
+ if (input.EndTime.HasValue)
+ {
+ query = query.Where(x => x.CreateTIme <= input.EndTime.Value);
+ }
+
+ // 门店过滤(通过开单记录关联)
+ if (!string.IsNullOrEmpty(input.StoreId))
+ {
+ query = query.InnerJoin((px, kd) => px.Glkdbh == kd.Id)
+ .Where((px, kd) => kd.Djmd == input.StoreId && kd.IsEffective == 1);
+ }
+
+ var result = await query
+ .GroupBy(x => x.Px)
+ .Select(x => new ItemStatisticsData
+ {
+ ItemId = x.Px,
+ BillingAmount = SqlFunc.AggregateSum(x.Pxjg * x.ProjectNumber),
+ TotalBuyers = SqlFunc.AggregateCount(x.MemberId),
+ RepeatBuyers = 0 // 复购人数需要单独计算
+ })
+ .ToListAsync();
+
+ // 单独计算复购人数
+ foreach (var item in result)
+ {
+ var memberCountQuery = _db.Queryable()
+ .Where(x => x.Px == item.ItemId && x.IsEffective == 1);
+
+ if (input.StartTime.HasValue)
+ {
+ memberCountQuery = memberCountQuery.Where(x => x.CreateTIme >= input.StartTime.Value);
+ }
+ if (input.EndTime.HasValue)
+ {
+ memberCountQuery = memberCountQuery.Where(x => x.CreateTIme <= input.EndTime.Value);
+ }
+
+ if (!string.IsNullOrEmpty(input.StoreId))
+ {
+ memberCountQuery = memberCountQuery.InnerJoin((px, kd) => px.Glkdbh == kd.Id)
+ .Where((px, kd) => kd.Djmd == input.StoreId && kd.IsEffective == 1);
+ }
+
+ var memberStats = await memberCountQuery
+ .GroupBy(x => x.MemberId)
+ .Having(x => SqlFunc.AggregateCount(x.MemberId) > 1)
+ .Select(x => SqlFunc.AggregateCount(x.MemberId))
+ .ToListAsync();
+
+ item.RepeatBuyers = memberStats.Count;
+ }
+
+ return result;
+ }
+
+ ///
+ /// 获取消耗统计数据
+ ///
+ private async Task> GetConsumeStatistics(List itemIds, LqXmzlStatisticsInput input)
+ {
+ var query = _db.Queryable()
+ .Where(x => itemIds.Contains(x.Px));
+
+ // 时间过滤
+ if (input.StartTime.HasValue)
+ {
+ query = query.Where(x => x.CreateTIme >= input.StartTime.Value);
+ }
+ if (input.EndTime.HasValue)
+ {
+ query = query.Where(x => x.CreateTIme <= input.EndTime.Value);
+ }
+
+ // 门店过滤(通过耗卡记录关联)
+ if (!string.IsNullOrEmpty(input.StoreId))
+ {
+ query = query.InnerJoin((px, xh) => px.ConsumeInfoId == xh.Id)
+ .Where((px, xh) => xh.Md == input.StoreId && xh.IsEffective == 1);
+ }
+
+ var result = await query
+ .GroupBy(x => x.Px)
+ .Select(x => new ItemConsumeStatisticsData
+ {
+ ItemId = x.Px,
+ ConsumeAmount = SqlFunc.AggregateSum(x.Pxjg * x.ProjectNumber),
+ ConsumePurchaseCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SourceType == "购买", x.ProjectNumber, 0)),
+ ConsumeGiftCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SourceType == "赠送", x.ProjectNumber, 0)),
+ ConsumeExperienceCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SourceType == "体验", x.ProjectNumber, 0))
+ })
+ .ToListAsync();
+
+ return result;
+ }
+
+ ///
+ /// 获取退卡统计数据
+ ///
+ private async Task> GetRefundStatistics(List itemIds, LqXmzlStatisticsInput input)
+ {
+ var query = _db.Queryable()
+ .Where(x => itemIds.Contains(x.Px));
+
+ // 时间过滤
+ if (input.StartTime.HasValue)
+ {
+ query = query.Where(x => x.Tksj >= input.StartTime.Value);
+ }
+ if (input.EndTime.HasValue)
+ {
+ query = query.Where(x => x.Tksj <= input.EndTime.Value);
+ }
+
+ // 门店过滤(通过退卡记录关联)
+ if (!string.IsNullOrEmpty(input.StoreId))
+ {
+ query = query.InnerJoin((mx, hytk) => mx.RefundInfoId == hytk.Id)
+ .Where((mx, hytk) => hytk.Md == input.StoreId && hytk.IsEffective == 1);
+ }
+
+ var result = await query
+ .GroupBy(x => x.Px)
+ .Select(x => new ItemRefundStatisticsData
+ {
+ ItemId = x.Px,
+ RefundAmount = SqlFunc.AggregateSum(x.Tkje ?? 0),
+ RefundCount = SqlFunc.AggregateCount(x.Id)
+ })
+ .ToListAsync();
+
+ return result;
+ }
+ #endregion
+
+ }
+
+ ///
+ /// 品项统计数据(内部类)
+ ///
+ public class ItemStatisticsData
+ {
+ public string ItemId { get; set; }
+ public decimal BillingAmount { get; set; }
+ public int TotalBuyers { get; set; }
+ public int RepeatBuyers { get; set; }
+ }
+
+ ///
+ /// 品项消耗统计数据(内部类)
+ ///
+ public class ItemConsumeStatisticsData
+ {
+ public string ItemId { get; set; }
+ public decimal ConsumeAmount { get; set; }
+ public int ConsumePurchaseCount { get; set; }
+ public int ConsumeGiftCount { get; set; }
+ public int ConsumeExperienceCount { get; set; }
+ }
+ ///
+ /// 品项退卡统计数据(内部类)
+ ///
+ public class ItemRefundStatisticsData
+ {
+ public string ItemId { get; set; }
+ public decimal RefundAmount { get; set; }
+ public int RefundCount { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqYcsdDysbmxbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqYcsdDysbmxbService.cs
index 6048ee4..75cd737 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqYcsdDysbmxbService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqYcsdDysbmxbService.cs
@@ -28,7 +28,7 @@ namespace NCC.Extend.LqYcsdDysbmxb
///
/// 当月社保明细表服务
///
- [ApiDescriptionSettings(Tag = "Extend",Name = "LqYcsdDysbmxb", Order = 200)]
+ [ApiDescriptionSettings(Tag = "Extend", Name = "LqYcsdDysbmxb", Order = 200)]
[Route("api/Extend/[controller]")]
public class LqYcsdDysbmxbService : ILqYcsdDysbmxbService, IDynamicApiController, ITransient
{
@@ -43,7 +43,7 @@ namespace NCC.Extend.LqYcsdDysbmxb
ISqlSugarRepository lqYcsdDysbmxbRepository,
IUserManager userManager)
{
- _lqYcsdDysbmxbRepository = lqYcsdDysbmxbRepository;
+ _lqYcsdDysbmxbRepository = lqYcsdDysbmxbRepository;
_db = _lqYcsdDysbmxbRepository.Context;
_userManager = userManager;
}
@@ -84,23 +84,23 @@ namespace NCC.Extend.LqYcsdDysbmxb
.WhereIF(!string.IsNullOrEmpty(input.zj), p => p.Zj.Equals(input.zj))
.WhereIF(!string.IsNullOrEmpty(input.gzk), p => p.Gzk.Equals(input.gzk))
.WhereIF(!string.IsNullOrEmpty(input.cb), p => p.Cb.Equals(input.cb))
- .Select(it=> new LqYcsdDysbmxbListOutput
+ .Select(it => new LqYcsdDysbmxbListOutput
{
id = it.Id,
- xm=it.Xm,
- md1=it.Md1,
- md2=it.Md2,
- gmmd=it.Gmmd,
- hxcb=it.Hxcb,
- cbyf=it.Cbyf,
- yf=it.Yf,
- sb=it.Sb,
- yb=it.Yb,
- zj=it.Zj,
- gzk=it.Gzk,
- cb=it.Cb,
- }).MergeTable().OrderBy(sidx+" "+input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
- return PageResult.SqlSugarPageResult(data);
+ xm = it.Xm,
+ md1 = it.Md1,
+ md2 = it.Md2,
+ gmmd = it.Gmmd,
+ hxcb = it.Hxcb,
+ cbyf = it.Cbyf,
+ yf = it.Yf,
+ sb = it.Sb,
+ yb = it.Yb,
+ zj = it.Zj,
+ gzk = it.Gzk,
+ cb = it.Cb,
+ }).MergeTable().OrderBy(sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
+ return PageResult.SqlSugarPageResult(data);
}
///
@@ -141,23 +141,23 @@ namespace NCC.Extend.LqYcsdDysbmxb
.WhereIF(!string.IsNullOrEmpty(input.zj), p => p.Zj.Equals(input.zj))
.WhereIF(!string.IsNullOrEmpty(input.gzk), p => p.Gzk.Equals(input.gzk))
.WhereIF(!string.IsNullOrEmpty(input.cb), p => p.Cb.Equals(input.cb))
- .Select(it=> new LqYcsdDysbmxbListOutput
+ .Select(it => new LqYcsdDysbmxbListOutput
{
id = it.Id,
- xm=it.Xm,
- md1=it.Md1,
- md2=it.Md2,
- gmmd=it.Gmmd,
- hxcb=it.Hxcb,
- cbyf=it.Cbyf,
- yf=it.Yf,
- sb=it.Sb,
- yb=it.Yb,
- zj=it.Zj,
- gzk=it.Gzk,
- cb=it.Cb,
- }).MergeTable().OrderBy(sidx+" "+input.sort).ToListAsync();
- return data;
+ xm = it.Xm,
+ md1 = it.Md1,
+ md2 = it.Md2,
+ gmmd = it.Gmmd,
+ hxcb = it.Hxcb,
+ cbyf = it.Cbyf,
+ yf = it.Yf,
+ sb = it.Sb,
+ yb = it.Yb,
+ zj = it.Zj,
+ gzk = it.Gzk,
+ cb = it.Cb,
+ }).MergeTable().OrderBy(sidx + " " + input.sort).ToListAsync();
+ return data;
}
///
@@ -179,7 +179,7 @@ namespace NCC.Extend.LqYcsdDysbmxb
{
exportData = await this.GetNoPagingList(input);
}
- List paramList = "[{\"value\":\"序号\",\"field\":\"id\"},{\"value\":\"姓名\",\"field\":\"xm\"},{\"value\":\"门店1\",\"field\":\"md1\"},{\"value\":\"门店2\",\"field\":\"md2\"},{\"value\":\"购买门店\",\"field\":\"gmmd\"},{\"value\":\"后续参保\",\"field\":\"hxcb\"},{\"value\":\"参保月份\",\"field\":\"cbyf\"},{\"value\":\"月份\",\"field\":\"yf\"},{\"value\":\"社保\",\"field\":\"sb\"},{\"value\":\"医保\",\"field\":\"yb\"},{\"value\":\"总计\",\"field\":\"zj\"},{\"value\":\"工资扣\",\"field\":\"gzk\"},{\"value\":\"成本\",\"field\":\"cb\"},]".ToList();
+ List paramList = "[{\"value\":\"序号\",\"field\":\"id\"},{\"value\":\"姓名\",\"field\":\"xm\"},{\"value\":\"门店1\",\"field\":\"md1\"},{\"value\":\"门店2\",\"field\":\"md2\"},{\"value\":\"购买门店\",\"field\":\"gmmd\"},{\"value\":\"后续参保\",\"field\":\"hxcb\"},{\"value\":\"参保月份\",\"field\":\"cbyf\"},{\"value\":\"月份\",\"field\":\"yf\"},{\"value\":\"社保\",\"field\":\"sb\"},{\"value\":\"医保\",\"field\":\"yb\"},{\"value\":\"总计\",\"field\":\"zj\"},{\"value\":\"工资扣\",\"field\":\"gzk\"},{\"value\":\"成本\",\"field\":\"cb\"},]".ToList();
ExcelConfig excelconfig = new ExcelConfig();
excelconfig.FileName = "当月社保明细表.xls";
excelconfig.HeadFont = "微软雅黑";
@@ -222,7 +222,7 @@ namespace NCC.Extend.LqYcsdDysbmxb
//开启事务
_db.BeginTran();
//批量删除当月社保明细表
- await _db.Deleteable().In(d => d.Id,ids).ExecuteCommandAsync();
+ await _db.Deleteable().In(d => d.Id, ids).ExecuteCommandAsync();
//关闭事务
_db.CommitTran();
}