diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListOutput.cs
new file mode 100644
index 0000000..132e466
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListOutput.cs
@@ -0,0 +1,71 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
+{
+ ///
+ /// 开单品项明细记录输出
+ ///
+ public class BillingItemDetailListOutput
+ {
+ ///
+ /// 品项明细ID
+ ///
+ public string id { get; set; }
+
+ ///
+ /// 开单ID
+ ///
+ public string billingId { get; set; }
+
+ ///
+ /// 开单时间
+ ///
+ public DateTime? billingTime { get; set; }
+
+ ///
+ /// 营销活动名称
+ ///
+ public string activityName { get; set; }
+
+ ///
+ /// 会员名称
+ ///
+ public string memberName { get; set; }
+
+ ///
+ /// 会员手机
+ ///
+ public string memberPhone { get; set; }
+
+ ///
+ /// 品项名称
+ ///
+ public string itemName { get; set; }
+
+ ///
+ /// 品项类型(分类④-统计品项用)
+ ///
+ public string itemType { get; set; }
+
+ ///
+ /// 实付金额
+ ///
+ public decimal actualPrice { get; set; }
+
+ ///
+ /// 项目次数
+ ///
+ public decimal projectNumber { get; set; }
+
+ ///
+ /// 来源类型(购买/赠送/体验)
+ ///
+ public string sourceType { get; set; }
+
+ ///
+ /// 备注
+ ///
+ public string remark { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs
new file mode 100644
index 0000000..1d5f3a4
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs
@@ -0,0 +1,71 @@
+using NCC.Common.Filter;
+
+namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
+{
+ ///
+ /// 开单品项明细记录查询输入参数
+ ///
+ public class BillingItemDetailListQueryInput : PageInputBase
+ {
+ ///
+ /// 品项明细ID
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 开单ID
+ ///
+ public string BillingId { get; set; }
+
+ ///
+ /// 开单时间(开始)
+ ///
+ public string StartBillingTime { get; set; }
+
+ ///
+ /// 开单时间(结束)
+ ///
+ public string EndBillingTime { get; set; }
+
+ ///
+ /// 营销活动ID
+ ///
+ public string ActivityId { get; set; }
+
+ ///
+ /// 会员ID
+ ///
+ public string MemberId { get; set; }
+
+ ///
+ /// 会员名称(模糊查询)
+ ///
+ public string MemberName { get; set; }
+
+ ///
+ /// 会员手机号
+ ///
+ public string MemberPhone { get; set; }
+
+ ///
+ /// 品项ID
+ ///
+ public string ItemId { get; set; }
+
+ ///
+ /// 品项名称(模糊查询)
+ ///
+ public string ItemName { get; set; }
+
+ ///
+ /// 品项类型(分类④-统计品项用)
+ ///
+ public string ItemType { get; set; }
+
+ ///
+ /// 来源类型(购买/赠送/体验)
+ ///
+ public string SourceType { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/MemberItemInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/MemberItemInfoOutput.cs
new file mode 100644
index 0000000..645b424
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/MemberItemInfoOutput.cs
@@ -0,0 +1,164 @@
+using System;
+using System.Collections.Generic;
+
+namespace NCC.Extend.Entitys.Dto.LqKhxx
+{
+ ///
+ /// 会员品项信息输出
+ ///
+ public class MemberItemInfoOutput
+ {
+ ///
+ /// 会员ID
+ ///
+ public string MemberId { get; set; }
+
+ ///
+ /// 会员编号(档案号)
+ ///
+ public string MemberCode { get; set; }
+
+ ///
+ /// 会员名称
+ ///
+ public string MemberName { get; set; }
+
+ ///
+ /// 会员电话
+ ///
+ public string MemberPhone { get; set; }
+
+ ///
+ /// 所属门店ID
+ ///
+ public string BelongStoreId { get; set; }
+
+ ///
+ /// 所属门店名称
+ ///
+ public string BelongStoreName { get; set; }
+
+ ///
+ /// 开单信息列表
+ ///
+ public List BillingItems { get; set; } = new List();
+ }
+
+ ///
+ /// 开单信息
+ ///
+ public class BillingItemInfo
+ {
+ ///
+ /// 开单ID
+ ///
+ public string BillingId { get; set; }
+
+ ///
+ /// 开单时间
+ ///
+ public DateTime? BillingTime { get; set; }
+
+ ///
+ /// 开单门店ID
+ ///
+ public string BillingStoreId { get; set; }
+
+ ///
+ /// 开单门店名称
+ ///
+ public string BillingStoreName { get; set; }
+
+ ///
+ /// 开单人ID
+ ///
+ public string BillingUserId { get; set; }
+
+ ///
+ /// 开单人名称
+ ///
+ public string BillingUserName { get; set; }
+
+ ///
+ /// 购买品项列表
+ ///
+ public List PurchaseItems { get; set; } = new List();
+
+ ///
+ /// 购买品项总金额
+ ///
+ public decimal PurchaseItemsTotalAmount { get; set; }
+
+ ///
+ /// 赠送品项列表
+ ///
+ public List GiftItems { get; set; } = new List();
+
+ ///
+ /// 体验品项列表
+ ///
+ public List ExperienceItems { get; set; } = new List();
+
+ ///
+ /// 已消耗品项列表
+ ///
+ public List ConsumedItems { get; set; } = new List();
+
+ ///
+ /// 已消耗品项总金额
+ ///
+ public decimal ConsumedItemsTotalAmount { get; set; }
+
+ ///
+ /// 已退卡品项列表
+ ///
+ public List RefundedItems { get; set; } = new List();
+
+ ///
+ /// 已退卡品项总金额
+ ///
+ public decimal RefundedItemsTotalAmount { get; set; }
+
+ ///
+ /// 已储扣品项列表
+ ///
+ public List DeductedItems { get; set; } = new List();
+
+ ///
+ /// 已储扣品项总金额
+ ///
+ public decimal DeductedItemsTotalAmount { get; set; }
+ }
+
+ ///
+ /// 品项明细
+ ///
+ public class ItemDetail
+ {
+ ///
+ /// 品项ID
+ ///
+ public string ItemId { get; set; }
+
+ ///
+ /// 品项名称
+ ///
+ public string ItemName { get; set; }
+
+ ///
+ /// 品项价格
+ ///
+ public decimal ItemPrice { get; set; }
+
+ ///
+ /// 项目次数
+ ///
+ public decimal ProjectNumber { get; set; }
+
+ ///
+ /// 总金额
+ ///
+ public decimal TotalAmount { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/MemberItemInfoQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/MemberItemInfoQueryInput.cs
new file mode 100644
index 0000000..6f3b19d
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/MemberItemInfoQueryInput.cs
@@ -0,0 +1,47 @@
+using System;
+using NCC.Common.Filter;
+
+namespace NCC.Extend.Entitys.Dto.LqKhxx
+{
+ ///
+ /// 会员品项信息查询输入参数
+ ///
+ public class MemberItemInfoQueryInput : PageInputBase
+ {
+ ///
+ /// 会员ID
+ ///
+ public string MemberId { get; set; }
+
+ ///
+ /// 所属门店ID
+ ///
+ public string BelongStoreId { get; set; }
+
+ ///
+ /// 开单门店ID
+ ///
+ public string BillingStoreId { get; set; }
+
+ ///
+ /// 开单人ID
+ ///
+ public string BillingUserId { get; set; }
+
+ ///
+ /// 购买品项ID
+ ///
+ public string PurchaseItemId { get; set; }
+
+ ///
+ /// 赠送品项ID
+ ///
+ public string GiftItemId { get; set; }
+
+ ///
+ /// 体验品项ID
+ ///
+ public string ExperienceItemId { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs
index 9f0cdb0..19701a8 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs
@@ -1745,6 +1745,8 @@ namespace NCC.Extend
}
#endregion
+
+
#region 获取储值扣减金额统计
///
/// 获取储值扣减金额统计
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
index 2006ffc..27806f2 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
@@ -3211,5 +3211,218 @@ namespace NCC.Extend.LqKdKdjlb
}
}
#endregion
+
+ #region 获取开单品项明细记录列表
+ ///
+ /// 获取开单品项明细记录列表(分页)
+ ///
+ ///
+ /// 查询开单品项明细记录,支持多条件筛选和分页查询。采用先分页后关联的查询方式,确保分页准确性和查询性能。
+ ///
+ /// 示例请求:
+ /// ```json
+ /// {
+ /// "currentPage": 1,
+ /// "pageSize": 10,
+ /// "sidx": "yjsj",
+ /// "sort": "DESC",
+ /// "Id": "品项明细ID",
+ /// "BillingId": "开单ID",
+ /// "StartBillingTime": "2025-01-01",
+ /// "EndBillingTime": "2025-12-31",
+ /// "ActivityId": "营销活动ID",
+ /// "MemberId": "会员ID",
+ /// "MemberName": "会员名称",
+ /// "MemberPhone": "会员手机号",
+ /// "ItemId": "品项ID",
+ /// "ItemName": "品项名称",
+ /// "ItemType": "品项类型",
+ /// "SourceType": "来源类型"
+ /// }
+ /// ```
+ ///
+ /// 查询参数说明:
+ /// - currentPage: 当前页码(必填,从1开始)
+ /// - pageSize: 每页数量(必填)
+ /// - sidx: 排序字段(可选,默认:yjsj,支持:id、billingId、billingTime、itemName、actualPrice、projectNumber等)
+ /// - sort: 排序方式(可选,默认:DESC,支持:ASC、DESC)
+ /// - Id: 品项明细ID(可选,精确匹配)
+ /// - BillingId: 开单ID(可选,精确匹配)
+ /// - StartBillingTime: 开单时间开始(可选,格式:yyyy-MM-dd,与EndBillingTime同时使用)
+ /// - EndBillingTime: 开单时间结束(可选,格式:yyyy-MM-dd,与StartBillingTime同时使用)
+ /// - ActivityId: 营销活动ID(可选,精确匹配)
+ /// - MemberId: 会员ID(可选,精确匹配)
+ /// - MemberName: 会员名称(可选,模糊查询)
+ /// - MemberPhone: 会员手机号(可选,精确匹配)
+ /// - ItemId: 品项ID(可选,精确匹配)
+ /// - ItemName: 品项名称(可选,模糊查询)
+ /// - ItemType: 品项类型(可选,精确匹配,对应项目资料表的qt2字段)
+ /// - SourceType: 来源类型(可选,精确匹配,如:购买、赠送、体验)
+ ///
+ /// 返回数据结构:
+ /// ```json
+ /// {
+ /// "pagination": {
+ /// "pageIndex": 1,
+ /// "pageSize": 10,
+ /// "total": 100
+ /// },
+ /// "list": [
+ /// {
+ /// "id": "品项明细ID",
+ /// "billingId": "开单ID",
+ /// "billingTime": "2025-11-15T10:00:00",
+ /// "activityName": "营销活动名称",
+ /// "memberName": "会员名称",
+ /// "memberPhone": "会员手机号",
+ /// "itemName": "品项名称",
+ /// "itemType": "品项类型",
+ /// "actualPrice": 500.00,
+ /// "projectNumber": 5.0,
+ /// "sourceType": "购买",
+ /// "remark": "备注"
+ /// }
+ /// ]
+ /// }
+ /// ```
+ ///
+ /// 返回字段说明:
+ /// - id: 品项明细ID(主键)
+ /// - billingId: 开单ID(关联开单记录表)
+ /// - billingTime: 开单时间(业绩时间yjsj,DateTime格式)
+ /// - activityName: 营销活动名称(关联营销活动表)
+ /// - memberName: 会员名称(关联会员表)
+ /// - memberPhone: 会员手机号(关联会员表)
+ /// - itemName: 品项名称(品项明细表字段)
+ /// - itemType: 品项类型(关联项目资料表的qt2字段)
+ /// - actualPrice: 实付金额(decimal类型)
+ /// - projectNumber: 项目次数(decimal类型,支持小数)
+ /// - sourceType: 来源类型(字符串,如:购买、赠送、体验)
+ /// - remark: 备注(字符串)
+ ///
+ /// 查询参数
+ /// 开单品项明细记录列表(分页)
+ /// 查询成功,返回开单品项明细记录列表
+ /// 参数错误,如页码或页大小无效
+ /// 服务器错误,查询过程中发生异常
+ [HttpGet("billing-item-detail-list")]
+ public async Task GetBillingItemDetailList([FromQuery] BillingItemDetailListQueryInput input)
+ {
+ try
+ {
+ var sidx = input.sidx == null ? "yjsj" : input.sidx;
+ var sort = string.IsNullOrEmpty(input.sort) ? "DESC" : input.sort;
+
+ // 处理开单时间范围
+ List queryBillingTime = null;
+ DateTime? startBillingTime = null;
+ DateTime? endBillingTime = null;
+ if (!string.IsNullOrEmpty(input.StartBillingTime) && !string.IsNullOrEmpty(input.EndBillingTime))
+ {
+ queryBillingTime = new List { input.StartBillingTime, input.EndBillingTime };
+ startBillingTime = Ext.GetDateTime(queryBillingTime.First());
+ endBillingTime = Ext.GetDateTime(queryBillingTime.Last());
+ }
+
+ // 优化查询:先分页查询主表,再批量查询关联数据,避免子查询性能问题
+ // 1. 先构建基础查询条件
+ var baseQuery = _db.Queryable()
+ .Where(pxmx => pxmx.IsEffective == StatusEnum.有效.GetHashCode())
+ .WhereIF(!string.IsNullOrEmpty(input.Id), pxmx => pxmx.Id == input.Id)
+ .WhereIF(!string.IsNullOrEmpty(input.BillingId), pxmx => pxmx.Glkdbh == input.BillingId)
+ .WhereIF(queryBillingTime != null && startBillingTime.HasValue, pxmx => pxmx.Yjsj >= new DateTime(startBillingTime.Value.Year, startBillingTime.Value.Month, startBillingTime.Value.Day, 0, 0, 0))
+ .WhereIF(queryBillingTime != null && endBillingTime.HasValue, pxmx => pxmx.Yjsj <= new DateTime(endBillingTime.Value.Year, endBillingTime.Value.Month, endBillingTime.Value.Day, 23, 59, 59))
+ .WhereIF(!string.IsNullOrEmpty(input.ActivityId), pxmx => pxmx.ActivityId == input.ActivityId)
+ .WhereIF(!string.IsNullOrEmpty(input.MemberId), pxmx => pxmx.MemberId == input.MemberId)
+ .WhereIF(!string.IsNullOrEmpty(input.ItemId), pxmx => pxmx.Px == input.ItemId)
+ .WhereIF(!string.IsNullOrEmpty(input.ItemName), pxmx => pxmx.Pxmc != null && pxmx.Pxmc.Contains(input.ItemName))
+ .WhereIF(!string.IsNullOrEmpty(input.SourceType), pxmx => pxmx.SourceType == input.SourceType);
+
+ // 2. 通过 EXISTS 子查询筛选关联字段(在分页前筛选,确保分页准确)
+ baseQuery = baseQuery
+ .WhereIF(!string.IsNullOrEmpty(input.MemberName), pxmx =>
+ SqlFunc.Subqueryable().Where(x => x.Id == pxmx.MemberId && x.Khmc != null && x.Khmc.Contains(input.MemberName)).Any())
+ .WhereIF(!string.IsNullOrEmpty(input.MemberPhone), pxmx =>
+ SqlFunc.Subqueryable().Where(x => x.Id == pxmx.MemberId && x.Sjh == input.MemberPhone).Any())
+ .WhereIF(!string.IsNullOrEmpty(input.ItemType), pxmx =>
+ SqlFunc.Subqueryable().Where(x => x.Id == pxmx.Px && x.Fl4 == input.ItemType).Any());
+
+ // 3. 先分页查询主表数据(查询实体类,提高性能)
+ var pagedData = await baseQuery
+ .OrderBy(sidx + " " + sort)
+ .ToPagedListAsync(input.currentPage, input.pageSize);
+
+ // 4. 批量查询关联数据
+ var itemIds = pagedData.list.Select(x => x.Id).ToList();
+ var memberIds = pagedData.list.Where(x => !string.IsNullOrEmpty(x.MemberId)).Select(x => x.MemberId).Distinct().ToList();
+ var activityIds = pagedData.list.Where(x => !string.IsNullOrEmpty(x.ActivityId)).Select(x => x.ActivityId).Distinct().ToList();
+ var projectIds = pagedData.list.Where(x => !string.IsNullOrEmpty(x.Px)).Select(x => x.Px).Distinct().ToList();
+
+ // 批量查询会员信息
+ var memberDict = new Dictionary();
+ if (memberIds.Any())
+ {
+ var members = await _db.Queryable()
+ .Where(x => memberIds.Contains(x.Id))
+ .Select(x => new { x.Id, x.Khmc, x.Sjh })
+ .ToListAsync();
+ memberDict = members.ToDictionary(x => x.Id, x => (x.Khmc ?? "", x.Sjh ?? ""));
+ }
+
+ // 批量查询活动信息
+ var activityDict = new Dictionary();
+ if (activityIds.Any())
+ {
+ var activities = await _db.Queryable()
+ .Where(x => activityIds.Contains(x.Id))
+ .Select(x => new { x.Id, x.ActivityName })
+ .ToListAsync();
+ activityDict = activities.ToDictionary(x => x.Id, x => x.ActivityName ?? "");
+ }
+
+ // 批量查询项目资料
+ var projectDict = new Dictionary();
+ if (projectIds.Any())
+ {
+ var projects = await _db.Queryable()
+ .Where(x => projectIds.Contains(x.Id))
+ .Select(x => new { x.Id, x.Qt2 })
+ .ToListAsync();
+ projectDict = projects.ToDictionary(x => x.Id, x => x.Qt2 ?? "");
+ }
+
+ // 5. 组装返回数据
+ var resultList = pagedData.list.Select(pxmx => new BillingItemDetailListOutput
+ {
+ id = pxmx.Id,
+ billingId = pxmx.Glkdbh,
+ billingTime = pxmx.Yjsj,
+ activityName = pxmx.ActivityId != null && activityDict.ContainsKey(pxmx.ActivityId) ? activityDict[pxmx.ActivityId] : "",
+ memberName = pxmx.MemberId != null && memberDict.ContainsKey(pxmx.MemberId) ? memberDict[pxmx.MemberId].Name : "",
+ memberPhone = pxmx.MemberId != null && memberDict.ContainsKey(pxmx.MemberId) ? memberDict[pxmx.MemberId].Phone : "",
+ itemName = pxmx.Pxmc,
+ itemType = pxmx.Px != null && projectDict.ContainsKey(pxmx.Px) ? projectDict[pxmx.Px] : "",
+ actualPrice = pxmx.ActualPrice,
+ projectNumber = pxmx.ProjectNumber,
+ sourceType = pxmx.SourceType,
+ remark = pxmx.Remark
+ }).ToList();
+
+ // 6. 返回分页结果
+ var result = new SqlSugarPagedList
+ {
+ list = resultList,
+ pagination = pagedData.pagination
+ };
+
+ return PageResult.SqlSugarPageResult(result);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, $"获取开单品项明细记录列表失败: {ex.ToString()}");
+ throw NCCException.Oh(ErrorCode.COM1005, $"获取开单品项明细记录列表失败: {ex.Message}");
+ }
+ }
+ #endregion
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
index e7b3951..8f431f7 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
@@ -776,5 +776,676 @@ namespace NCC.Extend.LqKhxx
}
#endregion
+ #region 获取会员品项信息
+ ///
+ /// 获取所有会员的品项信息(分页)
+ ///
+ ///
+ /// 查询所有会员的品项信息,包括购买品项、赠送品项、体验品项、已消耗品项、已退卡品项、已储扣品项
+ ///
+ /// 示例请求:
+ /// ```json
+ /// {
+ /// "currentPage": 1,
+ /// "pageSize": 10,
+ /// "MemberId": "会员ID",
+ /// "BelongStoreId": "所属门店ID",
+ /// "BillingStoreId": "开单门店ID",
+ /// "BillingUserId": "开单人ID",
+ /// "PurchaseItemId": "购买品项ID",
+ /// "GiftItemId": "赠送品项ID",
+ /// "ExperienceItemId": "体验品项ID"
+ /// }
+ /// ```
+ ///
+ /// 参数说明:
+ /// - currentPage: 当前页码(必填)
+ /// - pageSize: 每页数量(必填)
+ /// - MemberId: 会员ID(可选)
+ /// - BelongStoreId: 所属门店ID(可选)
+ /// - BillingStoreId: 开单门店ID(可选)
+ /// - BillingUserId: 开单人ID(可选)
+ /// - PurchaseItemId: 购买品项ID(可选)
+ /// - GiftItemId: 赠送品项ID(可选)
+ /// - ExperienceItemId: 体验品项ID(可选)
+ ///
+ /// 返回数据结构说明:
+ /// ```json
+ /// {
+ /// "pagination": {
+ /// "pageIndex": 1,
+ /// "pageSize": 10,
+ /// "total": 100
+ /// },
+ /// "list": [
+ /// {
+ /// "memberId": "会员ID",
+ /// "memberCode": "会员编号(档案号)",
+ /// "memberName": "会员名称",
+ /// "memberPhone": "会员电话",
+ /// "belongStoreId": "所属门店ID",
+ /// "belongStoreName": "所属门店名称",
+ /// "billingItems": [
+ /// {
+ /// "billingId": "开单ID",
+ /// "billingTime": "2025-11-15T10:00:00",
+ /// "billingStoreId": "开单门店ID",
+ /// "billingStoreName": "开单门店名称",
+ /// "billingUserId": "开单人ID",
+ /// "billingUserName": "开单人名称",
+ /// "purchaseItems": [
+ /// {
+ /// "itemId": "品项ID",
+ /// "itemName": "品项名称",
+ /// "itemPrice": 100.00,
+ /// "projectNumber": 5.0,
+ /// "totalAmount": 500.00
+ /// }
+ /// ],
+ /// "purchaseItemsTotalAmount": 500.00,
+ /// "giftItems": [
+ /// {
+ /// "itemId": "品项ID",
+ /// "itemName": "品项名称",
+ /// "itemPrice": 50.00,
+ /// "projectNumber": 2.0,
+ /// "totalAmount": 100.00
+ /// }
+ /// ],
+ /// "experienceItems": [
+ /// {
+ /// "itemId": "品项ID",
+ /// "itemName": "品项名称",
+ /// "itemPrice": 30.00,
+ /// "projectNumber": 1.0,
+ /// "totalAmount": 30.00
+ /// }
+ /// ],
+ /// "consumedItems": [
+ /// {
+ /// "itemId": "品项ID",
+ /// "itemName": "品项名称",
+ /// "itemPrice": 100.00,
+ /// "projectNumber": 2.0,
+ /// "totalAmount": 200.00
+ /// }
+ /// ],
+ /// "consumedItemsTotalAmount": 200.00,
+ /// "refundedItems": [
+ /// {
+ /// "itemId": "品项ID",
+ /// "itemName": "品项名称",
+ /// "itemPrice": 100.00,
+ /// "projectNumber": 1.0,
+ /// "totalAmount": 100.00
+ /// }
+ /// ],
+ /// "refundedItemsTotalAmount": 100.00,
+ /// "deductedItems": [
+ /// {
+ /// "itemId": "品项ID",
+ /// "itemName": "品项名称",
+ /// "itemPrice": 100.00,
+ /// "projectNumber": 1.0,
+ /// "totalAmount": 100.00
+ /// }
+ /// ],
+ /// "deductedItemsTotalAmount": 100.00
+ /// }
+ /// ]
+ /// }
+ /// ]
+ /// }
+ /// ```
+ ///
+ /// 返回字段说明:
+ ///
+ /// **分页信息 (pagination)**:
+ /// - pageIndex: 当前页码
+ /// - pageSize: 每页数量
+ /// - total: 总记录数
+ ///
+ /// **会员信息 (list[].memberInfo)**:
+ /// - memberId: 会员ID
+ /// - memberCode: 会员编号(档案号)
+ /// - memberName: 会员名称
+ /// - memberPhone: 会员电话
+ /// - belongStoreId: 所属门店ID
+ /// - belongStoreName: 所属门店名称
+ ///
+ /// **开单信息 (list[].billingItems[])**:
+ /// - billingId: 开单ID
+ /// - billingTime: 开单时间(DateTime格式)
+ /// - billingStoreId: 开单门店ID
+ /// - billingStoreName: 开单门店名称
+ /// - billingUserId: 开单人ID
+ /// - billingUserName: 开单人名称
+ ///
+ /// **品项信息 (list[].billingItems[].*Items[])**:
+ /// - purchaseItems: 购买品项列表
+ /// - purchaseItemsTotalAmount: 购买品项总金额
+ /// - giftItems: 赠送品项列表
+ /// - experienceItems: 体验品项列表
+ /// - consumedItems: 已消耗品项列表
+ /// - consumedItemsTotalAmount: 已消耗品项总金额
+ /// - refundedItems: 已退卡品项列表
+ /// - refundedItemsTotalAmount: 已退卡品项总金额
+ /// - deductedItems: 已储扣品项列表
+ /// - deductedItemsTotalAmount: 已储扣品项总金额
+ ///
+ /// **品项明细 (ItemDetail)**:
+ /// - itemId: 品项ID
+ /// - itemName: 品项名称
+ /// - itemPrice: 品项单价
+ /// - projectNumber: 项目次数(支持小数)
+ /// - totalAmount: 总金额(单价 × 次数)
+ ///
+ /// 查询参数
+ /// 会员品项信息列表(分页)
+ /// 查询成功,返回会员品项信息列表
+ /// 参数错误,如页码或页大小无效
+ /// 服务器错误,查询过程中发生异常
+ [HttpPost("get-member-item-info")]
+ public async Task GetMemberItemInfo([FromBody] MemberItemInfoQueryInput input)
+ {
+ try
+ {
+ // 1. 构建会员查询条件
+ var memberQuery = _db.Queryable();
+
+ // 筛选条件
+ if (!string.IsNullOrEmpty(input.MemberId))
+ {
+ memberQuery = memberQuery.Where(x => x.Id == input.MemberId);
+ }
+
+ if (!string.IsNullOrEmpty(input.BelongStoreId))
+ {
+ memberQuery = memberQuery.Where(x => x.Gsmd == input.BelongStoreId);
+ }
+
+ // 如果指定了开单门店、开单人、品项ID等条件,需要通过开单表进行筛选
+ if (!string.IsNullOrEmpty(input.BillingStoreId) ||
+ !string.IsNullOrEmpty(input.BillingUserId) ||
+ !string.IsNullOrEmpty(input.PurchaseItemId) ||
+ !string.IsNullOrEmpty(input.GiftItemId) ||
+ !string.IsNullOrEmpty(input.ExperienceItemId))
+ {
+ // 先查询符合条件的开单记录,获取会员ID列表
+ var billingQuery = _db.Queryable()
+ .Where(x => x.IsEffective == StatusEnum.有效.GetHashCode());
+
+ if (!string.IsNullOrEmpty(input.BillingStoreId))
+ {
+ billingQuery = billingQuery.Where(x => x.Djmd == input.BillingStoreId);
+ }
+
+ if (!string.IsNullOrEmpty(input.BillingUserId))
+ {
+ billingQuery = billingQuery.Where(x => x.CreateUser == input.BillingUserId);
+ }
+
+ // 如果指定了品项ID,需要通过品项明细表进行筛选
+ if (!string.IsNullOrEmpty(input.PurchaseItemId) ||
+ !string.IsNullOrEmpty(input.GiftItemId) ||
+ !string.IsNullOrEmpty(input.ExperienceItemId))
+ {
+ var itemQuery = _db.Queryable()
+ .Where(x => x.IsEffective == StatusEnum.有效.GetHashCode());
+
+ if (!string.IsNullOrEmpty(input.PurchaseItemId))
+ {
+ itemQuery = itemQuery.Where(x => x.Px == input.PurchaseItemId && x.SourceType == "购买");
+ }
+
+ if (!string.IsNullOrEmpty(input.GiftItemId))
+ {
+ itemQuery = itemQuery.Where(x => x.Px == input.GiftItemId && x.SourceType == "赠送");
+ }
+
+ if (!string.IsNullOrEmpty(input.ExperienceItemId))
+ {
+ itemQuery = itemQuery.Where(x => x.Px == input.ExperienceItemId && x.SourceType == "体验");
+ }
+
+ var itemBillingIds = await itemQuery.Select(x => x.Glkdbh).Distinct().ToListAsync();
+ if (itemBillingIds != null && itemBillingIds.Any())
+ {
+ billingQuery = billingQuery.Where(x => itemBillingIds.Contains(x.Id));
+ }
+ else
+ {
+ // 如果没有匹配的品项记录,返回空结果
+ return PageResult.SqlSugarPageResult(new SqlSugarPagedList
+ {
+ list = new List(),
+ pagination = new PagedModel
+ {
+ PageIndex = input.currentPage,
+ PageSize = input.pageSize,
+ Total = 0
+ }
+ });
+ }
+ }
+
+ var memberIds = await billingQuery.Select(x => x.Kdhy).Distinct().ToListAsync();
+ if (memberIds != null && memberIds.Any())
+ {
+ memberQuery = memberQuery.Where(x => memberIds.Contains(x.Id));
+ }
+ else
+ {
+ // 如果没有匹配的开单记录,返回空结果
+ return PageResult.SqlSugarPageResult(new SqlSugarPagedList
+ {
+ list = new List(),
+ pagination = new PagedModel
+ {
+ PageIndex = input.currentPage,
+ PageSize = input.pageSize,
+ Total = 0
+ }
+ });
+ }
+ }
+
+ // 2. 分页查询会员列表
+ var totalCount = await memberQuery.CountAsync();
+ var skipCount = (input.currentPage - 1) * input.pageSize;
+ var memberList = await memberQuery
+ .OrderBy(x => x.Id)
+ .Skip(skipCount)
+ .Take(input.pageSize)
+ .Select(x => new
+ {
+ x.Id,
+ x.Dah,
+ x.Khmc,
+ x.Sjh,
+ x.Gsmd
+ })
+ .ToListAsync();
+
+ var memberData = new SqlSugarPagedList
+ {
+ list = memberList.Cast().ToList(),
+ pagination = new PagedModel
+ {
+ PageIndex = input.currentPage,
+ PageSize = input.pageSize,
+ Total = totalCount
+ }
+ };
+
+ if (memberList == null || !memberList.Any())
+ {
+ return PageResult.SqlSugarPageResult(new SqlSugarPagedList
+ {
+ list = new List(),
+ pagination = new PagedModel
+ {
+ PageIndex = input.currentPage,
+ PageSize = input.pageSize,
+ Total = totalCount
+ }
+ });
+ }
+
+ var memberIdsList = memberList.Select(x => x.Id).ToList();
+
+ // 3. 批量查询会员的开单记录
+ var billingRecords = await _db.Queryable()
+ .Where(x => memberIdsList.Contains(x.Kdhy) && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .Select(x => new
+ {
+ x.Id,
+ x.Kdhy,
+ x.Kdrq,
+ x.Djmd,
+ x.CreateUser
+ })
+ .ToListAsync();
+
+ var billingIds = billingRecords.Select(x => x.Id).ToList();
+
+ // 4. 批量查询开单的品项明细
+ var itemDetails = new List();
+ if (billingIds.Any())
+ {
+ var itemDetailsData = await _db.Queryable()
+ .Where(x => billingIds.Contains(x.Glkdbh) && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .Select(x => new
+ {
+ x.Id,
+ x.Glkdbh,
+ x.Px,
+ x.Pxmc,
+ x.Pxjg,
+ x.SourceType,
+ x.ProjectNumber,
+ x.TotalPrice
+ })
+ .ToListAsync();
+ itemDetails = itemDetailsData.Cast().ToList();
+ }
+
+ var itemDetailIds = itemDetails.Select(x => (string)x.Id).ToList();
+
+ // 5. 批量查询消耗品项
+ var consumedItems = new List();
+ if (itemDetailIds.Any())
+ {
+ var consumedItemsData = await _db.Queryable()
+ .Where(x => itemDetailIds.Contains(x.BillingItemId) && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .Select(x => new
+ {
+ x.BillingItemId,
+ x.Px,
+ x.Pxmc,
+ x.Pxjg,
+ x.ProjectNumber,
+ x.TotalPrice
+ })
+ .ToListAsync();
+ consumedItems = consumedItemsData.Cast().ToList();
+ }
+
+ // 6. 批量查询退卡品项
+ var refundedItems = new List();
+ if (itemDetailIds.Any())
+ {
+ var refundedItemsData = await _db.Queryable()
+ .Where(x => itemDetailIds.Contains(x.BillingItemId) && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .Select(x => new
+ {
+ x.BillingItemId,
+ x.Px,
+ x.Pxmc,
+ x.Pxjg,
+ x.ProjectNumber,
+ x.Tkje
+ })
+ .ToListAsync();
+ refundedItems = refundedItemsData.Cast().ToList();
+ }
+
+ // 7. 批量查询储扣品项
+ var deductedItems = new List();
+ if (billingIds.Any())
+ {
+ var deductedItemsData = await _db.Queryable()
+ .Where(x => billingIds.Contains(x.BillingId) && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .Select(x => new
+ {
+ x.BillingId,
+ x.ItemId,
+ x.ItemName,
+ x.UnitPrice,
+ x.ProjectNumber,
+ x.Amount
+ })
+ .ToListAsync();
+ deductedItems = deductedItemsData.Cast().ToList();
+ }
+
+ // 8. 批量查询门店信息
+ var storeIds = new List();
+ if (memberList != null && memberList.Any())
+ {
+ storeIds.AddRange(memberList.Select(x => x.Gsmd).Where(x => !string.IsNullOrEmpty(x)));
+ }
+ if (billingRecords != null && billingRecords.Any())
+ {
+ storeIds.AddRange(billingRecords.Select(x => x.Djmd).Where(x => !string.IsNullOrEmpty(x)));
+ }
+ storeIds = storeIds.Distinct().ToList();
+
+ var stores = new Dictionary();
+ if (storeIds.Any())
+ {
+ var storeList = await _db.Queryable()
+ .Where(x => storeIds.Contains(x.Id))
+ .Select(x => new { x.Id, x.Dm })
+ .ToListAsync();
+
+ stores = storeList.ToDictionary(x => x.Id, x => x.Dm ?? "");
+ }
+
+ // 9. 批量查询用户信息
+ var userIds = new List();
+ if (billingRecords != null && billingRecords.Any())
+ {
+ userIds = billingRecords.Select(x => x.CreateUser)
+ .Where(x => !string.IsNullOrEmpty(x))
+ .Distinct()
+ .ToList();
+ }
+
+ var users = new Dictionary();
+ if (userIds.Any())
+ {
+ var userList = await _db.Queryable()
+ .Where(x => userIds.Contains(x.Id))
+ .Select(x => new { x.Id, x.RealName })
+ .ToListAsync();
+
+ users = userList.ToDictionary(x => x.Id, x => x.RealName ?? "");
+ }
+
+ // 10. 组装数据
+ var result = new List();
+
+ foreach (var member in memberList)
+ {
+ var memberOutput = new MemberItemInfoOutput
+ {
+ MemberId = member.Id,
+ MemberCode = member.Dah ?? "",
+ MemberName = member.Khmc ?? "",
+ MemberPhone = member.Sjh ?? "",
+ BelongStoreId = member.Gsmd ?? "",
+ BelongStoreName = stores.ContainsKey(member.Gsmd ?? "") ? stores[member.Gsmd] : ""
+ };
+
+ // 获取该会员的所有开单
+ var memberBillings = billingRecords.Where(x => x.Kdhy == member.Id).ToList();
+
+ foreach (var billing in memberBillings)
+ {
+ var billingItem = new BillingItemInfo
+ {
+ BillingId = billing.Id,
+ BillingTime = billing.Kdrq,
+ BillingStoreId = billing.Djmd ?? "",
+ BillingStoreName = stores.ContainsKey(billing.Djmd ?? "") ? stores[billing.Djmd] : "",
+ BillingUserId = billing.CreateUser ?? "",
+ BillingUserName = users.ContainsKey(billing.CreateUser ?? "") ? users[billing.CreateUser] : ""
+ };
+
+ // 获取该开单的所有品项明细
+ var billingItemDetails = itemDetails.Where(x =>
+ {
+ try
+ {
+ return x.Glkdbh?.ToString() == billing.Id;
+ }
+ catch
+ {
+ return false;
+ }
+ }).ToList();
+
+ // 分类品项
+ foreach (var item in billingItemDetails)
+ {
+ try
+ {
+ var itemDetail = new ItemDetail
+ {
+ ItemId = item.Px?.ToString() ?? "",
+ ItemName = item.Pxmc?.ToString() ?? "",
+ ItemPrice = Convert.ToDecimal(item.Pxjg ?? 0),
+ ProjectNumber = Convert.ToDecimal(item.ProjectNumber ?? 0),
+ TotalAmount = Convert.ToDecimal(item.TotalPrice ?? 0)
+ };
+
+ var sourceType = item.SourceType?.ToString() ?? "";
+ if (sourceType == "购买")
+ {
+ billingItem.PurchaseItems.Add(itemDetail);
+ billingItem.PurchaseItemsTotalAmount += itemDetail.TotalAmount;
+ }
+ else if (sourceType == "赠送")
+ {
+ billingItem.GiftItems.Add(itemDetail);
+ }
+ else if (sourceType == "体验")
+ {
+ billingItem.ExperienceItems.Add(itemDetail);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "处理品项明细时出错,开单ID:{BillingId}", billing.Id);
+ }
+ }
+
+ // 获取消耗品项
+ var billingItemIds = billingItemDetails.Select(x =>
+ {
+ try
+ {
+ return x.Id?.ToString() ?? "";
+ }
+ catch
+ {
+ return "";
+ }
+ }).Where(x => !string.IsNullOrEmpty(x)).ToList();
+
+ var consumed = consumedItems.Where(x =>
+ {
+ try
+ {
+ return billingItemIds.Contains(x.BillingItemId?.ToString() ?? "");
+ }
+ catch
+ {
+ return false;
+ }
+ }).ToList();
+
+ foreach (var consumedItem in consumed)
+ {
+ try
+ {
+ billingItem.ConsumedItems.Add(new ItemDetail
+ {
+ ItemId = consumedItem.Px?.ToString() ?? "",
+ ItemName = consumedItem.Pxmc?.ToString() ?? "",
+ ItemPrice = Convert.ToDecimal(consumedItem.Pxjg ?? 0),
+ ProjectNumber = Convert.ToDecimal(consumedItem.ProjectNumber ?? 0),
+ TotalAmount = Convert.ToDecimal(consumedItem.TotalPrice ?? 0)
+ });
+ billingItem.ConsumedItemsTotalAmount += Convert.ToDecimal(consumedItem.TotalPrice ?? 0);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "处理消耗品项时出错");
+ }
+ }
+
+ // 获取退卡品项
+ var refunded = refundedItems.Where(x =>
+ {
+ try
+ {
+ return billingItemIds.Contains(x.BillingItemId?.ToString() ?? "");
+ }
+ catch
+ {
+ return false;
+ }
+ }).ToList();
+
+ foreach (var refundedItem in refunded)
+ {
+ try
+ {
+ billingItem.RefundedItems.Add(new ItemDetail
+ {
+ ItemId = refundedItem.Px?.ToString() ?? "",
+ ItemName = refundedItem.Pxmc?.ToString() ?? "",
+ ItemPrice = Convert.ToDecimal(refundedItem.Pxjg ?? 0),
+ ProjectNumber = Convert.ToDecimal(refundedItem.ProjectNumber ?? 0),
+ TotalAmount = Convert.ToDecimal(refundedItem.Tkje ?? 0)
+ });
+ billingItem.RefundedItemsTotalAmount += Convert.ToDecimal(refundedItem.Tkje ?? 0);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "处理退卡品项时出错");
+ }
+ }
+
+ // 获取储扣品项
+ var deducted = deductedItems.Where(x =>
+ {
+ try
+ {
+ return x.BillingId?.ToString() == billing.Id;
+ }
+ catch
+ {
+ return false;
+ }
+ }).ToList();
+
+ foreach (var deductedItem in deducted)
+ {
+ try
+ {
+ billingItem.DeductedItems.Add(new ItemDetail
+ {
+ ItemId = deductedItem.ItemId?.ToString() ?? "",
+ ItemName = deductedItem.ItemName?.ToString() ?? "",
+ ItemPrice = Convert.ToDecimal(deductedItem.UnitPrice ?? 0),
+ ProjectNumber = Convert.ToDecimal(deductedItem.ProjectNumber ?? 0),
+ TotalAmount = Convert.ToDecimal(deductedItem.Amount ?? 0)
+ });
+ billingItem.DeductedItemsTotalAmount += Convert.ToDecimal(deductedItem.Amount ?? 0);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "处理储扣品项时出错");
+ }
+ }
+
+ memberOutput.BillingItems.Add(billingItem);
+ }
+
+ result.Add(memberOutput);
+ }
+
+ return PageResult.SqlSugarPageResult(new SqlSugarPagedList
+ {
+ list = result,
+ pagination = new PagedModel
+ {
+ PageIndex = input.currentPage,
+ PageSize = input.pageSize,
+ Total = totalCount
+ }
+ });
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "查询会员品项信息失败,异常详情:{ExceptionDetail}", ex.ToString());
+ throw NCCException.Oh(ErrorCode.COM1005, $"查询会员品项信息失败: {ex.Message}");
+ }
+ }
+ #endregion
+
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
index 25a252b..3870d34 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
@@ -971,6 +971,8 @@ namespace NCC.Extend.LqXhHyhk
{
memberInfo.Khlx = MemberTypeEnum.新客.GetHashCode().ToString();
}
+ //保存会员信息
+ await _db.Updateable(memberInfo).ExecuteCommandAsync();
// 新增会员耗卡记录
var newEntity = await _db.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteReturnEntityAsync();
// 收集所有需要插入的实体,然后批量插入
@@ -1265,6 +1267,15 @@ namespace NCC.Extend.LqXhHyhk
//更新会员耗卡记录
await _db.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
+ var memberInfo = await _db.Queryable().Where(w => w.Id == entity.Hy).FirstAsync();
+ //如果会员类型是线索,那么就更新为新客
+ if (memberInfo.Khlx == MemberTypeEnum.线索.GetHashCode().ToString())
+ {
+ memberInfo.Khlx = MemberTypeEnum.新客.GetHashCode().ToString();
+ }
+ //保存会员信息
+ await _db.Updateable(memberInfo).ExecuteCommandAsync();
+
//清空原有数据
await _db.Deleteable().Where(u => u.Glkdbh == id).ExecuteCommandAsync();
await _db.Deleteable().Where(u => u.Glkdbh == id).ExecuteCommandAsync();
diff --git a/sql/更新潜客为新客.sql b/sql/更新潜客为新客.sql
new file mode 100644
index 0000000..372112d
--- /dev/null
+++ b/sql/更新潜客为新客.sql
@@ -0,0 +1,54 @@
+-- ============================================
+-- 更新会员类型:将存在耗卡记录的潜客(0)更新为新客(1)
+-- ============================================
+--
+-- 功能说明:
+-- 1. 查找会员类型为 0(潜客/线索)的会员
+-- 2. 如果该会员存在有效的耗卡记录(lq_xh_hyhk 表中有记录且 F_IsEffective = 1)
+-- 3. 将该会员的类型更新为 1(新客)
+--
+-- 执行前建议:
+-- 1. 先执行查询语句查看会更新多少条记录
+-- 2. 确认无误后再执行更新语句
+-- ============================================
+
+-- 1. 查询语句:查看将要更新的会员数量和信息
+SELECT
+ kh.F_Id AS 会员ID,
+ kh.khmc AS 会员名称,
+ kh.sjh AS 手机号,
+ kh.khlx AS 当前类型,
+ COUNT(hyhk.F_Id) AS 耗卡记录数
+FROM lq_khxx kh
+INNER JOIN lq_xh_hyhk hyhk ON kh.F_Id = hyhk.hy
+WHERE kh.khlx = '0' -- 会员类型为 0(潜客/线索)
+ AND hyhk.F_IsEffective = 1 -- 耗卡记录有效
+GROUP BY kh.F_Id, kh.khmc, kh.sjh, kh.khlx;
+
+-- 2. 更新语句:将存在耗卡记录的潜客更新为新客
+UPDATE lq_khxx kh
+SET kh.khlx = '1' -- 更新为新客(1)
+WHERE kh.khlx = '0' -- 会员类型为 0(潜客/线索)
+ AND EXISTS (
+ -- 确保至少有一条有效的耗卡记录
+ SELECT 1
+ FROM lq_xh_hyhk hyhk
+ WHERE hyhk.hy = kh.F_Id
+ AND hyhk.F_IsEffective = 1
+ LIMIT 1
+ );
+
+-- 3. 验证语句:查看更新后的结果
+SELECT
+ kh.F_Id AS 会员ID,
+ kh.khmc AS 会员名称,
+ kh.sjh AS 手机号,
+ kh.khlx AS 更新后类型,
+ COUNT(hyhk.F_Id) AS 耗卡记录数
+FROM lq_khxx kh
+INNER JOIN lq_xh_hyhk hyhk ON kh.F_Id = hyhk.hy
+WHERE kh.khlx = '1' -- 会员类型为 1(新客)
+ AND hyhk.F_IsEffective = 1 -- 耗卡记录有效
+GROUP BY kh.F_Id, kh.khmc, kh.sjh, kh.khlx
+HAVING COUNT(hyhk.F_Id) > 0;
+