Commit 910e21a04974e54a6f54c777b4957f6db31e1bf3

Authored by “wangming”
1 parent 96e0ccc7

修复开单记录汇总筛选逻辑:当传入筛选条件但无匹配数据时返回空结果,而不是所有记录

netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoListOutput.cs
@@ -95,5 +95,20 @@ namespace NCC.Extend.Entitys.Dto.LqKdDeductinfo @@ -95,5 +95,20 @@ namespace NCC.Extend.Entitys.Dto.LqKdDeductinfo
95 /// 门店名称 95 /// 门店名称
96 /// </summary> 96 /// </summary>
97 public string StoreName { get; set; } 97 public string StoreName { get; set; }
  98 +
  99 + /// <summary>
  100 + /// 时间期间(开单日期,用于时间范围筛选)
  101 + /// </summary>
  102 + public DateTime? TimePeriod { get; set; }
  103 +
  104 + /// <summary>
  105 + /// 开单类型(购买、赠送、体验等)
  106 + /// </summary>
  107 + public string BillingType { get; set; }
  108 +
  109 + /// <summary>
  110 + /// 合作机构
  111 + /// </summary>
  112 + public string CooperationInstitution { get; set; }
98 } 113 }
99 } 114 }
netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
@@ -47,6 +47,7 @@ using NCC.Extend.Entitys.lq_mdxx; @@ -47,6 +47,7 @@ using NCC.Extend.Entitys.lq_mdxx;
47 using NCC.Extend.Entitys.lq_card_transfer_log; 47 using NCC.Extend.Entitys.lq_card_transfer_log;
48 using NCC.Extend.Entitys.Dto.LqDailyReport; 48 using NCC.Extend.Entitys.Dto.LqDailyReport;
49 using NCC.Extend.Entitys.lq_yyjl; 49 using NCC.Extend.Entitys.lq_yyjl;
  50 +using NCC.Extend.Entitys.lq_hzf;
50 51
51 namespace NCC.Extend.LqKdKdjlb 52 namespace NCC.Extend.LqKdKdjlb
52 { 53 {
@@ -2322,9 +2323,9 @@ namespace NCC.Extend.LqKdKdjlb @@ -2322,9 +2323,9 @@ namespace NCC.Extend.LqKdKdjlb
2322 } 2323 }
2323 #endregion 2324 #endregion
2324 2325
2325 - #region 获取门店某个时间段的开单记录汇总信息 2326 + #region 获取门店某个时间段的开单记录汇总信息(台账)
2326 /// <summary> 2327 /// <summary>
2327 - /// 获取门店某个时间段的开单记录汇总信息 2328 + /// 获取门店某个时间段的开单记录汇总信息(台账)
2328 /// </summary> 2329 /// </summary>
2329 /// <param name="input">查询参数</param> 2330 /// <param name="input">查询参数</param>
2330 /// <returns>开单记录汇总信息</returns> 2331 /// <returns>开单记录汇总信息</returns>
@@ -2368,12 +2369,15 @@ namespace NCC.Extend.LqKdKdjlb @@ -2368,12 +2369,15 @@ namespace NCC.Extend.LqKdKdjlb
2368 zdyj = it.Zdyj, 2369 zdyj = it.Zdyj,
2369 sfyj = it.Sfyj, 2370 sfyj = it.Sfyj,
2370 qk = it.Qk, 2371 qk = it.Qk,
  2372 + hgjg = it.Hgjg,
  2373 + hgjgName = SqlFunc.Subqueryable<LqHzfEntity>().Where(x => x.Id == it.Hgjg).Select(x => x.Hzmc),
2371 kdhyc = SqlFunc.Subqueryable<LqKhxxEntity>().Where(x => x.Id == it.Kdhy).Select(x => x.Khmc), 2374 kdhyc = SqlFunc.Subqueryable<LqKhxxEntity>().Where(x => x.Id == it.Kdhy).Select(x => x.Khmc),
2372 kdhysjh = SqlFunc.Subqueryable<LqKhxxEntity>().Where(x => x.Id == it.Kdhy).Select(x => x.Sjh), 2375 kdhysjh = SqlFunc.Subqueryable<LqKhxxEntity>().Where(x => x.Id == it.Kdhy).Select(x => x.Sjh),
2373 fkfs = it.Fkfs, // 付款方式 2376 fkfs = it.Fkfs, // 付款方式
2374 khly = it.Khly, // 客户来源 2377 khly = it.Khly, // 客户来源
2375 bz = it.Bz, // 备注 2378 bz = it.Bz, // 备注
2376 createTime = it.CreateTime 2379 createTime = it.CreateTime
  2380 +
2377 }) 2381 })
2378 .ToListAsync(); 2382 .ToListAsync();
2379 2383
@@ -2491,240 +2495,55 @@ namespace NCC.Extend.LqKdKdjlb @@ -2491,240 +2495,55 @@ namespace NCC.Extend.LqKdKdjlb
2491 }) 2495 })
2492 .ToListAsync(); 2496 .ToListAsync();
2493 2497
2494 - // 构建按开单记录分组的详细数据  
2495 - var detailedRecords = billingRecords.Select(billing => new  
2496 - {  
2497 - // 基本信息  
2498 - date = billing.kdrq?.ToString("yyyy-MM-dd"),  
2499 - customerName = billing.kdhyc,  
2500 - customerPhone = billing.kdhysjh,  
2501 - storeId = billing.djmd,  
2502 - goldTriangle = billing.jsj,  
2503 - customerType = billing.gjlx,  
2504 -  
2505 - // 品项分类  
2506 - purchasedItems = itemDetails.Where(x => x.glkdbh == billing.id && x.sourceType == "购买").Select(x => new  
2507 - {  
2508 - id = x.id,  
2509 - itemName = x.pxmc,  
2510 - itemCode = x.px,  
2511 - price = x.pxjg,  
2512 - totalPrice = x.totalPrice,  
2513 - actualPrice = x.actualPrice,  
2514 - projectNumber = x.projectNumber,  
2515 - remark = x.remark,  
2516 - itemCategory = x.itemCategory,  
2517 - }).ToList(),  
2518 -  
2519 - giftedItems = itemDetails.Where(x => x.glkdbh == billing.id && x.sourceType == "赠送").Select(x => new  
2520 - {  
2521 - id = x.id,  
2522 - itemName = x.pxmc,  
2523 - itemCode = x.px,  
2524 - price = x.pxjg,  
2525 - totalPrice = x.totalPrice,  
2526 - actualPrice = x.actualPrice,  
2527 - projectNumber = x.projectNumber,  
2528 - remark = x.remark,  
2529 - itemCategory = x.itemCategory,  
2530 - }).ToList(),  
2531 -  
2532 - experienceItems = itemDetails.Where(x => x.glkdbh == billing.id && x.sourceType == "体验").Select(x => new  
2533 - {  
2534 - id = x.id,  
2535 - itemName = x.pxmc,  
2536 - itemCode = x.px,  
2537 - price = x.pxjg,  
2538 - totalPrice = x.totalPrice,  
2539 - actualPrice = x.actualPrice,  
2540 - projectNumber = x.projectNumber,  
2541 - remark = x.remark,  
2542 - itemCategory = x.itemCategory,  
2543 - }).ToList(),  
2544 -  
2545 - // 金额信息  
2546 - paidAmount = billing.sfyj,  
2547 - debtAmount = billing.qk,  
2548 - totalAmount = billing.zdyj,  
2549 -  
2550 - // 健康师信息  
2551 - healthTeachers = healthTeacherData.Where(x => x.glkdbh == billing.id).Select(x => new  
2552 - {  
2553 - teacherId = x.jks,  
2554 - teacherName = x.jksxm,  
2555 - teacherAccount = x.jkszh,  
2556 - performance = x.jksyj,  
2557 - performanceTime = x.yjsj,  
2558 - itemDetailId = x.kdpxid,  
2559 - goldTriangleId = x.jsj_id,  
2560 - itemCategory = x.itemCategory,  
2561 - itemId = x.itemId,  
2562 - storeId = x.storeId,  
2563 - itemName = x.itemName  
2564 - }).ToList(),  
2565 -  
2566 - // 其他信息  
2567 - source = billing.khly, // 客户来源  
2568 - paymentMethod = billing.fkfs, // 支付方式  
2569 - remark = billing.bz, // 备注  
2570 - createTime = billing.createTime  
2571 - }).OrderByDescending(x => x.date).ToList(); 2498 + // 根据筛选条件过滤开单记录
  2499 + // 收集所有需要匹配的开单ID(取交集)
  2500 + var matchedBillingIds = new List<string>();
  2501 + var hasFilterCondition = false; // 标记是否传入了筛选条件
2572 2502
2573 - // 构建返回结果  
2574 - var result = new 2503 + // 如果传入了品项分类或品项筛选条件,收集匹配的开单ID
  2504 + if (!string.IsNullOrEmpty(input.ItemCategory) || !string.IsNullOrEmpty(input.ItemId))
2575 { 2505 {
2576 - success = true,  
2577 - data = new 2506 + hasFilterCondition = true;
  2507 + var itemMatchedIds = itemDetails.Select(x => x.glkdbh).Distinct().ToList();
  2508 + if (matchedBillingIds.Any())
2578 { 2509 {
2579 - // 汇总统计  
2580 - summary = new  
2581 - {  
2582 - totalCount = billingRecords.Count,  
2583 - totalAmount = billingRecords.Sum(x => x.zdyj),  
2584 - totalPaidAmount = billingRecords.Sum(x => x.sfyj),  
2585 - totalDebt = billingRecords.Sum(x => x.qk),  
2586 - totalPurchasedItems = purchasedItems.Count,  
2587 - totalGiftedItems = giftedItems.Count,  
2588 - totalExperienceItems = experienceItems.Count,  
2589 - totalHealthTeachers = healthTeacherData.GroupBy(x => x.jks).Count()  
2590 - },  
2591 - // 详细记录列表  
2592 - records = detailedRecords  
2593 - },  
2594 - message = "获取开单记录汇总信息成功"  
2595 - };  
2596 - return result;  
2597 - }  
2598 - catch (Exception ex)  
2599 - {  
2600 - throw NCCException.Oh($"获取开单记录汇总信息失败:{ex.Message}");  
2601 - }  
2602 - }  
2603 - #endregion  
2604 -  
2605 - #region 获取门店某个时间段的开单记录汇总信息(备份)  
2606 - /// <summary>  
2607 - /// 获取门店某个时间段的开单记录汇总信息(备份)  
2608 - /// </summary>  
2609 - /// <param name="input">查询参数</param>  
2610 - /// <returns>开单记录汇总信息</returns>  
2611 - [HttpGet("GetBillingRecordSummaryByStoreId_bak")]  
2612 - public async Task<dynamic> GetBillingRecordSummaryByStoreId_bak([FromQuery] BillingRecordSummaryQueryInput input)  
2613 - {  
2614 - try  
2615 - {  
2616 - // 验证参数  
2617 - if (string.IsNullOrEmpty(input.StoreId))  
2618 - {  
2619 - throw NCCException.Oh("门店ID不能为空"); 2510 + matchedBillingIds = matchedBillingIds.Intersect(itemMatchedIds).ToList();
  2511 + }
  2512 + else
  2513 + {
  2514 + matchedBillingIds = itemMatchedIds;
  2515 + }
2620 } 2516 }
2621 2517
2622 - // 如果开始时间和结束时间为空,就默认是当月  
2623 - if (input.StartTime == null || input.EndTime == null) 2518 + // 如果传入了健康师筛选条件,收集匹配的开单ID
  2519 + if (!string.IsNullOrEmpty(input.HealthCoachId))
2624 { 2520 {
2625 - input.StartTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);  
2626 - input.EndTime = DateTime.Now.AddDays(DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month));  
2627 - }  
2628 -  
2629 - // 查询开单记录  
2630 - var billingRecords = await _db.Queryable<LqKdKdjlbEntity>()  
2631 - .Where(w => w.Djmd == input.StoreId && w.Kdrq >= input.StartTime && w.Kdrq <= input.EndTime && w.IsEffective == StatusEnum.有效.GetHashCode())  
2632 - .Select(it => new 2521 + hasFilterCondition = true;
  2522 + var healthTeacherMatchedIds = healthTeacherData.Select(x => x.glkdbh).Distinct().ToList();
  2523 + if (matchedBillingIds.Any())
2633 { 2524 {
2634 - id = it.Id,  
2635 - djmd = it.Djmd,  
2636 - jsj = it.Jsj,  
2637 - kdrq = it.Kdrq,  
2638 - gjlx = it.Gjlx,  
2639 - zdyj = it.Zdyj,  
2640 - sfyj = it.Sfyj,  
2641 - qk = it.Qk,  
2642 - kdhyc = SqlFunc.Subqueryable<LqKhxxEntity>().Where(x => x.Id == it.Kdhy).Select(x => x.Khmc),  
2643 - kdhysjh = SqlFunc.Subqueryable<LqKhxxEntity>().Where(x => x.Id == it.Kdhy).Select(x => x.Sjh),  
2644 - fkfs = it.Fkfs, // 付款方式  
2645 - khly = it.Khly, // 客户来源  
2646 - bz = it.Bz, // 备注  
2647 - createTime = it.CreateTime  
2648 - })  
2649 - .ToListAsync();  
2650 -  
2651 - if (!billingRecords.Any())  
2652 - {  
2653 - return new 2525 + matchedBillingIds = matchedBillingIds.Intersect(healthTeacherMatchedIds).ToList();
  2526 + }
  2527 + else
2654 { 2528 {
2655 - success = true,  
2656 - data = new  
2657 - {  
2658 - billingSummary = new  
2659 - {  
2660 - totalCount = 0,  
2661 - totalAmount = 0,  
2662 - totalPaidAmount = 0,  
2663 - totalDebt = 0,  
2664 - billingRecords = new List<object>()  
2665 - },  
2666 - itemSummary = new  
2667 - {  
2668 - purchased = new { count = 0, totalAmount = 0, items = new List<object>() },  
2669 - gifted = new { count = 0, totalAmount = 0, items = new List<object>() },  
2670 - experience = new { count = 0, totalAmount = 0, items = new List<object>() }  
2671 - },  
2672 - healthTeacherSummary = new  
2673 - {  
2674 - totalCount = 0,  
2675 - teachers = new List<object>()  
2676 - }  
2677 - },  
2678 - message = "该时间段内无开单记录"  
2679 - }; 2529 + matchedBillingIds = healthTeacherMatchedIds;
  2530 + }
2680 } 2531 }
2681 2532
2682 - var billingIds = billingRecords.Select(x => x.id).ToList();  
2683 -  
2684 - // 查询品项明细,按F_SourceType分类  
2685 - var itemDetails = await _db.Queryable<LqKdPxmxEntity>()  
2686 - .Where(w => billingIds.Contains(w.Glkdbh) && w.IsEffective == StatusEnum.有效.GetHashCode())  
2687 - .Select(it => new 2533 + // 如果传入了筛选条件,必须过滤开单记录(即使没有匹配数据也要过滤,返回空结果)
  2534 + if (hasFilterCondition)
  2535 + {
  2536 + if (matchedBillingIds.Any())
2688 { 2537 {
2689 - id = it.Id,  
2690 - glkdbh = it.Glkdbh,  
2691 - px = it.Px,  
2692 - pxmc = it.Pxmc,  
2693 - pxjg = it.Pxjg,  
2694 - sourceType = it.SourceType,  
2695 - totalPrice = it.TotalPrice,  
2696 - actualPrice = it.ActualPrice,  
2697 - projectNumber = it.ProjectNumber,  
2698 - remark = it.Remark,  
2699 - itemCategory = it.ItemCategory,  
2700 - })  
2701 - .ToListAsync();  
2702 -  
2703 - // 按来源类型分类品项  
2704 - var purchasedItems = itemDetails.Where(x => x.sourceType == "购买").ToList();  
2705 - var giftedItems = itemDetails.Where(x => x.sourceType == "赠送").ToList();  
2706 - var experienceItems = itemDetails.Where(x => x.sourceType == "体验").ToList();  
2707 -  
2708 - // 查询健康师业绩数据  
2709 - var healthTeacherData = await _db.Queryable<LqKdJksyjEntity>()  
2710 - .Where(w => billingIds.Contains(w.Glkdbh) && w.IsEffective == StatusEnum.有效.GetHashCode())  
2711 - .Select(it => new 2538 + billingRecords = billingRecords.Where(x => matchedBillingIds.Contains(x.id)).ToList();
  2539 + }
  2540 + else
2712 { 2541 {
2713 - id = it.Id,  
2714 - glkdbh = it.Glkdbh,  
2715 - jks = it.Jks,  
2716 - jksxm = it.Jksxm,  
2717 - jkszh = it.Jkszh,  
2718 - jksyj = it.Jksyj,  
2719 - kdpxid = it.Kdpxid,  
2720 - yjsj = it.Yjsj,  
2721 - jsj_id = it.Jsj_id,  
2722 - itemCategory = it.ItemCategory,  
2723 - storeId = it.StoreId,  
2724 - itemId = it.ItemId,  
2725 - itemName = it.ItemName,  
2726 - })  
2727 - .ToListAsync(); 2542 + // 传入了筛选条件但没有匹配数据,返回空结果
  2543 + billingRecords = billingRecords.Where(x => false).ToList();
  2544 + }
  2545 + billingIds = billingRecords.Select(x => x.id).ToList();
  2546 + }
2728 2547
2729 // 构建按开单记录分组的详细数据 2548 // 构建按开单记录分组的详细数据
2730 var detailedRecords = billingRecords.Select(billing => new 2549 var detailedRecords = billingRecords.Select(billing => new
@@ -2736,7 +2555,8 @@ namespace NCC.Extend.LqKdKdjlb @@ -2736,7 +2555,8 @@ namespace NCC.Extend.LqKdKdjlb
2736 storeId = billing.djmd, 2555 storeId = billing.djmd,
2737 goldTriangle = billing.jsj, 2556 goldTriangle = billing.jsj,
2738 customerType = billing.gjlx, 2557 customerType = billing.gjlx,
2739 - 2558 + cooperationInstitution = billing.hgjg,
  2559 + cooperationInstitutionName = billing.hgjgName,
2740 // 品项分类 2560 // 品项分类
2741 purchasedItems = itemDetails.Where(x => x.glkdbh == billing.id && x.sourceType == "购买").Select(x => new 2561 purchasedItems = itemDetails.Where(x => x.glkdbh == billing.id && x.sourceType == "购买").Select(x => new
2742 { 2562 {
@@ -3647,351 +3467,6 @@ namespace NCC.Extend.LqKdKdjlb @@ -3647,351 +3467,6 @@ namespace NCC.Extend.LqKdKdjlb
3647 } 3467 }
3648 #endregion 3468 #endregion
3649 3469
3650 - #region 门店整体统计表(备份)  
3651 - /// <summary>  
3652 - /// 门店整体统计表  
3653 - /// </summary>  
3654 - /// <remarks>  
3655 - /// 统计每个健康师在指定时间周期内的各项数据指标  
3656 - /// 包括:邀约人数、预约人数、到店人数、开单人数、开单金额、消耗金额、人头、人次、消耗项目数  
3657 - ///  
3658 - /// 示例请求:  
3659 - /// ```json  
3660 - /// {  
3661 - /// "startTime": "2025-10-01",  
3662 - /// "endTime": "2025-10-31",  
3663 - /// "departmentId": "部门ID",  
3664 - /// "storeId": "门店ID",  
3665 - /// "employeeName": "健康师姓名"  
3666 - /// }  
3667 - /// ```  
3668 - ///  
3669 - /// 参数说明:  
3670 - /// - startTime: 开始时间(可选,默认为当月1号)  
3671 - /// - endTime: 结束时间(可选,默认为当前时间)  
3672 - /// - departmentId: 事业部ID(可选)  
3673 - /// - storeId: 门店ID(可选)  
3674 - /// - employeeName: 健康师姓名(可选)  
3675 - ///  
3676 - /// 返回字段说明:  
3677 - /// - EmployeeId: 健康师ID  
3678 - /// - EmployeeName: 健康师姓名  
3679 - /// - StoreId: 门店ID  
3680 - /// - StoreName: 门店名称  
3681 - /// - DepartmentId: 事业部ID  
3682 - /// - DepartmentName: 事业部名称  
3683 - /// - InviteCount: 邀约人数(按客户去重)  
3684 - /// - AppointmentCount: 预约人数(按客户去重,无论预约状态)  
3685 - /// - VisitCount: 到店人数(按客户去重,仅统计状态为'已确认'的预约)  
3686 - /// - BillingCount: 开单人数(按开单记录去重)  
3687 - /// - BillingAmount: 开单金额(开单业绩总金额)  
3688 - /// - ConsumeAmount: 消耗金额(消耗业绩总金额)  
3689 - /// - HeadCount: 人头(按客户去重)  
3690 - /// - PersonCount: 人次(按客户+日期去重,同一客户不同天算多次)  
3691 - /// - ProjectCount: 消耗项目数(项目总次数)  
3692 - /// - RefundAmount: 退卡金额(健康师退卡业绩总金额)  
3693 - /// - LaborCost: 手工费(消耗时的手工费总金额)  
3694 - /// - OriginalLaborCost: 原始手工费(消耗时的原始手工费总金额)  
3695 - /// - OvertimeLaborCost: 加班手工费(消耗时的加班手工费总金额)  
3696 - /// </remarks>  
3697 - /// <param name="input">查询参数</param>  
3698 - /// <returns>健康师统计数据列表</returns>  
3699 - /// <response code="200">成功返回统计数据</response>  
3700 - /// <response code="400">参数错误</response>  
3701 - /// <response code="500">服务器错误</response>  
3702 - [HttpGet("get-health-coach-statistics_bak")]  
3703 - public async Task<dynamic> GetHealthCoachStatistics_bak([FromQuery] HealthCoachStatisticsQueryInput input)  
3704 - {  
3705 - try  
3706 - {  
3707 - // 设置默认时间范围(如果未提供,默认为当月)  
3708 - var startTime = input.StartTime ?? new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);  
3709 - var endTime = input.EndTime ?? DateTime.Now;  
3710 -  
3711 - // 构建SQL查询  
3712 - var sql = $@"  
3713 - SELECT  
3714 - u.F_Id as EmployeeId,  
3715 - u.F_REALNAME as EmployeeName,  
3716 - u.F_MDID as StoreId,  
3717 - md.dm as StoreName,  
3718 - md.syb as DepartmentId,  
3719 - dept.F_FullName as DepartmentName,  
3720 -  
3721 - -- 邀约人数  
3722 - COALESCE(invite_stats.InviteCount, 0) as InviteCount,  
3723 -  
3724 - -- 预约人数(无论状态)  
3725 - COALESCE(appointment_stats.AppointmentCount, 0) as AppointmentCount,  
3726 -  
3727 - -- 到店人数(已确认状态)  
3728 - COALESCE(visit_stats.VisitCount, 0) as VisitCount,  
3729 -  
3730 - -- 开单人数和金额  
3731 - COALESCE(billing_stats.BillingCount, 0) as BillingCount,  
3732 - COALESCE(billing_stats.BillingAmount, 0) as BillingAmount,  
3733 -  
3734 - -- 消耗相关统计  
3735 - COALESCE(consume_stats.ConsumeAmount, 0) as ConsumeAmount,  
3736 - CAST(COALESCE(headcount_stats.HeadCount, 0) AS DECIMAL(18,2)) as HeadCount,  
3737 - CAST(COALESCE(personcount_stats.PersonCount, 0) AS DECIMAL(18,2)) as PersonCount,  
3738 - CAST(COALESCE(invalid_headcount_stats.HeadCount, 0) AS DECIMAL(18,2)) as InvalidHeadCount,  
3739 - CAST(COALESCE(invalid_personcount_stats.PersonCount, 0) AS DECIMAL(18,2)) as InvalidPersonCount,  
3740 - CAST(COALESCE(consume_stats.ProjectCount, 0) AS DECIMAL(18,2)) as ProjectCount,  
3741 -  
3742 - -- 退卡金额  
3743 - COALESCE(refund_stats.RefundAmount, 0) as RefundAmount,  
3744 -  
3745 - -- 手工费相关统计  
3746 - COALESCE(consume_stats.LaborCost, 0) as LaborCost,  
3747 - COALESCE(consume_stats.OriginalLaborCost, 0) as OriginalLaborCost,  
3748 - COALESCE(consume_stats.OvertimeLaborCost, 0) as OvertimeLaborCost  
3749 -  
3750 - FROM BASE_USER u  
3751 - LEFT JOIN lq_mdxx md ON u.F_MDID = md.F_Id  
3752 - LEFT JOIN base_organize dept ON md.syb = dept.F_Id  
3753 -  
3754 - -- 邀约统计子查询  
3755 - LEFT JOIN (  
3756 - SELECT  
3757 - yyr as EmployeeId,  
3758 - COUNT(DISTINCT yykh) as InviteCount  
3759 - FROM lq_yaoyjl  
3760 - WHERE yyr IS NOT NULL  
3761 - AND F_CreateTime >= @startTime  
3762 - AND F_CreateTime <= @endTime  
3763 - GROUP BY yyr  
3764 - ) invite_stats ON u.F_Id = invite_stats.EmployeeId  
3765 -  
3766 - -- 预约统计子查询  
3767 - LEFT JOIN (  
3768 - SELECT  
3769 - yyr as EmployeeId,  
3770 - COUNT(DISTINCT gk) as AppointmentCount  
3771 - FROM lq_yyjl  
3772 - WHERE yyr IS NOT NULL  
3773 - AND F_CreateTime >= @startTime  
3774 - AND F_CreateTime <= @endTime  
3775 - GROUP BY yyr  
3776 - ) appointment_stats ON u.F_Id = appointment_stats.EmployeeId  
3777 -  
3778 - -- 到店统计子查询  
3779 - LEFT JOIN (  
3780 - SELECT  
3781 - yyr as EmployeeId,  
3782 - COUNT(DISTINCT gk) as VisitCount  
3783 - FROM lq_yyjl  
3784 - WHERE yyr IS NOT NULL  
3785 - AND F_Status = '已确认'  
3786 - AND F_CreateTime >= @startTime  
3787 - AND F_CreateTime <= @endTime  
3788 - GROUP BY yyr  
3789 - ) visit_stats ON u.F_Id = visit_stats.EmployeeId  
3790 -  
3791 - -- 开单统计子查询  
3792 - LEFT JOIN (  
3793 - SELECT  
3794 - jkszh as EmployeeId,  
3795 - COUNT(DISTINCT glkdbh) as BillingCount,  
3796 - SUM(CAST(jksyj AS DECIMAL(18,2))) as BillingAmount  
3797 - FROM lq_kd_jksyj  
3798 - WHERE jkszh IS NOT NULL  
3799 - AND F_IsEffective = 1  
3800 - AND yjsj >= @startTime  
3801 - AND yjsj <= @endTime  
3802 - GROUP BY jkszh  
3803 - ) billing_stats ON u.F_Id = billing_stats.EmployeeId  
3804 -  
3805 - -- 消耗统计子查询  
3806 - LEFT JOIN (  
3807 - SELECT  
3808 - jksyj.jks as EmployeeId,  
3809 - SUM(jksyj.jksyj) as ConsumeAmount,  
3810 - CAST(SUM(jksyj.F_kdpxNumber) AS DECIMAL(18,2)) as ProjectCount,  
3811 - COALESCE(SUM(jksyj.F_LaborCost), 0) as LaborCost,  
3812 - COALESCE(SUM(jksyj.F_OriginalLaborCost), 0) as OriginalLaborCost,  
3813 - COALESCE(SUM(jksyj.F_OvertimeLaborCost), 0) as OvertimeLaborCost  
3814 - FROM lq_xh_jksyj jksyj  
3815 - INNER JOIN lq_xh_hyhk hyhk ON jksyj.glkdbh = hyhk.F_Id  
3816 - WHERE jksyj.jks IS NOT NULL  
3817 - AND jksyj.F_IsEffective = 1  
3818 - AND hyhk.F_IsEffective = 1  
3819 - AND hyhk.hksj >= @startTime  
3820 - AND hyhk.hksj <= @endTime  
3821 - GROUP BY jksyj.jks  
3822 - ) consume_stats ON u.F_Id = consume_stats.EmployeeId  
3823 -  
3824 - -- 有效人头统计子查询(从人次记录表获取,按月份+客户+数量去重后累加数量,F_HasBilling=1)  
3825 - LEFT JOIN (  
3826 - SELECT  
3827 - F_PersonId as EmployeeId,  
3828 - CAST(COALESCE(SUM(F_Quantity), 0) AS DECIMAL(18,2)) as HeadCount  
3829 - FROM (  
3830 - SELECT  
3831 - F_PersonId,  
3832 - F_WorkMonth,  
3833 - F_MemberId,  
3834 - F_Quantity  
3835 - FROM lq_person_times_record  
3836 - WHERE F_PersonId IS NOT NULL  
3837 - AND F_IsEffective = 1  
3838 - AND F_PersonType = '健康师'  
3839 - AND F_HasBilling = 1  
3840 - AND F_WorkDate >= DATE(@startTime)  
3841 - AND F_WorkDate <= DATE(@endTime)  
3842 - GROUP BY F_PersonId, F_WorkMonth, F_MemberId, F_Quantity  
3843 - ) as distinct_headcount  
3844 - GROUP BY F_PersonId  
3845 - ) headcount_stats ON u.F_Id = headcount_stats.EmployeeId  
3846 -  
3847 - -- 有效人次统计子查询(从人次记录表获取,按日期+客户+数量去重后累加数量,F_HasBilling=1)  
3848 - LEFT JOIN (  
3849 - SELECT  
3850 - F_PersonId as EmployeeId,  
3851 - CAST(COALESCE(SUM(F_Quantity), 0) AS DECIMAL(18,2)) as PersonCount  
3852 - FROM (  
3853 - SELECT  
3854 - F_PersonId,  
3855 - F_WorkDate,  
3856 - F_MemberId,  
3857 - F_Quantity  
3858 - FROM lq_person_times_record  
3859 - WHERE F_PersonId IS NOT NULL  
3860 - AND F_IsEffective = 1  
3861 - AND F_PersonType = '健康师'  
3862 - AND F_HasBilling = 1  
3863 - AND F_WorkDate >= DATE(@startTime)  
3864 - AND F_WorkDate <= DATE(@endTime)  
3865 - GROUP BY F_PersonId, F_WorkDate, F_MemberId, F_Quantity  
3866 - ) as distinct_personcount  
3867 - GROUP BY F_PersonId  
3868 - ) personcount_stats ON u.F_Id = personcount_stats.EmployeeId  
3869 -  
3870 - -- 无效人头统计子查询(从人次记录表获取,按月份+客户+数量去重后累加数量,F_HasBilling=0)  
3871 - LEFT JOIN (  
3872 - SELECT  
3873 - F_PersonId as EmployeeId,  
3874 - CAST(COALESCE(SUM(F_Quantity), 0) AS DECIMAL(18,2)) as HeadCount  
3875 - FROM (  
3876 - SELECT  
3877 - F_PersonId,  
3878 - F_WorkMonth,  
3879 - F_MemberId,  
3880 - F_Quantity  
3881 - FROM lq_person_times_record  
3882 - WHERE F_PersonId IS NOT NULL  
3883 - AND F_IsEffective = 1  
3884 - AND F_PersonType = '健康师'  
3885 - AND F_HasBilling = 0  
3886 - AND F_WorkDate >= DATE(@startTime)  
3887 - AND F_WorkDate <= DATE(@endTime)  
3888 - GROUP BY F_PersonId, F_WorkMonth, F_MemberId, F_Quantity  
3889 - ) as distinct_headcount  
3890 - GROUP BY F_PersonId  
3891 - ) invalid_headcount_stats ON u.F_Id = invalid_headcount_stats.EmployeeId  
3892 -  
3893 - -- 无效人次统计子查询(从人次记录表获取,按日期+客户+数量去重后累加数量,F_HasBilling=0)  
3894 - LEFT JOIN (  
3895 - SELECT  
3896 - F_PersonId as EmployeeId,  
3897 - CAST(COALESCE(SUM(F_Quantity), 0) AS DECIMAL(18,2)) as PersonCount  
3898 - FROM (  
3899 - SELECT  
3900 - F_PersonId,  
3901 - F_WorkDate,  
3902 - F_MemberId,  
3903 - F_Quantity  
3904 - FROM lq_person_times_record  
3905 - WHERE F_PersonId IS NOT NULL  
3906 - AND F_IsEffective = 1  
3907 - AND F_PersonType = '健康师'  
3908 - AND F_HasBilling = 0  
3909 - AND F_WorkDate >= DATE(@startTime)  
3910 - AND F_WorkDate <= DATE(@endTime)  
3911 - GROUP BY F_PersonId, F_WorkDate, F_MemberId, F_Quantity  
3912 - ) as distinct_personcount  
3913 - GROUP BY F_PersonId  
3914 - ) invalid_personcount_stats ON u.F_Id = invalid_personcount_stats.EmployeeId  
3915 -  
3916 - -- 退卡统计子查询  
3917 - LEFT JOIN (  
3918 - SELECT  
3919 - jkszh as EmployeeId,  
3920 - SUM(CAST(jksyj AS DECIMAL(18,2))) as RefundAmount  
3921 - FROM lq_hytk_jksyj  
3922 - WHERE jkszh IS NOT NULL  
3923 - AND F_IsEffective = 1  
3924 - AND tksj >= @startTime  
3925 - AND tksj <= @endTime  
3926 - GROUP BY jkszh  
3927 - ) refund_stats ON u.F_Id = refund_stats.EmployeeId  
3928 -  
3929 - WHERE u.F_GW = '健康师'  
3930 - ";  
3931 -  
3932 - // 添加条件过滤  
3933 - var conditions = new List<string>();  
3934 - var parameters = new List<SugarParameter>  
3935 - {  
3936 - new SugarParameter("@startTime", startTime),  
3937 - new SugarParameter("@endTime", endTime)  
3938 - };  
3939 -  
3940 - if (!string.IsNullOrEmpty(input.DepartmentId))  
3941 - {  
3942 - conditions.Add("md.syb = @departmentId");  
3943 - parameters.Add(new SugarParameter("@departmentId", input.DepartmentId));  
3944 - }  
3945 -  
3946 - if (!string.IsNullOrEmpty(input.StoreId))  
3947 - {  
3948 - conditions.Add("u.F_MDID = @storeId");  
3949 - parameters.Add(new SugarParameter("@storeId", input.StoreId));  
3950 - }  
3951 -  
3952 - if (!string.IsNullOrEmpty(input.EmployeeName))  
3953 - {  
3954 - conditions.Add("u.F_REALNAME LIKE @employeeName");  
3955 - parameters.Add(new SugarParameter("@employeeName", $"%{input.EmployeeName}%"));  
3956 - }  
3957 -  
3958 - if (conditions.Any())  
3959 - {  
3960 - sql += " AND " + string.Join(" AND ", conditions);  
3961 - }  
3962 -  
3963 - sql += " ORDER BY u.F_REALNAME";  
3964 -  
3965 - // 执行查询  
3966 - var allData = await _db.Ado.SqlQueryAsync<HealthCoachStatisticsOutput>(sql, parameters);  
3967 -  
3968 - // 手动分页  
3969 - var totalCount = allData.Count;  
3970 - var pagedData = allData  
3971 - .Skip((input.currentPage - 1) * input.pageSize)  
3972 - .Take(input.pageSize)  
3973 - .ToList();  
3974 -  
3975 - // 直接返回分页结果  
3976 - return new  
3977 - {  
3978 - list = pagedData,  
3979 - pagination = new  
3980 - {  
3981 - pageIndex = input.currentPage,  
3982 - pageSize = input.pageSize,  
3983 - totalCount = totalCount  
3984 - }  
3985 - };  
3986 - }  
3987 - catch (Exception ex)  
3988 - {  
3989 - _logger.LogError(ex, "获取健康师统计数据失败");  
3990 - throw NCCException.Oh($"获取健康师统计数据失败:{ex.Message}");  
3991 - }  
3992 - }  
3993 - #endregion  
3994 -  
3995 #region 获取开单品项明细记录列表 3470 #region 获取开单品项明细记录列表
3996 /// <summary> 3471 /// <summary>
3997 /// 获取开单品项明细记录列表(分页) 3472 /// 获取开单品项明细记录列表(分页)
@@ -4274,7 +3749,11 @@ namespace NCC.Extend.LqKdKdjlb @@ -4274,7 +3749,11 @@ namespace NCC.Extend.LqKdKdjlb
4274 var sidx = string.IsNullOrEmpty(input.sidx) ? "CreateTime" : input.sidx; 3749 var sidx = string.IsNullOrEmpty(input.sidx) ? "CreateTime" : input.sidx;
4275 3750
4276 // 构建基础查询:储扣信息 JOIN 开单记录 JOIN 客户信息 JOIN 门店信息 3751 // 构建基础查询:储扣信息 JOIN 开单记录 JOIN 客户信息 JOIN 门店信息
4277 - var baseQuery = _db.Queryable<LqKdDeductinfoEntity, LqKdKdjlbEntity, LqKhxxEntity, LqMdxxEntity>((deduct, billing, member, store) => deduct.BillingId == billing.Id && billing.Kdhy == member.Id && billing.Djmd == store.Id) 3752 + var baseQuery = _db.Queryable<LqKdDeductinfoEntity, LqKdKdjlbEntity, LqKhxxEntity, LqMdxxEntity>(
  3753 + (deduct, billing, member, store) =>
  3754 + deduct.BillingId == billing.Id &&
  3755 + billing.Kdhy == member.Id &&
  3756 + billing.Djmd == store.Id)
4278 .WhereIF(!string.IsNullOrEmpty(input.DeductType), (deduct, billing, member, store) => deduct.DeductType == input.DeductType) 3757 .WhereIF(!string.IsNullOrEmpty(input.DeductType), (deduct, billing, member, store) => deduct.DeductType == input.DeductType)
4279 .WhereIF(!string.IsNullOrEmpty(input.DeductId), (deduct, billing, member, store) => deduct.DeductId == input.DeductId) 3758 .WhereIF(!string.IsNullOrEmpty(input.DeductId), (deduct, billing, member, store) => deduct.DeductId == input.DeductId)
4280 .WhereIF(!string.IsNullOrEmpty(input.BillingId), (deduct, billing, member, store) => deduct.BillingId == input.BillingId) 3759 .WhereIF(!string.IsNullOrEmpty(input.BillingId), (deduct, billing, member, store) => deduct.BillingId == input.BillingId)
@@ -4294,7 +3773,7 @@ namespace NCC.Extend.LqKdKdjlb @@ -4294,7 +3773,7 @@ namespace NCC.Extend.LqKdKdjlb
4294 (billing.Id != null && billing.Id.Contains(input.keyword))); 3773 (billing.Id != null && billing.Id.Contains(input.keyword)));
4295 3774
4296 3775
4297 - // 查询并分页 3776 + // 查询并分页,使用子查询获取开单类型
4298 var data = await baseQuery.Select((deduct, billing, member, store) => new LqKdDeductinfoListOutput 3777 var data = await baseQuery.Select((deduct, billing, member, store) => new LqKdDeductinfoListOutput
4299 { 3778 {
4300 Id = deduct.Id ?? "", 3779 Id = deduct.Id ?? "",
@@ -4314,7 +3793,12 @@ namespace NCC.Extend.LqKdKdjlb @@ -4314,7 +3793,12 @@ namespace NCC.Extend.LqKdKdjlb
4314 MemberName = member.Khmc ?? "", 3793 MemberName = member.Khmc ?? "",
4315 MemberPhone = member.Sjh ?? "", 3794 MemberPhone = member.Sjh ?? "",
4316 StoreId = billing.Djmd ?? "", 3795 StoreId = billing.Djmd ?? "",
4317 - StoreName = store.Dm ?? "" 3796 + StoreName = store.Dm ?? "",
  3797 + TimePeriod = billing.Kdrq,
  3798 + BillingType = SqlFunc.Subqueryable<LqKdPxmxEntity>()
  3799 + .Where(pxmx => pxmx.Id == deduct.DeductId && pxmx.Px == deduct.ItemId)
  3800 + .Select(pxmx => pxmx.SourceType),
  3801 + CooperationInstitution = billing.Hgjg ?? ""
4318 }).MergeTable().OrderBy(sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize); 3802 }).MergeTable().OrderBy(sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
4319 3803
4320 return PageResult<LqKdDeductinfoListOutput>.SqlSugarPageResult(data); 3804 return PageResult<LqKdDeductinfoListOutput>.SqlSugarPageResult(data);
netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
@@ -2133,7 +2133,7 @@ namespace NCC.Extend.LqStatistics @@ -2133,7 +2133,7 @@ namespace NCC.Extend.LqStatistics
2133 ) personcount_stats ON jksyj.jkszh = personcount_stats.jkszh AND hyhk.md = personcount_stats.md 2133 ) personcount_stats ON jksyj.jkszh = personcount_stats.jkszh AND hyhk.md = personcount_stats.md
2134 WHERE jksyj.F_IsEffective = 1 2134 WHERE jksyj.F_IsEffective = 1
2135 AND DATE_FORMAT(hyhk.hksj, '%Y%m') = @statisticsMonth 2135 AND DATE_FORMAT(hyhk.hksj, '%Y%m') = @statisticsMonth
2136 - GROUP BY jksyj.jkszh, jksyj.jksxm, hyhk.md, md.mdbm, md.dm, headcount_stats.F_HeadCount, personcount_stats.F_PersonCount"; 2136 + GROUP BY jksyj.jks, jksyj.jksxm, hyhk.md, md.mdbm, md.dm, headcount_stats.F_HeadCount, personcount_stats.F_PersonCount";
2137 2137
2138 var healthCoachData = await _db.Ado.SqlQueryAsync<dynamic>(healthCoachSql, new { statisticsMonth }); 2138 var healthCoachData = await _db.Ado.SqlQueryAsync<dynamic>(healthCoachSql, new { statisticsMonth });
2139 foreach (var item in healthCoachData) 2139 foreach (var item in healthCoachData)
netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
@@ -777,48 +777,48 @@ namespace NCC.Extend.LqXhHyhk @@ -777,48 +777,48 @@ namespace NCC.Extend.LqXhHyhk
777 .OrderBy($"{sidx} {sort}") 777 .OrderBy($"{sidx} {sort}")
778 .ToPagedListAsync(input.currentPage, input.pageSize); 778 .ToPagedListAsync(input.currentPage, input.pageSize);
779 779
780 - // 获取当前页的耗卡记录ID列表  
781 - var consumeIds = data.list.Select(x => x.id).ToList(); 780 + // 获取当前页的耗卡记录ID列表
  781 + var consumeIds = data.list.Select(x => x.id).ToList();
782 782
783 - // 批量查询耗卡明细  
784 - var consumeDetails = new List<LqXhPxmxInfoOutput>();  
785 - if (consumeIds.Any())  
786 - {  
787 - consumeDetails = await _db.Queryable<LqXhPxmxEntity>()  
788 - .Where(x => consumeIds.Contains(x.ConsumeInfoId) && x.IsEffective == StatusEnum.有效.GetHashCode())  
789 - .Select(x => new LqXhPxmxInfoOutput  
790 - {  
791 - id = x.Id,  
792 - consumeInfoId = x.ConsumeInfoId,  
793 - billingItemId = x.BillingItemId,  
794 - px = x.Px,  
795 - pxmc = x.Pxmc,  
796 - pxjg = x.Pxjg,  
797 - memberId = x.MemberId,  
798 - createTime = x.CreateTIme,  
799 - projectNumber = x.ProjectNumber,  
800 - originalProjectNumber = x.OriginalProjectNumber,  
801 - overtimeProjectNumber = x.OvertimeProjectNumber,  
802 - sourceType = x.SourceType,  
803 - totalPrice = x.TotalPrice,  
804 - isEffective = x.IsEffective,  
805 - })  
806 - .ToListAsync();  
807 - } 783 + // 批量查询耗卡明细
  784 + var consumeDetails = new List<LqXhPxmxInfoOutput>();
  785 + if (consumeIds.Any())
  786 + {
  787 + consumeDetails = await _db.Queryable<LqXhPxmxEntity>()
  788 + .Where(x => consumeIds.Contains(x.ConsumeInfoId) && x.IsEffective == StatusEnum.有效.GetHashCode())
  789 + .Select(x => new LqXhPxmxInfoOutput
  790 + {
  791 + id = x.Id,
  792 + consumeInfoId = x.ConsumeInfoId,
  793 + billingItemId = x.BillingItemId,
  794 + px = x.Px,
  795 + pxmc = x.Pxmc,
  796 + pxjg = x.Pxjg,
  797 + memberId = x.MemberId,
  798 + createTime = x.CreateTIme,
  799 + projectNumber = x.ProjectNumber,
  800 + originalProjectNumber = x.OriginalProjectNumber,
  801 + overtimeProjectNumber = x.OvertimeProjectNumber,
  802 + sourceType = x.SourceType,
  803 + totalPrice = x.TotalPrice,
  804 + isEffective = x.IsEffective,
  805 + })
  806 + .ToListAsync();
  807 + }
808 808
809 - // 按耗卡记录ID分组耗卡明细  
810 - var consumeDetailsGrouped = consumeDetails.GroupBy(x => x.consumeInfoId)  
811 - .ToDictionary(g => g.Key, g => g.ToList()); 809 + // 按耗卡记录ID分组耗卡明细
  810 + var consumeDetailsGrouped = consumeDetails.GroupBy(x => x.consumeInfoId)
  811 + .ToDictionary(g => g.Key, g => g.ToList());
812 812
813 - // 为每个耗卡记录分配耗卡明细  
814 - foreach (var item in data.list)  
815 - {  
816 - item.ConsumeDetails = consumeDetailsGrouped.ContainsKey(item.id)  
817 - ? consumeDetailsGrouped[item.id]  
818 - : new List<LqXhPxmxInfoOutput>();  
819 - } 813 + // 为每个耗卡记录分配耗卡明细
  814 + foreach (var item in data.list)
  815 + {
  816 + item.ConsumeDetails = consumeDetailsGrouped.ContainsKey(item.id)
  817 + ? consumeDetailsGrouped[item.id]
  818 + : new List<LqXhPxmxInfoOutput>();
  819 + }
820 820
821 - return PageResult<LqXhHyhkListOutput>.SqlSugarPageResult(data); 821 + return PageResult<LqXhHyhkListOutput>.SqlSugarPageResult(data);
822 } 822 }
823 catch (Exception ex) 823 catch (Exception ex)
824 { 824 {
@@ -1390,6 +1390,8 @@ namespace NCC.Extend.LqXhHyhk @@ -1390,6 +1390,8 @@ namespace NCC.Extend.LqXhHyhk
1390 } 1390 }
1391 } 1391 }
1392 } 1392 }
  1393 + //查询开单记录
  1394 + var billingRecord = await _db.Queryable<LqKdKdjlbEntity>().Where(x => x.Kdhy == entity.Hy && x.IsEffective == StatusEnum.有效.GetHashCode() && x.Sfyj > 0).AnyAsync();
1393 //剔除所有T区健康师(姓名中包含"T区"的健康师) 1395 //剔除所有T区健康师(姓名中包含"T区"的健康师)
1394 var NoTallJksyjEntities = allJksyjEntities.Where(x => x.Jks != null && x.Jks != "" && (x.Jksxm == null || !x.Jksxm.Contains("T区"))).ToList(); 1396 var NoTallJksyjEntities = allJksyjEntities.Where(x => x.Jks != null && x.Jks != "" && (x.Jksxm == null || !x.Jksxm.Contains("T区"))).ToList();
1395 //获取这次耗卡有多少个健康师 1397 //获取这次耗卡有多少个健康师
@@ -1412,6 +1414,7 @@ namespace NCC.Extend.LqXhHyhk @@ -1412,6 +1414,7 @@ namespace NCC.Extend.LqXhHyhk
1412 Quantity = 1 / (decimal)jksCount, 1414 Quantity = 1 / (decimal)jksCount,
1413 CreateTime = DateTime.Now, 1415 CreateTime = DateTime.Now,
1414 IsEffective = StatusEnum.有效.GetHashCode(), 1416 IsEffective = StatusEnum.有效.GetHashCode(),
  1417 + HasBilling = billingRecord ? 1 : 0,
1415 }; 1418 };
1416 allPersonTimesRecordEntities.Add(personTimesRecordEntity); 1419 allPersonTimesRecordEntities.Add(personTimesRecordEntity);
1417 } 1420 }
@@ -1437,6 +1440,7 @@ namespace NCC.Extend.LqXhHyhk @@ -1437,6 +1440,7 @@ namespace NCC.Extend.LqXhHyhk
1437 Quantity = 1 / (decimal)kjbCount, 1440 Quantity = 1 / (decimal)kjbCount,
1438 CreateTime = DateTime.Now, 1441 CreateTime = DateTime.Now,
1439 IsEffective = StatusEnum.有效.GetHashCode(), 1442 IsEffective = StatusEnum.有效.GetHashCode(),
  1443 + HasBilling = billingRecord ? 1 : 0,
1440 }; 1444 };
1441 allPersonTimesRecordEntities.Add(personTimesRecordEntity); 1445 allPersonTimesRecordEntities.Add(personTimesRecordEntity);
1442 } 1446 }
sql/修复人次记录HasBilling字段.sql 0 → 100644
  1 +-- 修复人次记录表中F_HasBilling字段
  2 +-- 对于耗卡类型的人次记录,如果会员有开单记录(F_IsEffective=1且Sfyj>0),则设置F_HasBilling=1
  3 +
  4 +-- 1. 先查看需要修复的记录数量
  5 +SELECT COUNT(*) as need_fix_count
  6 +FROM lq_person_times_record ptr
  7 +WHERE ptr.F_BusinessType = '耗卡'
  8 + AND ptr.F_HasBilling = 0
  9 + AND ptr.F_MemberId IS NOT NULL
  10 + AND ptr.F_MemberId != ''
  11 + AND EXISTS (
  12 + SELECT 1
  13 + FROM lq_kd_kdjlb kd
  14 + WHERE kd.Kdhy = ptr.F_MemberId
  15 + AND kd.F_IsEffective = 1
  16 + AND kd.Sfyj > 0
  17 + );
  18 +
  19 +-- 2. 修复耗卡类型的人次记录
  20 +UPDATE lq_person_times_record ptr
  21 +INNER JOIN (
  22 + SELECT DISTINCT Kdhy
  23 + FROM lq_kd_kdjlb
  24 + WHERE F_IsEffective = 1
  25 + AND Sfyj > 0
  26 +) kd ON ptr.F_MemberId = kd.Kdhy
  27 +SET ptr.F_HasBilling = 1
  28 +WHERE ptr.F_BusinessType = '耗卡'
  29 + AND ptr.F_HasBilling = 0
  30 + AND ptr.F_MemberId IS NOT NULL
  31 + AND ptr.F_MemberId != '';
  32 +
  33 +-- 3. 验证修复结果(可选)
  34 +SELECT COUNT(*) as fixed_count
  35 +FROM lq_person_times_record ptr
  36 +WHERE ptr.F_BusinessType = '耗卡'
  37 + AND ptr.F_HasBilling = 1
  38 + AND ptr.F_MemberId IS NOT NULL
  39 + AND ptr.F_MemberId != ''
  40 + AND EXISTS (
  41 + SELECT 1
  42 + FROM lq_kd_kdjlb kd
  43 + WHERE kd.Kdhy = ptr.F_MemberId
  44 + AND kd.F_IsEffective = 1
  45 + AND kd.Sfyj > 0
  46 + );
  47 +
项目信息-薪酬规则与名词解释.md
@@ -124,8 +124,8 @@ @@ -124,8 +124,8 @@
124 124
125 ### 顾问提成规则 125 ### 顾问提成规则
126 126
127 -- **高级顾问**:战队总业绩 ≥ 6万元 且 组员业绩达到40%以上 且 消耗达到6万元 → 团队总业绩0.8%  
128 -- **普通顾问**:战队总业绩 ≥ 4万元 且 组员业绩达到30%以上 且 消耗达到4万元 → 团队总业绩0.3% 127 +- 战队总业绩 ≥ 6万元 且 组员业绩达到40%以上 且 消耗达到6万元 → 团队总业绩0.8%
  128 +- 战队总业绩 ≥ 4万元 且 组员业绩达到30%以上 且 消耗达到4万元 → 团队总业绩0.3%
129 129
130 ### 店助考核规则 130 ### 店助考核规则
131 131