Commit 404cbc89e47eb76331c89be93e8da652accfa0fd

Authored by “wangming”
1 parent b472259f

完善升单类型判断逻辑和储扣列表功能

- 修复升单类型判断:需要判断之前是否有对应类型的开单记录,而不是只判断是否有开单记录
- 优化升单判断性能:批量查询品项分类,避免循环查询数据库
- 完善储扣列表查询接口:添加分页、筛选、关联查询等功能
- 添加升单类型字段到输出DTO:upgradeLifeBeauty、upgradeTechBeauty、upgradeMedicalBeauty
- 修复升医美判断:使用当前开单医美品项金额>=1000,而不是实付业绩>=1000
- 优化查询逻辑:直接使用LqKdPxmxEntity的MemberId字段,简化JOIN查询
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoListOutput.cs
... ... @@ -16,12 +16,6 @@ namespace NCC.Extend.Entitys.Dto.LqKdDeductinfo
16 16 /// 扣减类型
17 17 /// </summary>
18 18 public string DeductType { get; set; }
19   -
20   - /// <summary>
21   - /// 扣减类型名称
22   - /// </summary>
23   - public string DeductTypeName { get; set; }
24   -
25 19 /// <summary>
26 20 /// 扣减关联ID
27 21 /// </summary>
... ... @@ -61,5 +55,45 @@ namespace NCC.Extend.Entitys.Dto.LqKdDeductinfo
61 55 /// 创建时间
62 56 /// </summary>
63 57 public DateTime? CreateTime { get; set; }
  58 +
  59 + /// <summary>
  60 + /// 项目数量
  61 + /// </summary>
  62 + public decimal? ProjectNumber { get; set; }
  63 +
  64 + /// <summary>
  65 + /// 品项分类
  66 + /// </summary>
  67 + public string ItemCategory { get; set; }
  68 +
  69 + /// <summary>
  70 + /// 开单日期
  71 + /// </summary>
  72 + public DateTime? BillingDate { get; set; }
  73 +
  74 + /// <summary>
  75 + /// 客户ID
  76 + /// </summary>
  77 + public string MemberId { get; set; }
  78 +
  79 + /// <summary>
  80 + /// 客户名称
  81 + /// </summary>
  82 + public string MemberName { get; set; }
  83 +
  84 + /// <summary>
  85 + /// 客户手机号
  86 + /// </summary>
  87 + public string MemberPhone { get; set; }
  88 +
  89 + /// <summary>
  90 + /// 门店ID
  91 + /// </summary>
  92 + public string StoreId { get; set; }
  93 +
  94 + /// <summary>
  95 + /// 门店名称
  96 + /// </summary>
  97 + public string StoreName { get; set; }
64 98 }
65 99 }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoListQueryInput.cs
1 1 using System;
  2 +using NCC.Common.Filter;
2 3  
3 4 namespace NCC.Extend.Entitys.Dto.LqKdDeductinfo
4 5 {
5 6 /// <summary>
6 7 /// 开单扣减信息列表查询输入
7 8 /// </summary>
8   - public class LqKdDeductinfoListQueryInput
  9 + public class LqKdDeductinfoListQueryInput : PageInputBase
9 10 {
10 11 /// <summary>
11 12 /// 扣减类型
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbInfoOutput.cs
... ... @@ -182,6 +182,21 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
182 182 /// </summary>
183 183 public DateTime? appointmentTime { get; set; }
184 184  
  185 +
  186 + /// <summary>
  187 + /// 升生美
  188 + /// </summary>
  189 + public string upgradeLifeBeauty { get; set; }
  190 +
  191 + /// <summary>
  192 + /// 升科美
  193 + /// </summary>
  194 + public string upgradeTechBeauty { get; set; }
  195 +
  196 + /// <summary>
  197 + /// 升医美
  198 + /// </summary>
  199 + public string upgradeMedicalBeauty { get; set; }
185 200 /// <summary>
186 201 /// 健康师业绩
187 202 /// </summary>
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListOutput.cs
... ... @@ -171,6 +171,21 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
171 171 /// 预约记录ID
172 172 /// </summary>
173 173 public string appointmentId { get; set; }
  174 +
  175 + /// <summary>
  176 + /// 是否升医美
  177 + /// </summary>
  178 + public string upgradeLifeBeauty { get; set; }
  179 +
  180 + /// <summary>
  181 + /// 是否升科美
  182 + /// </summary>
  183 + public string upgradeTechBeauty { get; set; }
  184 +
  185 + /// <summary>
  186 + /// 是否升生美
  187 + /// </summary>
  188 + public string upgradeMedicalBeauty { get; set; }
174 189 /// <summary>
175 190 /// 预约记录时间
176 191 /// </summary>
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/EmployeePerformanceStatisticsOutput.cs
... ... @@ -78,7 +78,7 @@ namespace NCC.Extend.Entitys.Dto.LqStatistics
78 78 /// <summary>
79 79 /// 消耗项目数(项目次数总和,包含原始+加班+陪同)
80 80 /// </summary>
81   - public int ConsumeProjectCount { get; set; }
  81 + public decimal ConsumeProjectCount { get; set; }
82 82  
83 83 /// <summary>
84 84 /// 消耗原始项目数(原始项目次数总和)
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
... ... @@ -126,6 +126,9 @@ namespace NCC.Extend.LqKdKdjlb
126 126 throw NCCException.Oh(ErrorCode.COM1005, "开单记录不存在");
127 127 }
128 128 var output = entity.Adapt<LqKdKdjlbInfoOutput>();
  129 + output.upgradeLifeBeauty = entity.UpgradeLifeBeauty;
  130 + output.upgradeTechBeauty = entity.UpgradeTechBeauty;
  131 + output.upgradeMedicalBeauty = entity.UpgradeMedicalBeauty;
129 132 if (!string.IsNullOrEmpty(entity.AppointmentId))
130 133 {
131 134 output.appointmentTime = await _db.Queryable<LqYyjlEntity>().Where(x => x.Id == entity.AppointmentId).Select(x => x.Yysj).FirstAsync();
... ... @@ -323,6 +326,9 @@ namespace NCC.Extend.LqKdKdjlb
323 326 activityName = SqlFunc.Subqueryable<LqPackageInfoEntity>().Where(x => x.Id == it.ActivityId).Select(x => x.ActivityName),
324 327 appointmentId = it.AppointmentId,
325 328 appointmentTime = it.AppointmentId == null ? (DateTime?)null : SqlFunc.Subqueryable<LqYyjlEntity>().Where(x => x.Id == it.AppointmentId).Select(x => SqlFunc.ToDate(x.Yysj)),
  329 + upgradeMedicalBeauty = it.UpgradeMedicalBeauty,
  330 + upgradeTechBeauty = it.UpgradeTechBeauty,
  331 + upgradeLifeBeauty = it.UpgradeLifeBeauty,
326 332 })
327 333 .MergeTable()
328 334 .OrderBy(sidx + " " + input.sort)
... ... @@ -769,7 +775,6 @@ namespace NCC.Extend.LqKdKdjlb
769 775 {
770 776 //开启事务
771 777 _db.BeginTran();
772   -
773 778 //判断是否有补缴开单ID
774 779 if (!string.IsNullOrEmpty(input.supplementBillingId))
775 780 {
... ... @@ -785,11 +790,96 @@ namespace NCC.Extend.LqKdKdjlb
785 790 supplementBillingEntity.PaidDebt += input.supplementAmount > supplementAmount ? supplementAmount : input.supplementAmount;
786 791 await _db.Updateable(supplementBillingEntity).ExecuteCommandAsync();
787 792 }
788   -
789 793 //新增开单记录表记录
790 794 entity.CreateUser = userInfo.userId;
791   - entity.DeductAmount = input.lqKdKdjlbDeductList.Sum(x => x.Amount ?? 0);//计算储扣总金额
  795 + //计算储扣总金额
  796 + entity.DeductAmount = input.lqKdKdjlbDeductList.Sum(x => x.Amount ?? 0);
  797 + //判断升单类型:需要同时满足两个条件
  798 + //1. 当前开单包含对应类型的品项
  799 + //2. 该会员之前有开单记录(升单的前提)
  800 +
  801 + //批量查询当前开单所有品项的分类(性能优化)
  802 + var itemIds = input.lqKdPxmxList?.Where(x => !string.IsNullOrEmpty(x.px)).Select(x => x.px).Distinct().ToList() ?? new List<string>();
  803 + var itemCategoryDict = new Dictionary<string, string>();
  804 + if (itemIds.Any())
  805 + {
  806 + var itemCategories = await _db.Queryable<LqXmzlEntity>()
  807 + .Where(x => itemIds.Contains(x.Id) && x.IsEffective == StatusEnum.有效.GetHashCode())
  808 + .Select(x => new { x.Id, x.Qt2 })
  809 + .ToListAsync();
  810 + itemCategoryDict = itemCategories.ToDictionary(k => k.Id, v => v.Qt2 ?? "");
  811 + }
  812 +
  813 + //判断当前开单是否包含医美品项
  814 + var hasMedicalItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
  815 + !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "医美");
  816 + var MedicalItemInCurrentBillingAmount = input.lqKdPxmxList.Where(x =>
  817 + !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "医美").Sum(x => x.actualPrice);
  818 +
  819 + //判断当前开单是否包含科美品项
  820 + var hasTechItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
  821 + !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "科美");
  822 +
  823 + //判断当前开单是否包含生美品项
  824 + var hasLifeItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
  825 + !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "生美");
  826 +
  827 + //判断该会员之前是否有医美类型的开单记录(升医美的前提)
  828 + var hasPreviousMedicalBilling = await _db.Queryable<LqKdPxmxEntity>()
  829 + .Where(pxmx => pxmx.MemberId == entity.Kdhy
  830 + && pxmx.IsEffective == StatusEnum.有效.GetHashCode()
  831 + && pxmx.ItemCategory == "医美"
  832 + && pxmx.ActualPrice > 0
  833 + && pxmx.Px != "61")
  834 + .AnyAsync();
  835 +
  836 + //判断该会员之前是否有科美类型的开单记录(升科美的前提)
  837 + var hasPreviousTechBilling = await _db.Queryable<LqKdPxmxEntity>()
  838 + .Where(pxmx => pxmx.MemberId == entity.Kdhy
  839 + && pxmx.IsEffective == StatusEnum.有效.GetHashCode()
  840 + && pxmx.ItemCategory == "科美"
  841 + && pxmx.ActualPrice > 0
  842 + && pxmx.Px != "61")
  843 + .AnyAsync();
  844 +
  845 + //判断该会员之前是否有生美类型的开单记录(升生美的前提)
  846 + var hasPreviousLifeBilling = await _db.Queryable<LqKdPxmxEntity>()
  847 + .Where(pxmx => pxmx.MemberId == entity.Kdhy
  848 + && pxmx.IsEffective == StatusEnum.有效.GetHashCode()
  849 + && pxmx.ItemCategory == "生美"
  850 + && pxmx.ActualPrice > 0
  851 + && pxmx.Px != "61")
  852 + .AnyAsync();
  853 +
  854 + //判断升医美:当前开单包含医美品项 + 之前有医美类型的开单记录 + 实付业绩>=1000
  855 + if (hasMedicalItemInCurrentBilling && hasPreviousMedicalBilling && MedicalItemInCurrentBillingAmount >= 1000)
  856 + {
  857 + entity.UpgradeMedicalBeauty = "是";
  858 + }
  859 + else
  860 + {
  861 + entity.UpgradeMedicalBeauty = "否";
  862 + }
  863 +
  864 + //判断升科美:当前开单包含科美品项 + 之前有科美类型的开单记录
  865 + if (hasTechItemInCurrentBilling && hasPreviousTechBilling)
  866 + {
  867 + entity.UpgradeTechBeauty = "是";
  868 + }
  869 + else
  870 + {
  871 + entity.UpgradeTechBeauty = "否";
  872 + }
792 873  
  874 + //判断升生美:当前开单包含生美品项 + 之前有生美类型的开单记录
  875 + if (hasLifeItemInCurrentBilling && hasPreviousLifeBilling)
  876 + {
  877 + entity.UpgradeLifeBeauty = "是";
  878 + }
  879 + else
  880 + {
  881 + entity.UpgradeLifeBeauty = "否";
  882 + }
793 883 //保存开单记录
794 884 var newEntity = await _db.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteReturnEntityAsync();
795 885 //循环品相信息
... ... @@ -843,7 +933,6 @@ namespace NCC.Extend.LqKdKdjlb
843 933 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(),
844 934 };
845 935 allPxmxEntities.Add(lqKdPxmxEntity);
846   -
847 936 // 收集该品项关联的健康师业绩
848 937 if (item.lqKdJksyjList != null && item.lqKdJksyjList.Any())
849 938 {
... ... @@ -1247,6 +1336,58 @@ namespace NCC.Extend.LqKdKdjlb
1247 1336 {
1248 1337 //开启事务
1249 1338 _db.BeginTran();
  1339 + //批量查询当前开单所有品项的分类(性能优化)
  1340 + var itemIds = input.lqKdPxmxList?.Where(x => !string.IsNullOrEmpty(x.px)).Select(x => x.px).Distinct().ToList() ?? new List<string>();
  1341 + var itemCategoryDict = new Dictionary<string, string>();
  1342 + if (itemIds.Any())
  1343 + {
  1344 + var itemCategories = await _db.Queryable<LqXmzlEntity>()
  1345 + .Where(x => itemIds.Contains(x.Id) && x.IsEffective == StatusEnum.有效.GetHashCode())
  1346 + .Select(x => new { x.Id, x.Qt2 })
  1347 + .ToListAsync();
  1348 + itemCategoryDict = itemCategories.ToDictionary(k => k.Id, v => v.Qt2 ?? "");
  1349 + }
  1350 + //判断当前开单是否包含医美品项
  1351 + var hasMedicalItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
  1352 + !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "医美");
  1353 + var MedicalItemInCurrentBillingAmount = input.lqKdPxmxList.Where(x =>
  1354 + !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "医美").Sum(x => x.actualPrice);
  1355 + //判断当前开单是否包含科美品项
  1356 + var hasTechItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
  1357 + !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "科美");
  1358 + //判断当前开单是否包含生美品项
  1359 + var hasLifeItemInCurrentBilling = input.lqKdPxmxList != null && input.lqKdPxmxList.Any(x =>
  1360 + !string.IsNullOrEmpty(x.px) && itemCategoryDict.ContainsKey(x.px) && itemCategoryDict[x.px] == "生美");
  1361 + //获取该会员之前开单品项里面是否有医美项目
  1362 + var isMedicalProject = hasMedicalItemInCurrentBilling && await _db.Queryable<LqKdPxmxEntity>().Where(x => x.MemberId == entity.Kdhy && x.IsEffective == StatusEnum.有效.GetHashCode() && x.ItemCategory == "医美" && x.ActualPrice > 0 && x.Px != "61" && x.Glkdbh != id).AnyAsync();
  1363 + if (isMedicalProject && MedicalItemInCurrentBillingAmount >= 1000)
  1364 + {
  1365 + entity.UpgradeLifeBeauty = "是";
  1366 + }
  1367 + else
  1368 + {
  1369 + entity.UpgradeLifeBeauty = "否";
  1370 + }
  1371 + //获取该会员之前开单品项里面是否有科美项目
  1372 + var isTechProject = hasTechItemInCurrentBilling && await _db.Queryable<LqKdPxmxEntity>().Where(x => x.MemberId == entity.Kdhy && x.IsEffective == StatusEnum.有效.GetHashCode() && x.ItemCategory == "科美" && x.ActualPrice > 0 && x.Px != "61" && x.Glkdbh != id).AnyAsync();
  1373 + if (isTechProject)
  1374 + {
  1375 + entity.UpgradeTechBeauty = "是";
  1376 + }
  1377 + else
  1378 + {
  1379 + entity.UpgradeTechBeauty = "否";
  1380 + }
  1381 + //获取该会员之前开单品项里面是否有生美项目
  1382 + var isLifeProject = hasLifeItemInCurrentBilling && await _db.Queryable<LqKdPxmxEntity>().Where(x => x.MemberId == entity.Kdhy && x.IsEffective == StatusEnum.有效.GetHashCode() && x.ItemCategory == "生美" && x.ActualPrice > 0 && x.Px != "61" && x.Glkdbh != id).AnyAsync();
  1383 + if (isLifeProject)
  1384 + {
  1385 + entity.UpgradeMedicalBeauty = "是";
  1386 + }
  1387 + else
  1388 + {
  1389 + entity.UpgradeMedicalBeauty = "否";
  1390 + }
1250 1391  
1251 1392 //更新开单记录表记录
1252 1393 await _db.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
... ... @@ -3436,5 +3577,106 @@ namespace NCC.Extend.LqKdKdjlb
3436 3577 }
3437 3578 }
3438 3579 #endregion
  3580 +
  3581 + #region 返回储扣列表
  3582 + /// <summary>
  3583 + /// 获取储扣列表
  3584 + /// </summary>
  3585 + /// <remarks>
  3586 + /// 获取开单扣减信息(储扣)列表,支持多种条件筛选和分页查询
  3587 + ///
  3588 + /// 示例请求:
  3589 + /// ```json
  3590 + /// {
  3591 + /// "currentPage": 1,
  3592 + /// "pageSize": 10,
  3593 + /// "sidx": "CreateTime",
  3594 + /// "sort": "desc",
  3595 + /// "DeductType": "储值",
  3596 + /// "BillingId": "开单ID",
  3597 + /// "ItemName": "品项名称",
  3598 + /// "MinAmount": 100,
  3599 + /// "MaxAmount": 1000
  3600 + /// }
  3601 + /// ```
  3602 + ///
  3603 + /// 返回字段说明:
  3604 + /// - Id: 储扣记录ID
  3605 + /// - DeductType: 扣减类型
  3606 + /// - DeductTypeName: 扣减类型名称
  3607 + /// - BillingId: 开单ID
  3608 + /// - Amount: 合计金额
  3609 + /// - ItemName: 品项名称
  3610 + /// - ItemCategory: 品项分类(医美/科美/生美)
  3611 + /// - BillingDate: 开单日期
  3612 + /// - MemberName: 客户名称
  3613 + /// - MemberPhone: 客户手机号
  3614 + /// - StoreName: 门店名称
  3615 + /// </remarks>
  3616 + /// <param name="input">查询参数</param>
  3617 + /// <returns>分页的储扣列表</returns>
  3618 + /// <response code="200">成功返回分页的储扣列表</response>
  3619 + /// <response code="500">服务器错误</response>
  3620 + [HttpGet("deduct-list")]
  3621 + public async Task<dynamic> GetDeductList([FromQuery] LqKdDeductinfoListQueryInput input)
  3622 + {
  3623 + try
  3624 + {
  3625 + var sidx = string.IsNullOrEmpty(input.sidx) ? "CreateTime" : input.sidx;
  3626 +
  3627 + // 构建基础查询:储扣信息 JOIN 开单记录 JOIN 客户信息 JOIN 门店信息
  3628 + var baseQuery = _db.Queryable<LqKdDeductinfoEntity, LqKdKdjlbEntity, LqKhxxEntity, LqMdxxEntity>((deduct, billing, member, store) => deduct.BillingId == billing.Id && billing.Kdhy == member.Id && billing.Djmd == store.Id)
  3629 + .WhereIF(!string.IsNullOrEmpty(input.DeductType), (deduct, billing, member, store) => deduct.DeductType == input.DeductType)
  3630 + .WhereIF(!string.IsNullOrEmpty(input.DeductId), (deduct, billing, member, store) => deduct.DeductId == input.DeductId)
  3631 + .WhereIF(!string.IsNullOrEmpty(input.BillingId), (deduct, billing, member, store) => deduct.BillingId == input.BillingId)
  3632 + .WhereIF(input.MinAmount.HasValue, (deduct, billing, member, store) => deduct.Amount >= input.MinAmount.Value)
  3633 + .WhereIF(input.MaxAmount.HasValue, (deduct, billing, member, store) => deduct.Amount <= input.MaxAmount.Value)
  3634 + .WhereIF(input.IsEffective.HasValue, (deduct, billing, member, store) => deduct.IsEffective == input.IsEffective.Value)
  3635 + .WhereIF(!string.IsNullOrEmpty(input.ItemName), (deduct, billing, member, store) => deduct.ItemName != null && deduct.ItemName.Contains(input.ItemName))
  3636 + .WhereIF(!string.IsNullOrEmpty(input.ItemId), (deduct, billing, member, store) => deduct.ItemId == input.ItemId)
  3637 + .WhereIF(input.MinUnitPrice.HasValue, (deduct, billing, member, store) => deduct.UnitPrice >= input.MinUnitPrice.Value)
  3638 + .WhereIF(input.MaxUnitPrice.HasValue, (deduct, billing, member, store) => deduct.UnitPrice <= input.MaxUnitPrice.Value)
  3639 + .WhereIF(input.StartCreateTime.HasValue, (deduct, billing, member, store) => deduct.CreateTime >= input.StartCreateTime.Value)
  3640 + .WhereIF(input.EndCreateTime.HasValue, (deduct, billing, member, store) => deduct.CreateTime <= input.EndCreateTime.Value)
  3641 + .WhereIF(!string.IsNullOrEmpty(input.keyword), (deduct, billing, member, store) =>
  3642 + (deduct.ItemName != null && deduct.ItemName.Contains(input.keyword)) ||
  3643 + (member.Khmc != null && member.Khmc.Contains(input.keyword)) ||
  3644 + (member.Sjh != null && member.Sjh.Contains(input.keyword)) ||
  3645 + (billing.Id != null && billing.Id.Contains(input.keyword)));
  3646 +
  3647 +
  3648 + // 查询并分页
  3649 + var data = await baseQuery.Select((deduct, billing, member, store) => new LqKdDeductinfoListOutput
  3650 + {
  3651 + Id = deduct.Id ?? "",
  3652 + DeductType = deduct.DeductType ?? "",
  3653 + DeductId = deduct.DeductId ?? "",
  3654 + BillingId = deduct.BillingId ?? "",
  3655 + Amount = deduct.Amount,
  3656 + IsEffective = deduct.IsEffective,
  3657 + UnitPrice = deduct.UnitPrice,
  3658 + ItemName = deduct.ItemName ?? "",
  3659 + ItemId = deduct.ItemId ?? "",
  3660 + CreateTime = deduct.CreateTime,
  3661 + ProjectNumber = deduct.ProjectNumber,
  3662 + ItemCategory = deduct.ItemCategory ?? "",
  3663 + BillingDate = billing.Kdrq,
  3664 + MemberId = billing.Kdhy ?? "",
  3665 + MemberName = member.Khmc ?? "",
  3666 + MemberPhone = member.Sjh ?? "",
  3667 + StoreId = billing.Djmd ?? "",
  3668 + StoreName = store.Dm ?? ""
  3669 + }).MergeTable().OrderBy(sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
  3670 +
  3671 + return PageResult<LqKdDeductinfoListOutput>.SqlSugarPageResult(data);
  3672 + }
  3673 + catch (Exception ex)
  3674 + {
  3675 + _logger.LogError(ex, $"获取储扣列表失败: {ex.ToString()}");
  3676 + throw NCCException.Oh(ErrorCode.COM1005, $"获取储扣列表失败: {ex.Message}");
  3677 + }
  3678 + }
  3679 + #endregion
  3680 +
3439 3681 }
3440 3682 }
... ...
sql/更新开单品项明细表品项分类字段.sql 0 → 100644
  1 +-- ============================================
  2 +-- 批量更新品项明细表的品项分类字段
  3 +-- ============================================
  4 +-- 说明:此脚本用于批量更新以下表的 F_ItemCategory 字段
  5 +-- 1. lq_kd_pxmx(开单品项明细表)
  6 +-- 2. lq_kd_deductinfo(开单扣减信息表)
  7 +-- 3. lq_xh_pxmx(耗卡品项明细表)
  8 +-- 4. lq_hytk_mx(会员退卡明细表)
  9 +--
  10 +-- 数据来源:从关联的项目资料表(lq_xmzl)的 qt2 字段获取品项分类
  11 +--
  12 +-- 关联关系:
  13 +-- - lq_kd_pxmx.px = lq_xmzl.F_Id
  14 +-- - lq_kd_deductinfo.F_ItemId = lq_xmzl.F_Id
  15 +-- - lq_xh_pxmx.px = lq_xmzl.F_Id
  16 +-- - lq_hytk_mx.px = lq_xmzl.F_Id
  17 +--
  18 +-- 更新逻辑:
  19 +-- - 更新所有记录(不判断是否有效)
  20 +-- - 只更新关联的项目资料存在且qt2字段有值的记录
  21 +-- - 从 lq_xmzl.qt2 字段获取品项分类(医美/科美/生美)
  22 +
  23 +-- ============================================
  24 +-- 1. 更新开单品项明细表的品项分类字段
  25 +-- ============================================
  26 +UPDATE lq_kd_pxmx pxmx
  27 +INNER JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
  28 +SET pxmx.F_ItemCategory = xmzl.qt2
  29 +WHERE xmzl.qt2 IS NOT NULL
  30 + AND xmzl.qt2 != '';
  31 +
  32 +-- ============================================
  33 +-- 2. 更新开单扣减信息表的品项分类字段
  34 +-- ============================================
  35 +UPDATE lq_kd_deductinfo deduct
  36 +INNER JOIN lq_xmzl xmzl ON deduct.F_ItemId = xmzl.F_Id
  37 +SET deduct.F_ItemCategory = xmzl.qt2
  38 +WHERE xmzl.qt2 IS NOT NULL
  39 + AND xmzl.qt2 != '';
  40 +
  41 +-- ============================================
  42 +-- 3. 更新耗卡品项明细表的品项分类字段
  43 +-- ============================================
  44 +UPDATE lq_xh_pxmx pxmx
  45 +INNER JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
  46 +SET pxmx.F_ItemCategory = xmzl.qt2
  47 +WHERE xmzl.qt2 IS NOT NULL
  48 + AND xmzl.qt2 != '';
  49 +
  50 +-- ============================================
  51 +-- 4. 更新会员退卡明细表的品项分类字段
  52 +-- ============================================
  53 +UPDATE lq_hytk_mx mx
  54 +INNER JOIN lq_xmzl xmzl ON mx.px = xmzl.F_Id
  55 +SET mx.F_ItemCategory = xmzl.qt2
  56 +WHERE xmzl.qt2 IS NOT NULL
  57 + AND xmzl.qt2 != '';
  58 +
  59 +-- ============================================
  60 +-- 5. 验证更新结果
  61 +-- ============================================
  62 +-- 查看 lq_kd_pxmx 更新后的统计信息
  63 +-- SELECT
  64 +-- '开单品项明细' AS 表名,
  65 +-- F_ItemCategory AS 品项分类,
  66 +-- COUNT(*) AS 记录数
  67 +-- FROM lq_kd_pxmx
  68 +-- GROUP BY F_ItemCategory
  69 +-- ORDER BY 记录数 DESC;
  70 +
  71 +-- 查看 lq_kd_deductinfo 更新后的统计信息
  72 +-- SELECT
  73 +-- '开单扣减信息' AS 表名,
  74 +-- F_ItemCategory AS 品项分类,
  75 +-- COUNT(*) AS 记录数
  76 +-- FROM lq_kd_deductinfo
  77 +-- GROUP BY F_ItemCategory
  78 +-- ORDER BY 记录数 DESC;
  79 +
  80 +-- 查看 lq_xh_pxmx 更新后的统计信息
  81 +-- SELECT
  82 +-- '耗卡品项明细' AS 表名,
  83 +-- F_ItemCategory AS 品项分类,
  84 +-- COUNT(*) AS 记录数
  85 +-- FROM lq_xh_pxmx
  86 +-- GROUP BY F_ItemCategory
  87 +-- ORDER BY 记录数 DESC;
  88 +
  89 +-- 查看 lq_hytk_mx 更新后的统计信息
  90 +-- SELECT
  91 +-- '会员退卡明细' AS 表名,
  92 +-- F_ItemCategory AS 品项分类,
  93 +-- COUNT(*) AS 记录数
  94 +-- FROM lq_hytk_mx
  95 +-- GROUP BY F_ItemCategory
  96 +-- ORDER BY 记录数 DESC;
  97 +
  98 +-- 查看未更新的记录数(关联的项目资料不存在或qt2为空)
  99 +--
  100 +-- lq_kd_pxmx 未更新记录数
  101 +-- SELECT COUNT(*) AS 未更新记录数
  102 +-- FROM lq_kd_pxmx pxmx
  103 +-- LEFT JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
  104 +-- WHERE xmzl.F_Id IS NULL
  105 +-- OR xmzl.qt2 IS NULL
  106 +-- OR xmzl.qt2 = '';
  107 +
  108 +-- lq_kd_deductinfo 未更新记录数
  109 +-- SELECT COUNT(*) AS 未更新记录数
  110 +-- FROM lq_kd_deductinfo deduct
  111 +-- LEFT JOIN lq_xmzl xmzl ON deduct.F_ItemId = xmzl.F_Id
  112 +-- WHERE xmzl.F_Id IS NULL
  113 +-- OR xmzl.qt2 IS NULL
  114 +-- OR xmzl.qt2 = '';
  115 +
  116 +-- lq_xh_pxmx 未更新记录数
  117 +-- SELECT COUNT(*) AS 未更新记录数
  118 +-- FROM lq_xh_pxmx pxmx
  119 +-- LEFT JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
  120 +-- WHERE xmzl.F_Id IS NULL
  121 +-- OR xmzl.qt2 IS NULL
  122 +-- OR xmzl.qt2 = '';
  123 +
  124 +-- lq_hytk_mx 未更新记录数
  125 +-- SELECT COUNT(*) AS 未更新记录数
  126 +-- FROM lq_hytk_mx mx
  127 +-- LEFT JOIN lq_xmzl xmzl ON mx.px = xmzl.F_Id
  128 +-- WHERE xmzl.F_Id IS NULL
  129 +-- OR xmzl.qt2 IS NULL
  130 +-- OR xmzl.qt2 = '';
  131 +
... ...