From 63df7ccb830b7faef56be2b3308e5b7a4bb670dd Mon Sep 17 00:00:00 2001 From: “wangming” <“wangming@antissoft.com”> Date: Mon, 20 Oct 2025 17:51:45 +0800 Subject: [PATCH] 1 --- netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkCrInput.cs | 5 +++++ netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkInfoOutput.cs | 5 +++++ netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs | 5 +++++ netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkUpInput.cs | 5 +++++ netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardInput.cs | 117 --------------------------------------------------------------------------------------------------------------------- netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs | 1 + netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_hytk/LqHytkHytkEntity.cs | 6 ++++++ netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs | 1 + netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs | 516 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------------- netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------- netcore/src/Modularity/Extend/NCC.Extend/LqXmzlService.cs | 13 ++++++++++--- 11 files changed, 653 insertions(+), 243 deletions(-) diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkCrInput.cs index cf559c9..ba7f7eb 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkCrInput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkCrInput.cs @@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk public decimal? tkje { get; set; } /// + /// 实退金额 + /// + public decimal? actualRefundAmount { get; set; } + + /// /// 手工费用 /// public decimal? sgfy { get; set; } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkInfoOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkInfoOutput.cs index d6b4825..f921982 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkInfoOutput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkInfoOutput.cs @@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk public decimal? tkje { get; set; } /// + /// 实退金额 + /// + public decimal? actualRefundAmount { get; set; } + + /// /// 手工费用 /// public decimal? sgfy { get; set; } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs index aa19208..4aeee69 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs @@ -53,6 +53,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk public decimal? tkje { get; set; } /// + /// 实退金额 + /// + public decimal? actualRefundAmount { get; set; } + + /// /// 手工费用 /// public decimal? sgfy { get; set; } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkUpInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkUpInput.cs index 1e15120..9ee7290 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkUpInput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkUpInput.cs @@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk public decimal? tkje { get; set; } /// + /// 实退金额 + /// + public decimal? actualRefundAmount { get; set; } + + /// /// 手工费用 /// public decimal? sgfy { get; set; } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardInput.cs index 6952310..99c8d24 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardInput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardInput.cs @@ -46,8 +46,6 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb [Display(Name = "转卡备注")] public string Remarks { get; set; } - - /// /// 门店ID /// @@ -109,120 +107,5 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb [Display(Name = "来源类型")] public string SourceType { get; set; } = "转卡"; - /// - /// 健康师业绩列表 - /// - [Display(Name = "健康师业绩列表")] - public List HealthTeacherPerformances { get; set; } - - /// - /// 科技部老师业绩列表 - /// - [Display(Name = "科技部老师业绩列表")] - public List TechTeacherPerformances { get; set; } - } - - /// - /// 转卡健康师业绩输入参数 - /// - public class TransferHealthTeacherPerformanceInput - { - /// - /// 健康师ID - /// - [Required(ErrorMessage = "健康师ID不能为空")] - [StringLength(50, ErrorMessage = "健康师ID长度不能超过50个字符")] - [Display(Name = "健康师ID")] - public string HealthTeacherId { get; set; } - - /// - /// 健康师姓名 - /// - [Required(ErrorMessage = "健康师姓名不能为空")] - [StringLength(50, ErrorMessage = "健康师姓名长度不能超过50个字符")] - [Display(Name = "健康师姓名")] - public string HealthTeacherName { get; set; } - - /// - /// 健康师账号 - /// - [StringLength(50, ErrorMessage = "健康师账号长度不能超过50个字符")] - [Display(Name = "健康师账号")] - public string HealthTeacherAccount { get; set; } - - /// - /// 业绩金额 - /// - [Required(ErrorMessage = "业绩金额不能为空")] - [Range(0, double.MaxValue, ErrorMessage = "业绩金额不能为负数")] - [Display(Name = "业绩金额")] - public decimal PerformanceAmount { get; set; } - - /// - /// 人工成本 - /// - [Range(0, double.MaxValue, ErrorMessage = "人工成本不能为负数")] - [Display(Name = "人工成本")] - public decimal LaborCost { get; set; } - - /// - /// 品项数量 - /// - [Required(ErrorMessage = "品项数量不能为空")] - [Range(1, int.MaxValue, ErrorMessage = "品项数量必须大于0")] - [Display(Name = "品项数量")] - public int ItemQuantity { get; set; } - } - - /// - /// 转卡科技部老师业绩输入参数 - /// - public class TransferTechTeacherPerformanceInput - { - /// - /// 科技部老师ID - /// - [Required(ErrorMessage = "科技部老师ID不能为空")] - [StringLength(50, ErrorMessage = "科技部老师ID长度不能超过50个字符")] - [Display(Name = "科技部老师ID")] - public string TechTeacherId { get; set; } - - /// - /// 科技部老师姓名 - /// - [Required(ErrorMessage = "科技部老师姓名不能为空")] - [StringLength(50, ErrorMessage = "科技部老师姓名长度不能超过50个字符")] - [Display(Name = "科技部老师姓名")] - public string TechTeacherName { get; set; } - - /// - /// 科技部老师账号 - /// - [StringLength(50, ErrorMessage = "科技部老师账号长度不能超过50个字符")] - [Display(Name = "科技部老师账号")] - public string TechTeacherAccount { get; set; } - - /// - /// 业绩金额 - /// - [Required(ErrorMessage = "业绩金额不能为空")] - [Range(0, double.MaxValue, ErrorMessage = "业绩金额不能为负数")] - [Display(Name = "业绩金额")] - public decimal PerformanceAmount { get; set; } - - /// - /// 人工成本 - /// - [Range(0, double.MaxValue, ErrorMessage = "人工成本不能为负数")] - [Display(Name = "人工成本")] - public decimal LaborCost { get; set; } - - /// - /// 品项数量 - /// - [Required(ErrorMessage = "品项数量不能为空")] - [Range(1, int.MaxValue, ErrorMessage = "品项数量必须大于0")] - [Display(Name = "品项数量")] - public int ItemQuantity { get; set; } } } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs index 55d0219..6c8a987 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs @@ -59,6 +59,7 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk /// public string xfje { get; set; } + /// /// 手工费用 /// diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_hytk/LqHytkHytkEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_hytk/LqHytkHytkEntity.cs index 6905bc1..745854c 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_hytk/LqHytkHytkEntity.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_hytk/LqHytkHytkEntity.cs @@ -67,6 +67,12 @@ namespace NCC.Extend.Entitys.lq_hytk_hytk public decimal? Tkje { get; set; } /// + /// 实退金额 + /// + [SugarColumn(ColumnName = "F_ActualRefundAmount")] + public decimal? ActualRefundAmount { get; set; } + + /// /// 手工费用 /// [SugarColumn(ColumnName = "sgfy")] diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs index b5e80d6..f94c400 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs @@ -116,6 +116,7 @@ namespace NCC.Extend.LqHytkHytk fileUrl = it.FileUrl, isEffective = it.IsEffective, cancelRemark = it.CancelRemark, + actualRefundAmount = it.ActualRefundAmount }) .MergeTable() .OrderBy(sidx + " " + input.sort) diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs index a58c258..6b63c97 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs @@ -2414,7 +2414,6 @@ namespace NCC.Extend.LqKdKdjlb { // 开启事务 _db.BeginTran(); - // 1. 验证转出和转入会员是否存在 var fromMember = await _db.Queryable().Where(x => x.Id == input.FromMemberId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync(); if (fromMember == null) @@ -2446,6 +2445,7 @@ namespace NCC.Extend.LqKdKdjlb // 3. 创建退卡记录(转出方) var refundId = YitIdHelper.NextId().ToString(); + var totalRefundAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity); var refundEntity = new LqHytkHytkEntity { Id = refundId, @@ -2457,7 +2457,8 @@ namespace NCC.Extend.LqKdKdjlb Hymc = fromMember.Khmc, Md = input.StoreId, SignatureFile = input.SignatureFile, - Tkje = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity), + Tkje = totalRefundAmount, + ActualRefundAmount = totalRefundAmount, // 转卡时实退金额等于退卡总金额 Tkyy = "转卡", Bz = $"转卡给会员:{toMember.Khmc},{input.Remarks}" }; @@ -2466,10 +2467,15 @@ namespace NCC.Extend.LqKdKdjlb // 4. 创建退卡品项明细和业绩记录 var refundMxEntities = new List(); var refundJksyjEntities = new List(); + var refundKjbsyjEntities = new List(); foreach (var item in input.TransferItems) { + var refundPxmxEntity = _db.Queryable().First(p => p.Id == item.BillingItemId); + //计算品项扣除总金额 + var 品项扣除总金额 = refundPxmxEntity.Pxjg * item.TransferQuantity; + //保存退卡明细表 var refundMxEntity = new LqHytkMxEntity { Id = YitIdHelper.NextId().ToString(), @@ -2480,63 +2486,61 @@ namespace NCC.Extend.LqKdKdjlb Px = item.ItemId, Pxmc = item.ItemName, Pxjg = item.ItemPrice, - Tkje = item.ItemPrice * item.TransferQuantity, + Tkje = 品项扣除总金额, ProjectNumber = item.TransferQuantity, SourceType = item.SourceType, - TotalPrice = item.ItemPrice * item.TransferQuantity, + TotalPrice = 品项扣除总金额, IsEffective = StatusEnum.有效.GetHashCode() }; refundMxEntities.Add(refundMxEntity); - - // 创建退卡健康师业绩记录 - if (item.HealthTeacherPerformances != null && item.HealthTeacherPerformances.Any()) + var refundKdyjEntities = _db.Queryable().Where(p => p.Kdpxid == item.BillingItemId).ToList(); + //保存退卡健康师业绩表 + foreach (var jks in refundKdyjEntities) { - foreach (var jks in item.HealthTeacherPerformances) + //获取健康师当月金三角id + var monthString = DateTime.Now.ToString("yyyyMM"); + var GetMonTeam = _db.Queryable().Where(p => p.UserId == jks.Jks && p.Month == monthString).First(); + //获取本月 + refundJksyjEntities.Add(new LqHytkJksyjEntity { - refundJksyjEntities.Add(new LqHytkJksyjEntity - { - Id = YitIdHelper.NextId().ToString(), - Gltkbh = refundId, - Jks = jks.HealthTeacherId, - Jksxm = jks.HealthTeacherName, - Jkszh = jks.HealthTeacherAccount, - Jksyj = jks.PerformanceAmount, - Tksj = transferTime, - F_jsjid = jks.HealthTeacherId, - F_tkpxid = refundMxEntity.Id, - F_LaborCost = jks.LaborCost, - F_tkpxNumber = jks.ItemQuantity, - F_CreateTime = transferTime, - F_CreateUser = userInfo.userId, - CardReturn = refundMxEntity.Id, - IsEffective = StatusEnum.有效.GetHashCode() - }); - } + Id = YitIdHelper.NextId().ToString(), + Gltkbh = refundId, + Jks = jks.Jks, + Jksxm = jks.Jksxm, + Jkszh = jks.Jkszh, + Jksyj = (品项扣除总金额 / refundKdyjEntities.Count()), + Tksj = DateTime.Now, + F_jsjid = GetMonTeam.JsjId, + F_tkpxid = refundMxEntity.Id, + F_tkpxNumber = item.TransferQuantity, + F_CreateTime = transferTime, + F_CreateUser = userInfo.userId, + CardReturn = refundMxEntity.Id, + IsEffective = StatusEnum.有效.GetHashCode() + }); } - + //查询科技部老师的业绩 + var TechTeacherEntities = _db.Queryable().Where(p => p.Kdpxid == item.BillingItemId).ToList(); // 创建退卡科技部老师业绩记录 - if (item.TechTeacherPerformances != null && item.TechTeacherPerformances.Any()) + foreach (var kjbs in TechTeacherEntities) { - foreach (var kjbs in item.TechTeacherPerformances) + refundKjbsyjEntities.Add(new LqHytkKjbsyjEntity { - refundKjbsyjEntities.Add(new LqHytkKjbsyjEntity - { - Id = YitIdHelper.NextId().ToString(), - Gltkbh = refundId, - Kjbls = kjbs.TechTeacherId, - Kjblsxm = kjbs.TechTeacherName, - Kjblszh = kjbs.TechTeacherAccount, - Kjblsyj = kjbs.PerformanceAmount, - Tksj = transferTime, - F_tkpxid = refundMxEntity.Id, - F_LaborCost = kjbs.LaborCost, - F_tkpxNumber = kjbs.ItemQuantity, - F_CreateTime = transferTime, - F_CreateUser = userInfo.userId, - CardReturn = refundMxEntity.Id, - IsEffective = StatusEnum.有效.GetHashCode() - }); - } + Id = YitIdHelper.NextId().ToString(), + Gltkbh = refundId, + Kjbls = kjbs.Kjbls, + Kjblsxm = kjbs.Kjblsxm, + Kjblszh = kjbs.Kjblszh, + Kjblsyj = (品项扣除总金额 / TechTeacherEntities.Count()), + Tksj = transferTime, + F_tkpxid = refundMxEntity.Id, + F_LaborCost = kjbs.LaborCost, + F_tkpxNumber = item.TransferQuantity, + F_CreateTime = transferTime, + F_CreateUser = userInfo.userId, + CardReturn = refundMxEntity.Id, + IsEffective = StatusEnum.有效.GetHashCode() + }); } } @@ -2561,6 +2565,8 @@ namespace NCC.Extend.LqKdKdjlb CreateUser = userInfo.userId, Kdhy = input.ToMemberId, Djmd = input.StoreId, + Fkfs = "转卡", + Sfskdd = "否", Sfyj = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity), Bz = $"从会员 {fromMember.Khmc} 转入,{input.Remarks}" }; @@ -2591,46 +2597,37 @@ namespace NCC.Extend.LqKdKdjlb }; billingPxmxEntities.Add(billingPxmxEntity); - // 创建开卡健康师业绩记录 - if (item.HealthTeacherPerformances != null && item.HealthTeacherPerformances.Any()) + foreach (var jks in refundJksyjEntities) { - foreach (var jks in item.HealthTeacherPerformances) + billingJksyjEntities.Add(new LqKdJksyjEntity { - billingJksyjEntities.Add(new LqKdJksyjEntity - { - Id = YitIdHelper.NextId().ToString(), - Glkdbh = billingId, - Jks = jks.HealthTeacherId, - Jksxm = jks.HealthTeacherName, - Jkszh = jks.HealthTeacherAccount, - Jksyj = jks.PerformanceAmount.ToString(), - Yjsj = transferTime, - Jsj_id = jks.HealthTeacherId, - Kdpxid = billingPxmxEntity.Id, - IsEffective = StatusEnum.有效.GetHashCode() - }); - } + Id = YitIdHelper.NextId().ToString(), + Glkdbh = billingId, + Jks = jks.Jks, + Jksxm = jks.Jksxm, + Jkszh = jks.Jkszh, + Jksyj = jks.Jksyj.ToString(), + Yjsj = transferTime, + Jsj_id = jks.F_jsjid, + Kdpxid = billingPxmxEntity.Id, + IsEffective = StatusEnum.有效.GetHashCode() + }); } - // 创建开卡科技部老师业绩记录 - if (item.TechTeacherPerformances != null && item.TechTeacherPerformances.Any()) + foreach (var kjbs in refundKjbsyjEntities) { - foreach (var kjbs in item.TechTeacherPerformances) + billingKjbsyjEntities.Add(new LqKdKjbsyjEntity { - billingKjbsyjEntities.Add(new LqKdKjbsyjEntity - { - Id = YitIdHelper.NextId().ToString(), - Glkdbh = billingId, - Kjbls = kjbs.TechTeacherId, - Kjblsxm = kjbs.TechTeacherName, - Kjblszh = kjbs.TechTeacherAccount, - Kjblsyj = kjbs.PerformanceAmount.ToString(), - Yjsj = transferTime, - Kdpxid = billingPxmxEntity.Id, - LaborCost = kjbs.LaborCost, - IsEffective = StatusEnum.有效.GetHashCode() - }); - } + Id = YitIdHelper.NextId().ToString(), + Glkdbh = billingId, + Kjbls = kjbs.Kjbls, + Kjblsxm = kjbs.Kjblsxm, + Kjblszh = kjbs.Kjblszh, + Kjblsyj = kjbs.Kjblsyj.ToString(), + Yjsj = transferTime, + Kdpxid = billingPxmxEntity.Id, + IsEffective = StatusEnum.有效.GetHashCode() + }); } } @@ -2669,6 +2666,361 @@ namespace NCC.Extend.LqKdKdjlb } #endregion + // #region 会员转卡操作 + // /// + // /// 会员转卡操作 + // /// + // /// + // /// 转卡是指一个会员把自己剩余的某些品项,转给另外一个会员 + // /// 转卡会员转出的品项,就做退卡操作 + // /// 被转卡会员收到的品项,做开卡操作 + // /// + // /// 示例请求: + // /// ```json + // /// { + // /// "fromMemberId": "member001", + // /// "toMemberId": "member002", + // /// "storeId": "store001", + // /// "signatureFile": "签名文件路径", + // /// "remarks": "转卡备注", + // /// "transferItems": [ + // /// { + // /// "billingItemId": "item001", + // /// "transferQuantity": 5, + // /// "itemId": "px001", + // /// "itemName": "美容项目", + // /// "itemPrice": 100.00, + // /// "sourceType": "转卡", + // /// "healthTeacherPerformances": [ + // /// { + // /// "healthTeacherId": "jks001", + // /// "healthTeacherName": "张医生", + // /// "healthTeacherAccount": "zhang001", + // /// "performanceAmount": 50.00, + // /// "laborCost": 20.00, + // /// "itemQuantity": 5 + // /// } + // /// ], + // /// "techTeacherPerformances": [ + // /// { + // /// "techTeacherId": "kjbs001", + // /// "techTeacherName": "李老师", + // /// "techTeacherAccount": "li001", + // /// "performanceAmount": 30.00, + // /// "laborCost": 10.00, + // /// "itemQuantity": 5 + // /// } + // /// ] + // /// } + // /// ] + // /// } + // /// ``` + // /// + // /// 参数说明: + // /// - fromMemberId: 转出会员ID + // /// - toMemberId: 转入会员ID + // /// - storeId: 门店ID + // /// - signatureFile: 转出会员签名 + // /// - remarks: 转卡备注 + // /// - transferItems: 转出品项列表 + // /// - billingItemId: 开单品项明细ID + // /// - transferQuantity: 转出数量 + // /// - itemId: 品项ID + // /// - itemName: 品项名称 + // /// - itemPrice: 品项价格 + // /// - sourceType: 来源类型 + // /// - healthTeacherPerformances: 健康师业绩列表 + // /// - healthTeacherId: 健康师ID + // /// - healthTeacherName: 健康师姓名 + // /// - healthTeacherAccount: 健康师账号 + // /// - performanceAmount: 业绩金额 + // /// - laborCost: 人工成本 + // /// - itemQuantity: 品项数量 + // /// - techTeacherPerformances: 科技部老师业绩列表 + // /// - techTeacherId: 科技部老师ID + // /// - techTeacherName: 科技部老师姓名 + // /// - techTeacherAccount: 科技部老师账号 + // /// - performanceAmount: 业绩金额 + // /// - laborCost: 人工成本 + // /// - itemQuantity: 品项数量 + // /// + // /// 转卡输入参数 + // /// 转卡结果 + // /// 转卡成功 + // /// 参数错误或业务规则验证失败 + // /// 服务器错误 + // [HttpPost("TransferCard")] + // public async Task TransferCard([FromBody] TransferCardInput input) + // { + // if (input == null) + // { + // throw NCCException.Oh("转卡参数不能为空"); + // } + + // var userInfo = await _userManager.GetUserInfo(); + // var transferTime = DateTime.Now; + + // try + // { + // // 开启事务 + // _db.BeginTran(); + + // // 1. 验证转出和转入会员是否存在 + // var fromMember = await _db.Queryable().Where(x => x.Id == input.FromMemberId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync(); + // if (fromMember == null) + // { + // throw NCCException.Oh("转出会员不存在或已失效"); + // } + // var toMember = await _db.Queryable().Where(x => x.Id == input.ToMemberId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync(); + // if (toMember == null) + // { + // throw NCCException.Oh("转入会员不存在或已失效"); + // } + + // // 2. 验证转出品项的余额是否足够 + // foreach (var item in input.TransferItems) + // { + // var billingItem = await _db.Queryable().Where(x => x.Id == item.BillingItemId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync(); + // if (billingItem == null) + // { + // throw NCCException.Oh($"品项明细不存在:{item.ItemName}"); + // } + + // // 查询剩余数量 + // var remainingCount = await GetItemRemainingCount(item.BillingItemId); + // if (remainingCount < item.TransferQuantity) + // { + // throw NCCException.Oh($"品项 {item.ItemName} 剩余数量不足,当前剩余:{remainingCount},需要转出:{item.TransferQuantity}"); + // } + // } + + // // 3. 创建退卡记录(转出方) + // var refundId = YitIdHelper.NextId().ToString(); + // var totalRefundAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity); + // var refundEntity = new LqHytkHytkEntity + // { + // Id = refundId, + // F_CreateTime = transferTime, + // F_CreateUser = userInfo.userId, + // IsEffective = StatusEnum.有效.GetHashCode(), + // Czry = userInfo.userId, + // Hy = input.FromMemberId, + // Hymc = fromMember.Khmc, + // Md = input.StoreId, + // SignatureFile = input.SignatureFile, + // Tkje = totalRefundAmount, + // ActualRefundAmount = totalRefundAmount, // 转卡时实退金额等于退卡总金额 + // Tkyy = "转卡", + // Bz = $"转卡给会员:{toMember.Khmc},{input.Remarks}" + // }; + // await _db.Insertable(refundEntity).ExecuteCommandAsync(); + + // // 4. 创建退卡品项明细和业绩记录 + // var refundMxEntities = new List(); + // var refundJksyjEntities = new List(); + // var refundKjbsyjEntities = new List(); + + // foreach (var item in input.TransferItems) + // { + // var refundMxEntity = new LqHytkMxEntity + // { + // Id = YitIdHelper.NextId().ToString(), + // RefundInfoId = refundId, + // BillingItemId = item.BillingItemId, + // CreateTime = transferTime, + // CreateUser = userInfo.userId, + // Px = item.ItemId, + // Pxmc = item.ItemName, + // Pxjg = item.ItemPrice, + // Tkje = item.ItemPrice * item.TransferQuantity, + // ProjectNumber = item.TransferQuantity, + // SourceType = item.SourceType, + // TotalPrice = item.ItemPrice * item.TransferQuantity, + // IsEffective = StatusEnum.有效.GetHashCode() + // }; + // refundMxEntities.Add(refundMxEntity); + + // // 创建退卡健康师业绩记录 + // if (item.HealthTeacherPerformances != null && item.HealthTeacherPerformances.Any()) + // { + // foreach (var jks in item.HealthTeacherPerformances) + // { + // refundJksyjEntities.Add(new LqHytkJksyjEntity + // { + // Id = YitIdHelper.NextId().ToString(), + // Gltkbh = refundId, + // Jks = jks.HealthTeacherId, + // Jksxm = jks.HealthTeacherName, + // Jkszh = jks.HealthTeacherAccount, + // Jksyj = jks.PerformanceAmount, + // Tksj = transferTime, + // F_jsjid = jks.HealthTeacherId, + // F_tkpxid = refundMxEntity.Id, + // F_LaborCost = jks.LaborCost, + // F_tkpxNumber = jks.ItemQuantity, + // F_CreateTime = transferTime, + // F_CreateUser = userInfo.userId, + // CardReturn = refundMxEntity.Id, + // IsEffective = StatusEnum.有效.GetHashCode() + // }); + // } + // } + + // // 创建退卡科技部老师业绩记录 + // if (item.TechTeacherPerformances != null && item.TechTeacherPerformances.Any()) + // { + // foreach (var kjbs in item.TechTeacherPerformances) + // { + // refundKjbsyjEntities.Add(new LqHytkKjbsyjEntity + // { + // Id = YitIdHelper.NextId().ToString(), + // Gltkbh = refundId, + // Kjbls = kjbs.TechTeacherId, + // Kjblsxm = kjbs.TechTeacherName, + // Kjblszh = kjbs.TechTeacherAccount, + // Kjblsyj = kjbs.PerformanceAmount, + // Tksj = transferTime, + // F_tkpxid = refundMxEntity.Id, + // F_LaborCost = kjbs.LaborCost, + // F_tkpxNumber = kjbs.ItemQuantity, + // F_CreateTime = transferTime, + // F_CreateUser = userInfo.userId, + // CardReturn = refundMxEntity.Id, + // IsEffective = StatusEnum.有效.GetHashCode() + // }); + // } + // } + // } + + // await _db.Insertable(refundMxEntities).ExecuteCommandAsync(); + // if (refundJksyjEntities.Any()) + // { + // await _db.Insertable(refundJksyjEntities).ExecuteCommandAsync(); + // } + // if (refundKjbsyjEntities.Any()) + // { + // await _db.Insertable(refundKjbsyjEntities).ExecuteCommandAsync(); + // } + + // // 5. 创建开卡记录(转入方) + // var billingId = YitIdHelper.NextId().ToString(); + // var billingEntity = new LqKdKdjlbEntity + // { + // Id = billingId, + // CreateTime = transferTime, + // UpdateTime = transferTime, + // IsEffective = StatusEnum.有效.GetHashCode(), + // CreateUser = userInfo.userId, + // Kdhy = input.ToMemberId, + // Djmd = input.StoreId, + // Sfyj = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity), + // Bz = $"从会员 {fromMember.Khmc} 转入,{input.Remarks}" + // }; + // await _db.Insertable(billingEntity).ExecuteCommandAsync(); + // // 6. 创建开单品项明细和业绩记录 + // var billingPxmxEntities = new List(); + // var billingJksyjEntities = new List(); + // var billingKjbsyjEntities = new List(); + + // foreach (var item in input.TransferItems) + // { + // var billingPxmxEntity = new LqKdPxmxEntity + // { + // Id = YitIdHelper.NextId().ToString(), + // Glkdbh = billingId, + // Px = item.ItemId, + // Pxmc = item.ItemName, + // Pxjg = item.ItemPrice, + // MemberId = input.ToMemberId, + // CreateTIme = transferTime, + // ProjectNumber = item.TransferQuantity, + // IsEnabled = StatusEnum.有效.GetHashCode(), + // SourceType = item.SourceType, + // TotalPrice = item.ItemPrice * item.TransferQuantity, + // ActualPrice = item.ItemPrice * item.TransferQuantity, + // IsEffective = StatusEnum.有效.GetHashCode(), + // Remark = $"从会员 {fromMember.Khmc} 转入" + // }; + // billingPxmxEntities.Add(billingPxmxEntity); + + // // 创建开卡健康师业绩记录 + // if (item.HealthTeacherPerformances != null && item.HealthTeacherPerformances.Any()) + // { + // foreach (var jks in item.HealthTeacherPerformances) + // { + // billingJksyjEntities.Add(new LqKdJksyjEntity + // { + // Id = YitIdHelper.NextId().ToString(), + // Glkdbh = billingId, + // Jks = jks.HealthTeacherId, + // Jksxm = jks.HealthTeacherName, + // Jkszh = jks.HealthTeacherAccount, + // Jksyj = jks.PerformanceAmount.ToString(), + // Yjsj = transferTime, + // Jsj_id = jks.HealthTeacherId, + // Kdpxid = billingPxmxEntity.Id, + // IsEffective = StatusEnum.有效.GetHashCode() + // }); + // } + // } + + // // 创建开卡科技部老师业绩记录 + // if (item.TechTeacherPerformances != null && item.TechTeacherPerformances.Any()) + // { + // foreach (var kjbs in item.TechTeacherPerformances) + // { + // billingKjbsyjEntities.Add(new LqKdKjbsyjEntity + // { + // Id = YitIdHelper.NextId().ToString(), + // Glkdbh = billingId, + // Kjbls = kjbs.TechTeacherId, + // Kjblsxm = kjbs.TechTeacherName, + // Kjblszh = kjbs.TechTeacherAccount, + // Kjblsyj = kjbs.PerformanceAmount.ToString(), + // Yjsj = transferTime, + // Kdpxid = billingPxmxEntity.Id, + // LaborCost = kjbs.LaborCost, + // IsEffective = StatusEnum.有效.GetHashCode() + // }); + // } + // } + // } + + // await _db.Insertable(billingPxmxEntities).ExecuteCommandAsync(); + // if (billingJksyjEntities.Any()) + // { + // await _db.Insertable(billingJksyjEntities).ExecuteCommandAsync(); + // } + // if (billingKjbsyjEntities.Any()) + // { + // await _db.Insertable(billingKjbsyjEntities).ExecuteCommandAsync(); + // } + // // 提交事务 + // _db.CommitTran(); + + // return new TransferCardOutput + // { + // Success = true, + // TransferId = refundId, + // RefundId = refundId, + // BillingId = billingId, + // TotalAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity), + // TotalQuantity = input.TransferItems.Sum(x => x.TransferQuantity), + // FromMemberName = fromMember.Khmc, + // ToMemberName = toMember.Khmc, + // TransferTime = transferTime, + // Message = "转卡操作成功" + // }; + // } + // catch (Exception ex) + // { + // _db.RollbackTran(); + // _logger.LogError(ex, "转卡操作失败:{Message}", ex.Message); + // throw NCCException.Oh($"转卡操作失败:{ex.Message}"); + // } + // } + // #endregion + #region 获取品项剩余数量 /// /// 获取品项剩余数量 diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs index 8c81539..1a4b767 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs @@ -531,7 +531,7 @@ namespace NCC.Extend.LqTkjlb #region 漏斗统计 /// - /// 获取拓客活动漏斗统计数据 + /// 获取拓客活动漏斗统计数据(优化版本) /// /// 活动ID /// 漏斗统计数据 @@ -540,31 +540,49 @@ namespace NCC.Extend.LqTkjlb { try { + // 优化版本:使用子查询减少JOIN复杂度 var sql = @" SELECT md.F_Id as store_id, md.dm as store_name, - COUNT(DISTINCT tk.F_Id) as tk_count, -- 拓客数量 - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as yy_count, -- 预约人数(已确认) - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as hk_count, -- 耗卡人数 - COALESCE(SUM(CASE WHEN xh.F_Id IS NOT NULL THEN xh.xfje END), 0) as hk_amount, -- 耗卡金额 - ROUND( - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 / - COUNT(DISTINCT tk.F_Id), 2 - ) as yy_conversion_rate, -- 预约转化率(预约人数/拓客数量) - ROUND( - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 / - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END), 2 - ) as hk_conversion_rate -- 耗卡转化率(耗卡人数/预约人数) - FROM lq_tkjlb tk - JOIN lq_mdxx md ON tk.F_StoreId = md.F_Id - LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk - AND yy.F_Status = '已确认' - LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy - AND xh.F_IsEffective = 1 - WHERE tk.F_EventId = @eventId - GROUP BY md.F_Id, md.dm - ORDER BY tk_count DESC"; + tk_stats.tk_count, + tk_stats.yaoy_count, + tk_stats.yy_count, + tk_stats.hk_count, + tk_stats.kd_count, + tk_stats.hk_amount, + tk_stats.kd_amount, + CASE + WHEN tk_stats.tk_count > 0 + THEN ROUND(tk_stats.yy_count * 100.0 / tk_stats.tk_count, 2) + ELSE 0 + END as yy_conversion_rate, + CASE + WHEN tk_stats.yy_count > 0 + THEN ROUND(tk_stats.hk_count * 100.0 / tk_stats.yy_count, 2) + ELSE 0 + END as hk_conversion_rate + FROM lq_mdxx md + LEFT JOIN ( + SELECT + tk.F_StoreId, + COUNT(DISTINCT tk.F_Id) as tk_count, + COUNT(DISTINCT yy.F_Id) as yaoy_count, + COUNT(DISTINCT yyjl.F_Id) as yy_count, + COUNT(DISTINCT xh.F_Id) as hk_count, + COUNT(DISTINCT kd.F_Id) as kd_count, + COALESCE(SUM(xh.xfje), 0) as hk_amount, + COALESCE(SUM(kd.sfyj), 0) as kd_amount + FROM lq_tkjlb tk + LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId + LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认' + LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1 + LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1 + WHERE tk.F_EventId = @eventId + GROUP BY tk.F_StoreId + ) tk_stats ON md.F_Id = tk_stats.F_StoreId + WHERE tk_stats.F_StoreId IS NOT NULL + ORDER BY tk_stats.tk_count DESC"; var result = await _db.Ado.SqlQueryAsync(sql, new { eventId }); @@ -582,7 +600,7 @@ namespace NCC.Extend.LqTkjlb } /// - /// 获取拓客活动总体漏斗统计 + /// 获取拓客活动总体漏斗统计(优化版本) /// /// 活动ID /// 总体漏斗统计数据 @@ -593,24 +611,39 @@ namespace NCC.Extend.LqTkjlb { var sql = @" SELECT - COUNT(DISTINCT tk.F_Id) as total_tk_count, -- 总拓客数量 - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as total_yy_count, -- 总预约人数 - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as total_hk_count, -- 总耗卡人数 - COALESCE(SUM(CASE WHEN xh.F_Id IS NOT NULL THEN xh.xfje END), 0) as total_hk_amount, -- 总耗卡金额 - ROUND( - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 / - COUNT(DISTINCT tk.F_Id), 2 - ) as overall_yy_conversion_rate, -- 总体预约转化率 - ROUND( - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 / - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END), 2 - ) as overall_hk_conversion_rate -- 总体耗卡转化率 - FROM lq_tkjlb tk - LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk - AND yy.F_Status = '已确认' - LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy - AND xh.F_IsEffective = 1 - WHERE tk.F_EventId = @eventId"; + SUM(tk_count) as total_tk_count, + SUM(yaoy_count) as total_yaoy_count, + SUM(yy_count) as total_yy_count, + SUM(hk_count) as total_hk_count, + SUM(kd_count) as total_kd_count, + SUM(hk_amount) as total_hk_amount, + SUM(kd_amount) as total_kd_amount, + CASE + WHEN SUM(tk_count) > 0 + THEN ROUND(SUM(yy_count) * 100.0 / SUM(tk_count), 2) + ELSE 0 + END as overall_yy_conversion_rate, + CASE + WHEN SUM(yy_count) > 0 + THEN ROUND(SUM(hk_count) * 100.0 / SUM(yy_count), 2) + ELSE 0 + END as overall_hk_conversion_rate + FROM ( + SELECT + COUNT(DISTINCT tk.F_Id) as tk_count, + COUNT(DISTINCT yy.F_Id) as yaoy_count, + COUNT(DISTINCT yyjl.F_Id) as yy_count, + COUNT(DISTINCT xh.F_Id) as hk_count, + COUNT(DISTINCT kd.F_Id) as kd_count, + COALESCE(SUM(xh.xfje), 0) as hk_amount, + COALESCE(SUM(kd.sfyj), 0) as kd_amount + FROM lq_tkjlb tk + LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId + LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认' + LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1 + LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1 + WHERE tk.F_EventId = @eventId + ) stats"; var result = await _db.Ado.SqlQueryAsync(sql, new { eventId }); @@ -626,6 +659,113 @@ namespace NCC.Extend.LqTkjlb throw NCCException.Oh("获取总体漏斗统计数据失败:" + ex.Message); } } + + /// + /// 获取拓客活动漏斗统计数据(高性能版本 - 分步查询) + /// + /// 活动ID + /// 漏斗统计数据 + [HttpGet("GetFunnelStatisticsFast/{eventId}")] + public async Task GetFunnelStatisticsFast(string eventId) + { + try + { + // 第一步:获取拓客基础数据 + var tkSql = @" + SELECT + tk.F_StoreId, + md.dm as store_name, + COUNT(DISTINCT tk.F_Id) as tk_count + FROM lq_tkjlb tk + JOIN lq_mdxx md ON tk.F_StoreId = md.F_Id + WHERE tk.F_EventId = @eventId + GROUP BY tk.F_StoreId, md.dm"; + + var tkData = await _db.Ado.SqlQueryAsync(tkSql, new { eventId }); + var tkDict = tkData.ToDictionary(x => (string)x.F_StoreId, x => x); + + // 第二步:获取邀约数据 + var yaoySql = @" + SELECT + tk.F_StoreId, + COUNT(DISTINCT yy.F_Id) as yaoy_count + FROM lq_tkjlb tk + LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId + WHERE tk.F_EventId = @eventId + GROUP BY tk.F_StoreId"; + + var yaoyData = await _db.Ado.SqlQueryAsync(yaoySql, new { eventId }); + var yaoyDict = yaoyData.ToDictionary(x => (string)x.F_StoreId, x => (int)x.yaoy_count); + + // 第三步:获取预约数据 + var yySql = @" + SELECT + tk.F_StoreId, + COUNT(DISTINCT yyjl.F_Id) as yy_count + FROM lq_tkjlb tk + LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认' + WHERE tk.F_EventId = @eventId + GROUP BY tk.F_StoreId"; + + var yyData = await _db.Ado.SqlQueryAsync(yySql, new { eventId }); + var yyDict = yyData.ToDictionary(x => (string)x.F_StoreId, x => (int)x.yy_count); + + // 第四步:获取耗卡数据 + var hkSql = @" + SELECT + tk.F_StoreId, + COUNT(DISTINCT xh.F_Id) as hk_count, + COALESCE(SUM(xh.xfje), 0) as hk_amount + FROM lq_tkjlb tk + LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1 + WHERE tk.F_EventId = @eventId + GROUP BY tk.F_StoreId"; + + var hkData = await _db.Ado.SqlQueryAsync(hkSql, new { eventId }); + var hkDict = hkData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.hk_count, amount = (decimal)x.hk_amount }); + + // 第五步:获取开单数据 + var kdSql = @" + SELECT + tk.F_StoreId, + COUNT(DISTINCT kd.F_Id) as kd_count, + COALESCE(SUM(kd.sfyj), 0) as kd_amount + FROM lq_tkjlb tk + LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1 + WHERE tk.F_EventId = @eventId + GROUP BY tk.F_StoreId"; + + var kdData = await _db.Ado.SqlQueryAsync(kdSql, new { eventId }); + var kdDict = kdData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.kd_count, amount = (decimal)x.kd_amount }); + + // 合并结果 + var result = tkDict.Values.Select(tk => new + { + store_id = tk.F_StoreId, + store_name = tk.store_name, + tk_count = (int)tk.tk_count, + yaoy_count = yaoyDict.ContainsKey(tk.F_StoreId) ? yaoyDict[tk.F_StoreId] : 0, + yy_count = yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0, + hk_count = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].count : 0, + kd_count = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].count : 0, + hk_amount = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].amount : 0m, + kd_amount = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].amount : 0m, + yy_conversion_rate = (int)tk.tk_count > 0 ? Math.Round((yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0) * 100.0 / (int)tk.tk_count, 2) : 0, + hk_conversion_rate = (yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0) > 0 ? Math.Round((hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].count : 0) * 100.0 / (yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0), 2) : 0 + }).OrderByDescending(x => x.tk_count).ToList(); + + return new + { + success = true, + data = result, + message = "获取漏斗统计数据成功(高性能版本)" + }; + } + catch (Exception ex) + { + throw NCCException.Oh("获取漏斗统计数据失败:" + ex.Message); + } + } #endregion #region 门店顾客详情 diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqXmzlService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqXmzlService.cs index e1d1d90..6c50d62 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqXmzlService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqXmzlService.cs @@ -292,13 +292,13 @@ namespace NCC.Extend.LqXmzl /// /// 字段名称,支持:fl1、fl2、fl3、fl4、fl、qt1、beautyType、sourceType /// 去重后的字段数据 - [HttpPost("GetDistinctFieldData")] - public async Task GetDistinctFieldData([FromBody] string fieldName) + [HttpGet("GetDistinctFieldData")] + public async Task GetDistinctFieldData([FromQuery] string fieldName) { try { // 验证字段名称 - var validFields = new[] { "fl1", "fl2", "fl3", "fl4", "fl", "qt1", "beautyType", "sourceType" }; + var validFields = new[] { "fl1", "fl2", "fl3", "fl4", "fl", "qt1", "qt2", "beautyType", "sourceType" }; if (!validFields.Contains(fieldName)) { throw NCCException.Oh($"无效的字段名称: {fieldName}。支持的字段: {string.Join(", ", validFields)}"); @@ -350,6 +350,13 @@ namespace NCC.Extend.LqXmzl .Distinct() .ToListAsync(); break; + case "qt2": + distinctValues = await _db.Queryable() + .Where(p => !string.IsNullOrEmpty(p.Qt2)) + .Select(p => p.Qt2) + .Distinct() + .ToListAsync(); + break; case "beautyType": distinctValues = await _db.Queryable() .Where(p => !string.IsNullOrEmpty(p.BeautyType)) -- libgit2 0.21.4