diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoListOutput.cs
index bce12b3..27b9c2b 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoListOutput.cs
@@ -16,12 +16,6 @@ namespace NCC.Extend.Entitys.Dto.LqKdDeductinfo
/// 扣减类型
///
public string DeductType { get; set; }
-
- ///
- /// 扣减类型名称
- ///
- public string DeductTypeName { get; set; }
-
///
/// 扣减关联ID
///
@@ -61,5 +55,45 @@ namespace NCC.Extend.Entitys.Dto.LqKdDeductinfo
/// 创建时间
///
public DateTime? CreateTime { get; set; }
+
+ ///
+ /// 项目数量
+ ///
+ public decimal? ProjectNumber { get; set; }
+
+ ///
+ /// 品项分类
+ ///
+ public string ItemCategory { get; set; }
+
+ ///
+ /// 开单日期
+ ///
+ public DateTime? BillingDate { get; set; }
+
+ ///
+ /// 客户ID
+ ///
+ public string MemberId { get; set; }
+
+ ///
+ /// 客户名称
+ ///
+ public string MemberName { get; set; }
+
+ ///
+ /// 客户手机号
+ ///
+ public string MemberPhone { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 门店名称
+ ///
+ public string StoreName { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoListQueryInput.cs
index 9f9dc60..75dd9ba 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoListQueryInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoListQueryInput.cs
@@ -1,11 +1,12 @@
using System;
+using NCC.Common.Filter;
namespace NCC.Extend.Entitys.Dto.LqKdDeductinfo
{
///
/// 开单扣减信息列表查询输入
///
- public class LqKdDeductinfoListQueryInput
+ public class LqKdDeductinfoListQueryInput : PageInputBase
{
///
/// 扣减类型
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbInfoOutput.cs
index 53c5625..b1f3b82 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbInfoOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbInfoOutput.cs
@@ -182,6 +182,21 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
///
public DateTime? appointmentTime { get; set; }
+
+ ///
+ /// 升生美
+ ///
+ public string upgradeLifeBeauty { get; set; }
+
+ ///
+ /// 升科美
+ ///
+ public string upgradeTechBeauty { get; set; }
+
+ ///
+ /// 升医美
+ ///
+ public string upgradeMedicalBeauty { get; set; }
///
/// 健康师业绩
///
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListOutput.cs
index 9927f26..7ad3605 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListOutput.cs
@@ -171,6 +171,21 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
/// 预约记录ID
///
public string appointmentId { get; set; }
+
+ ///
+ /// 是否升医美
+ ///
+ public string upgradeLifeBeauty { get; set; }
+
+ ///
+ /// 是否升科美
+ ///
+ public string upgradeTechBeauty { get; set; }
+
+ ///
+ /// 是否升生美
+ ///
+ public string upgradeMedicalBeauty { get; set; }
///
/// 预约记录时间
///
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/EmployeePerformanceStatisticsOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/EmployeePerformanceStatisticsOutput.cs
index 92a6d54..4800ff1 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/EmployeePerformanceStatisticsOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/EmployeePerformanceStatisticsOutput.cs
@@ -78,7 +78,7 @@ namespace NCC.Extend.Entitys.Dto.LqStatistics
///
/// 消耗项目数(项目次数总和,包含原始+加班+陪同)
///
- public int ConsumeProjectCount { get; set; }
+ public decimal ConsumeProjectCount { get; set; }
///
/// 消耗原始项目数(原始项目次数总和)
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
index ad43a60..a9beab8 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
@@ -126,6 +126,9 @@ namespace NCC.Extend.LqKdKdjlb
throw NCCException.Oh(ErrorCode.COM1005, "开单记录不存在");
}
var output = entity.Adapt();
+ output.upgradeLifeBeauty = entity.UpgradeLifeBeauty;
+ output.upgradeTechBeauty = entity.UpgradeTechBeauty;
+ output.upgradeMedicalBeauty = entity.UpgradeMedicalBeauty;
if (!string.IsNullOrEmpty(entity.AppointmentId))
{
output.appointmentTime = await _db.Queryable().Where(x => x.Id == entity.AppointmentId).Select(x => x.Yysj).FirstAsync();
@@ -323,6 +326,9 @@ namespace NCC.Extend.LqKdKdjlb
activityName = SqlFunc.Subqueryable().Where(x => x.Id == it.ActivityId).Select(x => x.ActivityName),
appointmentId = it.AppointmentId,
appointmentTime = it.AppointmentId == null ? (DateTime?)null : SqlFunc.Subqueryable().Where(x => x.Id == it.AppointmentId).Select(x => SqlFunc.ToDate(x.Yysj)),
+ upgradeMedicalBeauty = it.UpgradeMedicalBeauty,
+ upgradeTechBeauty = it.UpgradeTechBeauty,
+ upgradeLifeBeauty = it.UpgradeLifeBeauty,
})
.MergeTable()
.OrderBy(sidx + " " + input.sort)
@@ -769,7 +775,6 @@ namespace NCC.Extend.LqKdKdjlb
{
//开启事务
_db.BeginTran();
-
//判断是否有补缴开单ID
if (!string.IsNullOrEmpty(input.supplementBillingId))
{
@@ -785,11 +790,96 @@ namespace NCC.Extend.LqKdKdjlb
supplementBillingEntity.PaidDebt += input.supplementAmount > supplementAmount ? supplementAmount : input.supplementAmount;
await _db.Updateable(supplementBillingEntity).ExecuteCommandAsync();
}
-
//新增开单记录表记录
entity.CreateUser = userInfo.userId;
- entity.DeductAmount = input.lqKdKdjlbDeductList.Sum(x => x.Amount ?? 0);//计算储扣总金额
+ //计算储扣总金额
+ entity.DeductAmount = input.lqKdKdjlbDeductList.Sum(x => x.Amount ?? 0);
+ //判断升单类型:需要同时满足两个条件
+ //1. 当前开单包含对应类型的品项
+ //2. 该会员之前有开单记录(升单的前提)
+
+ //批量查询当前开单所有品项的分类(性能优化)
+ var itemIds = input.lqKdPxmxList?.Where(x => !string.IsNullOrEmpty(x.px)).Select(x => x.px).Distinct().ToList() ?? new List();
+ var itemCategoryDict = new Dictionary();
+ if (itemIds.Any())
+ {
+ var itemCategories = await _db.Queryable()
+ .Where(x => itemIds.Contains(x.Id) && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .Select(x => new { x.Id, x.Qt2 })
+ .ToListAsync();
+ itemCategoryDict = itemCategories.ToDictionary(k => k.Id, v => v.Qt2 ?? "");
+ }
+
+ //判断当前开单是否包含医美品项
+ var hasMedicalItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
+ !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "医美");
+ var MedicalItemInCurrentBillingAmount = input.lqKdPxmxList.Where(x =>
+ !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "医美").Sum(x => x.actualPrice);
+
+ //判断当前开单是否包含科美品项
+ var hasTechItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
+ !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "科美");
+
+ //判断当前开单是否包含生美品项
+ var hasLifeItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
+ !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "生美");
+
+ //判断该会员之前是否有医美类型的开单记录(升医美的前提)
+ var hasPreviousMedicalBilling = await _db.Queryable()
+ .Where(pxmx => pxmx.MemberId == entity.Kdhy
+ && pxmx.IsEffective == StatusEnum.有效.GetHashCode()
+ && pxmx.ItemCategory == "医美"
+ && pxmx.ActualPrice > 0
+ && pxmx.Px != "61")
+ .AnyAsync();
+
+ //判断该会员之前是否有科美类型的开单记录(升科美的前提)
+ var hasPreviousTechBilling = await _db.Queryable()
+ .Where(pxmx => pxmx.MemberId == entity.Kdhy
+ && pxmx.IsEffective == StatusEnum.有效.GetHashCode()
+ && pxmx.ItemCategory == "科美"
+ && pxmx.ActualPrice > 0
+ && pxmx.Px != "61")
+ .AnyAsync();
+
+ //判断该会员之前是否有生美类型的开单记录(升生美的前提)
+ var hasPreviousLifeBilling = await _db.Queryable()
+ .Where(pxmx => pxmx.MemberId == entity.Kdhy
+ && pxmx.IsEffective == StatusEnum.有效.GetHashCode()
+ && pxmx.ItemCategory == "生美"
+ && pxmx.ActualPrice > 0
+ && pxmx.Px != "61")
+ .AnyAsync();
+
+ //判断升医美:当前开单包含医美品项 + 之前有医美类型的开单记录 + 实付业绩>=1000
+ if (hasMedicalItemInCurrentBilling && hasPreviousMedicalBilling && MedicalItemInCurrentBillingAmount >= 1000)
+ {
+ entity.UpgradeMedicalBeauty = "是";
+ }
+ else
+ {
+ entity.UpgradeMedicalBeauty = "否";
+ }
+
+ //判断升科美:当前开单包含科美品项 + 之前有科美类型的开单记录
+ if (hasTechItemInCurrentBilling && hasPreviousTechBilling)
+ {
+ entity.UpgradeTechBeauty = "是";
+ }
+ else
+ {
+ entity.UpgradeTechBeauty = "否";
+ }
+ //判断升生美:当前开单包含生美品项 + 之前有生美类型的开单记录
+ if (hasLifeItemInCurrentBilling && hasPreviousLifeBilling)
+ {
+ entity.UpgradeLifeBeauty = "是";
+ }
+ else
+ {
+ entity.UpgradeLifeBeauty = "否";
+ }
//保存开单记录
var newEntity = await _db.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteReturnEntityAsync();
//循环品相信息
@@ -843,7 +933,6 @@ namespace NCC.Extend.LqKdKdjlb
ItemCategory = await _db.Queryable().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(),
};
allPxmxEntities.Add(lqKdPxmxEntity);
-
// 收集该品项关联的健康师业绩
if (item.lqKdJksyjList != null && item.lqKdJksyjList.Any())
{
@@ -1247,6 +1336,58 @@ namespace NCC.Extend.LqKdKdjlb
{
//开启事务
_db.BeginTran();
+ //批量查询当前开单所有品项的分类(性能优化)
+ var itemIds = input.lqKdPxmxList?.Where(x => !string.IsNullOrEmpty(x.px)).Select(x => x.px).Distinct().ToList() ?? new List();
+ var itemCategoryDict = new Dictionary();
+ if (itemIds.Any())
+ {
+ var itemCategories = await _db.Queryable()
+ .Where(x => itemIds.Contains(x.Id) && x.IsEffective == StatusEnum.有效.GetHashCode())
+ .Select(x => new { x.Id, x.Qt2 })
+ .ToListAsync();
+ itemCategoryDict = itemCategories.ToDictionary(k => k.Id, v => v.Qt2 ?? "");
+ }
+ //判断当前开单是否包含医美品项
+ var hasMedicalItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
+ !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "医美");
+ var MedicalItemInCurrentBillingAmount = input.lqKdPxmxList.Where(x =>
+ !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "医美").Sum(x => x.actualPrice);
+ //判断当前开单是否包含科美品项
+ var hasTechItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
+ !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "科美");
+ //判断当前开单是否包含生美品项
+ var hasLifeItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
+ !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "生美");
+ //获取该会员之前开单品项里面是否有医美项目
+ var isMedicalProject = hasMedicalItemInCurrentBilling && await _db.Queryable().Where(x => x.MemberId == entity.Kdhy && x.IsEffective == StatusEnum.有效.GetHashCode() && x.ItemCategory == "医美" && x.ActualPrice > 0 && x.Px != "61" && x.Glkdbh != id).AnyAsync();
+ if (isMedicalProject && MedicalItemInCurrentBillingAmount >= 1000)
+ {
+ entity.UpgradeLifeBeauty = "是";
+ }
+ else
+ {
+ entity.UpgradeLifeBeauty = "否";
+ }
+ //获取该会员之前开单品项里面是否有科美项目
+ var isTechProject = hasTechItemInCurrentBilling && await _db.Queryable().Where(x => x.MemberId == entity.Kdhy && x.IsEffective == StatusEnum.有效.GetHashCode() && x.ItemCategory == "科美" && x.ActualPrice > 0 && x.Px != "61" && x.Glkdbh != id).AnyAsync();
+ if (isTechProject)
+ {
+ entity.UpgradeTechBeauty = "是";
+ }
+ else
+ {
+ entity.UpgradeTechBeauty = "否";
+ }
+ //获取该会员之前开单品项里面是否有生美项目
+ var isLifeProject = hasLifeItemInCurrentBilling && await _db.Queryable().Where(x => x.MemberId == entity.Kdhy && x.IsEffective == StatusEnum.有效.GetHashCode() && x.ItemCategory == "生美" && x.ActualPrice > 0 && x.Px != "61" && x.Glkdbh != id).AnyAsync();
+ if (isLifeProject)
+ {
+ entity.UpgradeMedicalBeauty = "是";
+ }
+ else
+ {
+ entity.UpgradeMedicalBeauty = "否";
+ }
//更新开单记录表记录
await _db.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
@@ -3436,5 +3577,106 @@ namespace NCC.Extend.LqKdKdjlb
}
}
#endregion
+
+ #region 返回储扣列表
+ ///
+ /// 获取储扣列表
+ ///
+ ///
+ /// 获取开单扣减信息(储扣)列表,支持多种条件筛选和分页查询
+ ///
+ /// 示例请求:
+ /// ```json
+ /// {
+ /// "currentPage": 1,
+ /// "pageSize": 10,
+ /// "sidx": "CreateTime",
+ /// "sort": "desc",
+ /// "DeductType": "储值",
+ /// "BillingId": "开单ID",
+ /// "ItemName": "品项名称",
+ /// "MinAmount": 100,
+ /// "MaxAmount": 1000
+ /// }
+ /// ```
+ ///
+ /// 返回字段说明:
+ /// - Id: 储扣记录ID
+ /// - DeductType: 扣减类型
+ /// - DeductTypeName: 扣减类型名称
+ /// - BillingId: 开单ID
+ /// - Amount: 合计金额
+ /// - ItemName: 品项名称
+ /// - ItemCategory: 品项分类(医美/科美/生美)
+ /// - BillingDate: 开单日期
+ /// - MemberName: 客户名称
+ /// - MemberPhone: 客户手机号
+ /// - StoreName: 门店名称
+ ///
+ /// 查询参数
+ /// 分页的储扣列表
+ /// 成功返回分页的储扣列表
+ /// 服务器错误
+ [HttpGet("deduct-list")]
+ public async Task GetDeductList([FromQuery] LqKdDeductinfoListQueryInput input)
+ {
+ try
+ {
+ var sidx = string.IsNullOrEmpty(input.sidx) ? "CreateTime" : input.sidx;
+
+ // 构建基础查询:储扣信息 JOIN 开单记录 JOIN 客户信息 JOIN 门店信息
+ var baseQuery = _db.Queryable((deduct, billing, member, store) => deduct.BillingId == billing.Id && billing.Kdhy == member.Id && billing.Djmd == store.Id)
+ .WhereIF(!string.IsNullOrEmpty(input.DeductType), (deduct, billing, member, store) => deduct.DeductType == input.DeductType)
+ .WhereIF(!string.IsNullOrEmpty(input.DeductId), (deduct, billing, member, store) => deduct.DeductId == input.DeductId)
+ .WhereIF(!string.IsNullOrEmpty(input.BillingId), (deduct, billing, member, store) => deduct.BillingId == input.BillingId)
+ .WhereIF(input.MinAmount.HasValue, (deduct, billing, member, store) => deduct.Amount >= input.MinAmount.Value)
+ .WhereIF(input.MaxAmount.HasValue, (deduct, billing, member, store) => deduct.Amount <= input.MaxAmount.Value)
+ .WhereIF(input.IsEffective.HasValue, (deduct, billing, member, store) => deduct.IsEffective == input.IsEffective.Value)
+ .WhereIF(!string.IsNullOrEmpty(input.ItemName), (deduct, billing, member, store) => deduct.ItemName != null && deduct.ItemName.Contains(input.ItemName))
+ .WhereIF(!string.IsNullOrEmpty(input.ItemId), (deduct, billing, member, store) => deduct.ItemId == input.ItemId)
+ .WhereIF(input.MinUnitPrice.HasValue, (deduct, billing, member, store) => deduct.UnitPrice >= input.MinUnitPrice.Value)
+ .WhereIF(input.MaxUnitPrice.HasValue, (deduct, billing, member, store) => deduct.UnitPrice <= input.MaxUnitPrice.Value)
+ .WhereIF(input.StartCreateTime.HasValue, (deduct, billing, member, store) => deduct.CreateTime >= input.StartCreateTime.Value)
+ .WhereIF(input.EndCreateTime.HasValue, (deduct, billing, member, store) => deduct.CreateTime <= input.EndCreateTime.Value)
+ .WhereIF(!string.IsNullOrEmpty(input.keyword), (deduct, billing, member, store) =>
+ (deduct.ItemName != null && deduct.ItemName.Contains(input.keyword)) ||
+ (member.Khmc != null && member.Khmc.Contains(input.keyword)) ||
+ (member.Sjh != null && member.Sjh.Contains(input.keyword)) ||
+ (billing.Id != null && billing.Id.Contains(input.keyword)));
+
+
+ // 查询并分页
+ var data = await baseQuery.Select((deduct, billing, member, store) => new LqKdDeductinfoListOutput
+ {
+ Id = deduct.Id ?? "",
+ DeductType = deduct.DeductType ?? "",
+ DeductId = deduct.DeductId ?? "",
+ BillingId = deduct.BillingId ?? "",
+ Amount = deduct.Amount,
+ IsEffective = deduct.IsEffective,
+ UnitPrice = deduct.UnitPrice,
+ ItemName = deduct.ItemName ?? "",
+ ItemId = deduct.ItemId ?? "",
+ CreateTime = deduct.CreateTime,
+ ProjectNumber = deduct.ProjectNumber,
+ ItemCategory = deduct.ItemCategory ?? "",
+ BillingDate = billing.Kdrq,
+ MemberId = billing.Kdhy ?? "",
+ MemberName = member.Khmc ?? "",
+ MemberPhone = member.Sjh ?? "",
+ StoreId = billing.Djmd ?? "",
+ StoreName = store.Dm ?? ""
+ }).MergeTable().OrderBy(sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
+
+ return PageResult.SqlSugarPageResult(data);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, $"获取储扣列表失败: {ex.ToString()}");
+ throw NCCException.Oh(ErrorCode.COM1005, $"获取储扣列表失败: {ex.Message}");
+ }
+ }
+ #endregion
+
}
}
diff --git a/sql/更新开单品项明细表品项分类字段.sql b/sql/更新开单品项明细表品项分类字段.sql
new file mode 100644
index 0000000..f544745
--- /dev/null
+++ b/sql/更新开单品项明细表品项分类字段.sql
@@ -0,0 +1,131 @@
+-- ============================================
+-- 批量更新品项明细表的品项分类字段
+-- ============================================
+-- 说明:此脚本用于批量更新以下表的 F_ItemCategory 字段
+-- 1. lq_kd_pxmx(开单品项明细表)
+-- 2. lq_kd_deductinfo(开单扣减信息表)
+-- 3. lq_xh_pxmx(耗卡品项明细表)
+-- 4. lq_hytk_mx(会员退卡明细表)
+--
+-- 数据来源:从关联的项目资料表(lq_xmzl)的 qt2 字段获取品项分类
+--
+-- 关联关系:
+-- - lq_kd_pxmx.px = lq_xmzl.F_Id
+-- - lq_kd_deductinfo.F_ItemId = lq_xmzl.F_Id
+-- - lq_xh_pxmx.px = lq_xmzl.F_Id
+-- - lq_hytk_mx.px = lq_xmzl.F_Id
+--
+-- 更新逻辑:
+-- - 更新所有记录(不判断是否有效)
+-- - 只更新关联的项目资料存在且qt2字段有值的记录
+-- - 从 lq_xmzl.qt2 字段获取品项分类(医美/科美/生美)
+
+-- ============================================
+-- 1. 更新开单品项明细表的品项分类字段
+-- ============================================
+UPDATE lq_kd_pxmx pxmx
+INNER JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
+SET pxmx.F_ItemCategory = xmzl.qt2
+WHERE xmzl.qt2 IS NOT NULL
+ AND xmzl.qt2 != '';
+
+-- ============================================
+-- 2. 更新开单扣减信息表的品项分类字段
+-- ============================================
+UPDATE lq_kd_deductinfo deduct
+INNER JOIN lq_xmzl xmzl ON deduct.F_ItemId = xmzl.F_Id
+SET deduct.F_ItemCategory = xmzl.qt2
+WHERE xmzl.qt2 IS NOT NULL
+ AND xmzl.qt2 != '';
+
+-- ============================================
+-- 3. 更新耗卡品项明细表的品项分类字段
+-- ============================================
+UPDATE lq_xh_pxmx pxmx
+INNER JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
+SET pxmx.F_ItemCategory = xmzl.qt2
+WHERE xmzl.qt2 IS NOT NULL
+ AND xmzl.qt2 != '';
+
+-- ============================================
+-- 4. 更新会员退卡明细表的品项分类字段
+-- ============================================
+UPDATE lq_hytk_mx mx
+INNER JOIN lq_xmzl xmzl ON mx.px = xmzl.F_Id
+SET mx.F_ItemCategory = xmzl.qt2
+WHERE xmzl.qt2 IS NOT NULL
+ AND xmzl.qt2 != '';
+
+-- ============================================
+-- 5. 验证更新结果
+-- ============================================
+-- 查看 lq_kd_pxmx 更新后的统计信息
+-- SELECT
+-- '开单品项明细' AS 表名,
+-- F_ItemCategory AS 品项分类,
+-- COUNT(*) AS 记录数
+-- FROM lq_kd_pxmx
+-- GROUP BY F_ItemCategory
+-- ORDER BY 记录数 DESC;
+
+-- 查看 lq_kd_deductinfo 更新后的统计信息
+-- SELECT
+-- '开单扣减信息' AS 表名,
+-- F_ItemCategory AS 品项分类,
+-- COUNT(*) AS 记录数
+-- FROM lq_kd_deductinfo
+-- GROUP BY F_ItemCategory
+-- ORDER BY 记录数 DESC;
+
+-- 查看 lq_xh_pxmx 更新后的统计信息
+-- SELECT
+-- '耗卡品项明细' AS 表名,
+-- F_ItemCategory AS 品项分类,
+-- COUNT(*) AS 记录数
+-- FROM lq_xh_pxmx
+-- GROUP BY F_ItemCategory
+-- ORDER BY 记录数 DESC;
+
+-- 查看 lq_hytk_mx 更新后的统计信息
+-- SELECT
+-- '会员退卡明细' AS 表名,
+-- F_ItemCategory AS 品项分类,
+-- COUNT(*) AS 记录数
+-- FROM lq_hytk_mx
+-- GROUP BY F_ItemCategory
+-- ORDER BY 记录数 DESC;
+
+-- 查看未更新的记录数(关联的项目资料不存在或qt2为空)
+--
+-- lq_kd_pxmx 未更新记录数
+-- SELECT COUNT(*) AS 未更新记录数
+-- FROM lq_kd_pxmx pxmx
+-- LEFT JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
+-- WHERE xmzl.F_Id IS NULL
+-- OR xmzl.qt2 IS NULL
+-- OR xmzl.qt2 = '';
+
+-- lq_kd_deductinfo 未更新记录数
+-- SELECT COUNT(*) AS 未更新记录数
+-- FROM lq_kd_deductinfo deduct
+-- LEFT JOIN lq_xmzl xmzl ON deduct.F_ItemId = xmzl.F_Id
+-- WHERE xmzl.F_Id IS NULL
+-- OR xmzl.qt2 IS NULL
+-- OR xmzl.qt2 = '';
+
+-- lq_xh_pxmx 未更新记录数
+-- SELECT COUNT(*) AS 未更新记录数
+-- FROM lq_xh_pxmx pxmx
+-- LEFT JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
+-- WHERE xmzl.F_Id IS NULL
+-- OR xmzl.qt2 IS NULL
+-- OR xmzl.qt2 = '';
+
+-- lq_hytk_mx 未更新记录数
+-- SELECT COUNT(*) AS 未更新记录数
+-- FROM lq_hytk_mx mx
+-- LEFT JOIN lq_xmzl xmzl ON mx.px = xmzl.F_Id
+-- WHERE xmzl.F_Id IS NULL
+-- OR xmzl.qt2 IS NULL
+-- OR xmzl.qt2 = '';
+