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))