Commit 63df7ccb830b7faef56be2b3308e5b7a4bb670dd
1 parent
88610eda
1
Showing
11 changed files
with
653 additions
and
243 deletions
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkCrInput.cs
| ... | ... | @@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk |
| 57 | 57 | public decimal? tkje { get; set; } |
| 58 | 58 | |
| 59 | 59 | /// <summary> |
| 60 | + /// 实退金额 | |
| 61 | + /// </summary> | |
| 62 | + public decimal? actualRefundAmount { get; set; } | |
| 63 | + | |
| 64 | + /// <summary> | |
| 60 | 65 | /// 手工费用 |
| 61 | 66 | /// </summary> |
| 62 | 67 | public decimal? sgfy { get; set; } | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkInfoOutput.cs
| ... | ... | @@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk |
| 57 | 57 | public decimal? tkje { get; set; } |
| 58 | 58 | |
| 59 | 59 | /// <summary> |
| 60 | + /// 实退金额 | |
| 61 | + /// </summary> | |
| 62 | + public decimal? actualRefundAmount { get; set; } | |
| 63 | + | |
| 64 | + /// <summary> | |
| 60 | 65 | /// 手工费用 |
| 61 | 66 | /// </summary> |
| 62 | 67 | public decimal? sgfy { get; set; } | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs
| ... | ... | @@ -53,6 +53,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk |
| 53 | 53 | public decimal? tkje { get; set; } |
| 54 | 54 | |
| 55 | 55 | /// <summary> |
| 56 | + /// 实退金额 | |
| 57 | + /// </summary> | |
| 58 | + public decimal? actualRefundAmount { get; set; } | |
| 59 | + | |
| 60 | + /// <summary> | |
| 56 | 61 | /// 手工费用 |
| 57 | 62 | /// </summary> |
| 58 | 63 | public decimal? sgfy { get; set; } | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkUpInput.cs
| ... | ... | @@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk |
| 57 | 57 | public decimal? tkje { get; set; } |
| 58 | 58 | |
| 59 | 59 | /// <summary> |
| 60 | + /// 实退金额 | |
| 61 | + /// </summary> | |
| 62 | + public decimal? actualRefundAmount { get; set; } | |
| 63 | + | |
| 64 | + /// <summary> | |
| 60 | 65 | /// 手工费用 |
| 61 | 66 | /// </summary> |
| 62 | 67 | public decimal? sgfy { get; set; } | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardInput.cs
| ... | ... | @@ -46,8 +46,6 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb |
| 46 | 46 | [Display(Name = "转卡备注")] |
| 47 | 47 | public string Remarks { get; set; } |
| 48 | 48 | |
| 49 | - | |
| 50 | - | |
| 51 | 49 | /// <summary> |
| 52 | 50 | /// 门店ID |
| 53 | 51 | /// </summary> |
| ... | ... | @@ -109,120 +107,5 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb |
| 109 | 107 | [Display(Name = "来源类型")] |
| 110 | 108 | public string SourceType { get; set; } = "转卡"; |
| 111 | 109 | |
| 112 | - /// <summary> | |
| 113 | - /// 健康师业绩列表 | |
| 114 | - /// </summary> | |
| 115 | - [Display(Name = "健康师业绩列表")] | |
| 116 | - public List<TransferHealthTeacherPerformanceInput> HealthTeacherPerformances { get; set; } | |
| 117 | - | |
| 118 | - /// <summary> | |
| 119 | - /// 科技部老师业绩列表 | |
| 120 | - /// </summary> | |
| 121 | - [Display(Name = "科技部老师业绩列表")] | |
| 122 | - public List<TransferTechTeacherPerformanceInput> TechTeacherPerformances { get; set; } | |
| 123 | - } | |
| 124 | - | |
| 125 | - /// <summary> | |
| 126 | - /// 转卡健康师业绩输入参数 | |
| 127 | - /// </summary> | |
| 128 | - public class TransferHealthTeacherPerformanceInput | |
| 129 | - { | |
| 130 | - /// <summary> | |
| 131 | - /// 健康师ID | |
| 132 | - /// </summary> | |
| 133 | - [Required(ErrorMessage = "健康师ID不能为空")] | |
| 134 | - [StringLength(50, ErrorMessage = "健康师ID长度不能超过50个字符")] | |
| 135 | - [Display(Name = "健康师ID")] | |
| 136 | - public string HealthTeacherId { get; set; } | |
| 137 | - | |
| 138 | - /// <summary> | |
| 139 | - /// 健康师姓名 | |
| 140 | - /// </summary> | |
| 141 | - [Required(ErrorMessage = "健康师姓名不能为空")] | |
| 142 | - [StringLength(50, ErrorMessage = "健康师姓名长度不能超过50个字符")] | |
| 143 | - [Display(Name = "健康师姓名")] | |
| 144 | - public string HealthTeacherName { get; set; } | |
| 145 | - | |
| 146 | - /// <summary> | |
| 147 | - /// 健康师账号 | |
| 148 | - /// </summary> | |
| 149 | - [StringLength(50, ErrorMessage = "健康师账号长度不能超过50个字符")] | |
| 150 | - [Display(Name = "健康师账号")] | |
| 151 | - public string HealthTeacherAccount { get; set; } | |
| 152 | - | |
| 153 | - /// <summary> | |
| 154 | - /// 业绩金额 | |
| 155 | - /// </summary> | |
| 156 | - [Required(ErrorMessage = "业绩金额不能为空")] | |
| 157 | - [Range(0, double.MaxValue, ErrorMessage = "业绩金额不能为负数")] | |
| 158 | - [Display(Name = "业绩金额")] | |
| 159 | - public decimal PerformanceAmount { get; set; } | |
| 160 | - | |
| 161 | - /// <summary> | |
| 162 | - /// 人工成本 | |
| 163 | - /// </summary> | |
| 164 | - [Range(0, double.MaxValue, ErrorMessage = "人工成本不能为负数")] | |
| 165 | - [Display(Name = "人工成本")] | |
| 166 | - public decimal LaborCost { get; set; } | |
| 167 | - | |
| 168 | - /// <summary> | |
| 169 | - /// 品项数量 | |
| 170 | - /// </summary> | |
| 171 | - [Required(ErrorMessage = "品项数量不能为空")] | |
| 172 | - [Range(1, int.MaxValue, ErrorMessage = "品项数量必须大于0")] | |
| 173 | - [Display(Name = "品项数量")] | |
| 174 | - public int ItemQuantity { get; set; } | |
| 175 | - } | |
| 176 | - | |
| 177 | - /// <summary> | |
| 178 | - /// 转卡科技部老师业绩输入参数 | |
| 179 | - /// </summary> | |
| 180 | - public class TransferTechTeacherPerformanceInput | |
| 181 | - { | |
| 182 | - /// <summary> | |
| 183 | - /// 科技部老师ID | |
| 184 | - /// </summary> | |
| 185 | - [Required(ErrorMessage = "科技部老师ID不能为空")] | |
| 186 | - [StringLength(50, ErrorMessage = "科技部老师ID长度不能超过50个字符")] | |
| 187 | - [Display(Name = "科技部老师ID")] | |
| 188 | - public string TechTeacherId { get; set; } | |
| 189 | - | |
| 190 | - /// <summary> | |
| 191 | - /// 科技部老师姓名 | |
| 192 | - /// </summary> | |
| 193 | - [Required(ErrorMessage = "科技部老师姓名不能为空")] | |
| 194 | - [StringLength(50, ErrorMessage = "科技部老师姓名长度不能超过50个字符")] | |
| 195 | - [Display(Name = "科技部老师姓名")] | |
| 196 | - public string TechTeacherName { get; set; } | |
| 197 | - | |
| 198 | - /// <summary> | |
| 199 | - /// 科技部老师账号 | |
| 200 | - /// </summary> | |
| 201 | - [StringLength(50, ErrorMessage = "科技部老师账号长度不能超过50个字符")] | |
| 202 | - [Display(Name = "科技部老师账号")] | |
| 203 | - public string TechTeacherAccount { get; set; } | |
| 204 | - | |
| 205 | - /// <summary> | |
| 206 | - /// 业绩金额 | |
| 207 | - /// </summary> | |
| 208 | - [Required(ErrorMessage = "业绩金额不能为空")] | |
| 209 | - [Range(0, double.MaxValue, ErrorMessage = "业绩金额不能为负数")] | |
| 210 | - [Display(Name = "业绩金额")] | |
| 211 | - public decimal PerformanceAmount { get; set; } | |
| 212 | - | |
| 213 | - /// <summary> | |
| 214 | - /// 人工成本 | |
| 215 | - /// </summary> | |
| 216 | - [Range(0, double.MaxValue, ErrorMessage = "人工成本不能为负数")] | |
| 217 | - [Display(Name = "人工成本")] | |
| 218 | - public decimal LaborCost { get; set; } | |
| 219 | - | |
| 220 | - /// <summary> | |
| 221 | - /// 品项数量 | |
| 222 | - /// </summary> | |
| 223 | - [Required(ErrorMessage = "品项数量不能为空")] | |
| 224 | - [Range(1, int.MaxValue, ErrorMessage = "品项数量必须大于0")] | |
| 225 | - [Display(Name = "品项数量")] | |
| 226 | - public int ItemQuantity { get; set; } | |
| 227 | 110 | } |
| 228 | 111 | } | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_hytk/LqHytkHytkEntity.cs
| ... | ... | @@ -67,6 +67,12 @@ namespace NCC.Extend.Entitys.lq_hytk_hytk |
| 67 | 67 | public decimal? Tkje { get; set; } |
| 68 | 68 | |
| 69 | 69 | /// <summary> |
| 70 | + /// 实退金额 | |
| 71 | + /// </summary> | |
| 72 | + [SugarColumn(ColumnName = "F_ActualRefundAmount")] | |
| 73 | + public decimal? ActualRefundAmount { get; set; } | |
| 74 | + | |
| 75 | + /// <summary> | |
| 70 | 76 | /// 手工费用 |
| 71 | 77 | /// </summary> |
| 72 | 78 | [SugarColumn(ColumnName = "sgfy")] | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs
netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
| ... | ... | @@ -2414,7 +2414,6 @@ namespace NCC.Extend.LqKdKdjlb |
| 2414 | 2414 | { |
| 2415 | 2415 | // 开启事务 |
| 2416 | 2416 | _db.BeginTran(); |
| 2417 | - | |
| 2418 | 2417 | // 1. 验证转出和转入会员是否存在 |
| 2419 | 2418 | var fromMember = await _db.Queryable<LqKhxxEntity>().Where(x => x.Id == input.FromMemberId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync(); |
| 2420 | 2419 | if (fromMember == null) |
| ... | ... | @@ -2446,6 +2445,7 @@ namespace NCC.Extend.LqKdKdjlb |
| 2446 | 2445 | |
| 2447 | 2446 | // 3. 创建退卡记录(转出方) |
| 2448 | 2447 | var refundId = YitIdHelper.NextId().ToString(); |
| 2448 | + var totalRefundAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity); | |
| 2449 | 2449 | var refundEntity = new LqHytkHytkEntity |
| 2450 | 2450 | { |
| 2451 | 2451 | Id = refundId, |
| ... | ... | @@ -2457,7 +2457,8 @@ namespace NCC.Extend.LqKdKdjlb |
| 2457 | 2457 | Hymc = fromMember.Khmc, |
| 2458 | 2458 | Md = input.StoreId, |
| 2459 | 2459 | SignatureFile = input.SignatureFile, |
| 2460 | - Tkje = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity), | |
| 2460 | + Tkje = totalRefundAmount, | |
| 2461 | + ActualRefundAmount = totalRefundAmount, // 转卡时实退金额等于退卡总金额 | |
| 2461 | 2462 | Tkyy = "转卡", |
| 2462 | 2463 | Bz = $"转卡给会员:{toMember.Khmc},{input.Remarks}" |
| 2463 | 2464 | }; |
| ... | ... | @@ -2466,10 +2467,15 @@ namespace NCC.Extend.LqKdKdjlb |
| 2466 | 2467 | // 4. 创建退卡品项明细和业绩记录 |
| 2467 | 2468 | var refundMxEntities = new List<LqHytkMxEntity>(); |
| 2468 | 2469 | var refundJksyjEntities = new List<LqHytkJksyjEntity>(); |
| 2470 | + | |
| 2469 | 2471 | var refundKjbsyjEntities = new List<LqHytkKjbsyjEntity>(); |
| 2470 | 2472 | |
| 2471 | 2473 | foreach (var item in input.TransferItems) |
| 2472 | 2474 | { |
| 2475 | + var refundPxmxEntity = _db.Queryable<LqKdPxmxEntity>().First(p => p.Id == item.BillingItemId); | |
| 2476 | + //计算品项扣除总金额 | |
| 2477 | + var 品项扣除总金额 = refundPxmxEntity.Pxjg * item.TransferQuantity; | |
| 2478 | + //保存退卡明细表 | |
| 2473 | 2479 | var refundMxEntity = new LqHytkMxEntity |
| 2474 | 2480 | { |
| 2475 | 2481 | Id = YitIdHelper.NextId().ToString(), |
| ... | ... | @@ -2480,63 +2486,61 @@ namespace NCC.Extend.LqKdKdjlb |
| 2480 | 2486 | Px = item.ItemId, |
| 2481 | 2487 | Pxmc = item.ItemName, |
| 2482 | 2488 | Pxjg = item.ItemPrice, |
| 2483 | - Tkje = item.ItemPrice * item.TransferQuantity, | |
| 2489 | + Tkje = 品项扣除总金额, | |
| 2484 | 2490 | ProjectNumber = item.TransferQuantity, |
| 2485 | 2491 | SourceType = item.SourceType, |
| 2486 | - TotalPrice = item.ItemPrice * item.TransferQuantity, | |
| 2492 | + TotalPrice = 品项扣除总金额, | |
| 2487 | 2493 | IsEffective = StatusEnum.有效.GetHashCode() |
| 2488 | 2494 | }; |
| 2489 | 2495 | refundMxEntities.Add(refundMxEntity); |
| 2490 | - | |
| 2491 | - // 创建退卡健康师业绩记录 | |
| 2492 | - if (item.HealthTeacherPerformances != null && item.HealthTeacherPerformances.Any()) | |
| 2496 | + var refundKdyjEntities = _db.Queryable<LqKdJksyjEntity>().Where(p => p.Kdpxid == item.BillingItemId).ToList(); | |
| 2497 | + //保存退卡健康师业绩表 | |
| 2498 | + foreach (var jks in refundKdyjEntities) | |
| 2493 | 2499 | { |
| 2494 | - foreach (var jks in item.HealthTeacherPerformances) | |
| 2500 | + //获取健康师当月金三角id | |
| 2501 | + var monthString = DateTime.Now.ToString("yyyyMM"); | |
| 2502 | + var GetMonTeam = _db.Queryable<LqJinsanjiaoUserEntity>().Where(p => p.UserId == jks.Jks && p.Month == monthString).First(); | |
| 2503 | + //获取本月 | |
| 2504 | + refundJksyjEntities.Add(new LqHytkJksyjEntity | |
| 2495 | 2505 | { |
| 2496 | - refundJksyjEntities.Add(new LqHytkJksyjEntity | |
| 2497 | - { | |
| 2498 | - Id = YitIdHelper.NextId().ToString(), | |
| 2499 | - Gltkbh = refundId, | |
| 2500 | - Jks = jks.HealthTeacherId, | |
| 2501 | - Jksxm = jks.HealthTeacherName, | |
| 2502 | - Jkszh = jks.HealthTeacherAccount, | |
| 2503 | - Jksyj = jks.PerformanceAmount, | |
| 2504 | - Tksj = transferTime, | |
| 2505 | - F_jsjid = jks.HealthTeacherId, | |
| 2506 | - F_tkpxid = refundMxEntity.Id, | |
| 2507 | - F_LaborCost = jks.LaborCost, | |
| 2508 | - F_tkpxNumber = jks.ItemQuantity, | |
| 2509 | - F_CreateTime = transferTime, | |
| 2510 | - F_CreateUser = userInfo.userId, | |
| 2511 | - CardReturn = refundMxEntity.Id, | |
| 2512 | - IsEffective = StatusEnum.有效.GetHashCode() | |
| 2513 | - }); | |
| 2514 | - } | |
| 2506 | + Id = YitIdHelper.NextId().ToString(), | |
| 2507 | + Gltkbh = refundId, | |
| 2508 | + Jks = jks.Jks, | |
| 2509 | + Jksxm = jks.Jksxm, | |
| 2510 | + Jkszh = jks.Jkszh, | |
| 2511 | + Jksyj = (品项扣除总金额 / refundKdyjEntities.Count()), | |
| 2512 | + Tksj = DateTime.Now, | |
| 2513 | + F_jsjid = GetMonTeam.JsjId, | |
| 2514 | + F_tkpxid = refundMxEntity.Id, | |
| 2515 | + F_tkpxNumber = item.TransferQuantity, | |
| 2516 | + F_CreateTime = transferTime, | |
| 2517 | + F_CreateUser = userInfo.userId, | |
| 2518 | + CardReturn = refundMxEntity.Id, | |
| 2519 | + IsEffective = StatusEnum.有效.GetHashCode() | |
| 2520 | + }); | |
| 2515 | 2521 | } |
| 2516 | - | |
| 2522 | + //查询科技部老师的业绩 | |
| 2523 | + var TechTeacherEntities = _db.Queryable<LqKdKjbsyjEntity>().Where(p => p.Kdpxid == item.BillingItemId).ToList(); | |
| 2517 | 2524 | // 创建退卡科技部老师业绩记录 |
| 2518 | - if (item.TechTeacherPerformances != null && item.TechTeacherPerformances.Any()) | |
| 2525 | + foreach (var kjbs in TechTeacherEntities) | |
| 2519 | 2526 | { |
| 2520 | - foreach (var kjbs in item.TechTeacherPerformances) | |
| 2527 | + refundKjbsyjEntities.Add(new LqHytkKjbsyjEntity | |
| 2521 | 2528 | { |
| 2522 | - refundKjbsyjEntities.Add(new LqHytkKjbsyjEntity | |
| 2523 | - { | |
| 2524 | - Id = YitIdHelper.NextId().ToString(), | |
| 2525 | - Gltkbh = refundId, | |
| 2526 | - Kjbls = kjbs.TechTeacherId, | |
| 2527 | - Kjblsxm = kjbs.TechTeacherName, | |
| 2528 | - Kjblszh = kjbs.TechTeacherAccount, | |
| 2529 | - Kjblsyj = kjbs.PerformanceAmount, | |
| 2530 | - Tksj = transferTime, | |
| 2531 | - F_tkpxid = refundMxEntity.Id, | |
| 2532 | - F_LaborCost = kjbs.LaborCost, | |
| 2533 | - F_tkpxNumber = kjbs.ItemQuantity, | |
| 2534 | - F_CreateTime = transferTime, | |
| 2535 | - F_CreateUser = userInfo.userId, | |
| 2536 | - CardReturn = refundMxEntity.Id, | |
| 2537 | - IsEffective = StatusEnum.有效.GetHashCode() | |
| 2538 | - }); | |
| 2539 | - } | |
| 2529 | + Id = YitIdHelper.NextId().ToString(), | |
| 2530 | + Gltkbh = refundId, | |
| 2531 | + Kjbls = kjbs.Kjbls, | |
| 2532 | + Kjblsxm = kjbs.Kjblsxm, | |
| 2533 | + Kjblszh = kjbs.Kjblszh, | |
| 2534 | + Kjblsyj = (品项扣除总金额 / TechTeacherEntities.Count()), | |
| 2535 | + Tksj = transferTime, | |
| 2536 | + F_tkpxid = refundMxEntity.Id, | |
| 2537 | + F_LaborCost = kjbs.LaborCost, | |
| 2538 | + F_tkpxNumber = item.TransferQuantity, | |
| 2539 | + F_CreateTime = transferTime, | |
| 2540 | + F_CreateUser = userInfo.userId, | |
| 2541 | + CardReturn = refundMxEntity.Id, | |
| 2542 | + IsEffective = StatusEnum.有效.GetHashCode() | |
| 2543 | + }); | |
| 2540 | 2544 | } |
| 2541 | 2545 | } |
| 2542 | 2546 | |
| ... | ... | @@ -2561,6 +2565,8 @@ namespace NCC.Extend.LqKdKdjlb |
| 2561 | 2565 | CreateUser = userInfo.userId, |
| 2562 | 2566 | Kdhy = input.ToMemberId, |
| 2563 | 2567 | Djmd = input.StoreId, |
| 2568 | + Fkfs = "转卡", | |
| 2569 | + Sfskdd = "否", | |
| 2564 | 2570 | Sfyj = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity), |
| 2565 | 2571 | Bz = $"从会员 {fromMember.Khmc} 转入,{input.Remarks}" |
| 2566 | 2572 | }; |
| ... | ... | @@ -2591,46 +2597,37 @@ namespace NCC.Extend.LqKdKdjlb |
| 2591 | 2597 | }; |
| 2592 | 2598 | billingPxmxEntities.Add(billingPxmxEntity); |
| 2593 | 2599 | |
| 2594 | - // 创建开卡健康师业绩记录 | |
| 2595 | - if (item.HealthTeacherPerformances != null && item.HealthTeacherPerformances.Any()) | |
| 2600 | + foreach (var jks in refundJksyjEntities) | |
| 2596 | 2601 | { |
| 2597 | - foreach (var jks in item.HealthTeacherPerformances) | |
| 2602 | + billingJksyjEntities.Add(new LqKdJksyjEntity | |
| 2598 | 2603 | { |
| 2599 | - billingJksyjEntities.Add(new LqKdJksyjEntity | |
| 2600 | - { | |
| 2601 | - Id = YitIdHelper.NextId().ToString(), | |
| 2602 | - Glkdbh = billingId, | |
| 2603 | - Jks = jks.HealthTeacherId, | |
| 2604 | - Jksxm = jks.HealthTeacherName, | |
| 2605 | - Jkszh = jks.HealthTeacherAccount, | |
| 2606 | - Jksyj = jks.PerformanceAmount.ToString(), | |
| 2607 | - Yjsj = transferTime, | |
| 2608 | - Jsj_id = jks.HealthTeacherId, | |
| 2609 | - Kdpxid = billingPxmxEntity.Id, | |
| 2610 | - IsEffective = StatusEnum.有效.GetHashCode() | |
| 2611 | - }); | |
| 2612 | - } | |
| 2604 | + Id = YitIdHelper.NextId().ToString(), | |
| 2605 | + Glkdbh = billingId, | |
| 2606 | + Jks = jks.Jks, | |
| 2607 | + Jksxm = jks.Jksxm, | |
| 2608 | + Jkszh = jks.Jkszh, | |
| 2609 | + Jksyj = jks.Jksyj.ToString(), | |
| 2610 | + Yjsj = transferTime, | |
| 2611 | + Jsj_id = jks.F_jsjid, | |
| 2612 | + Kdpxid = billingPxmxEntity.Id, | |
| 2613 | + IsEffective = StatusEnum.有效.GetHashCode() | |
| 2614 | + }); | |
| 2613 | 2615 | } |
| 2614 | 2616 | |
| 2615 | - // 创建开卡科技部老师业绩记录 | |
| 2616 | - if (item.TechTeacherPerformances != null && item.TechTeacherPerformances.Any()) | |
| 2617 | + foreach (var kjbs in refundKjbsyjEntities) | |
| 2617 | 2618 | { |
| 2618 | - foreach (var kjbs in item.TechTeacherPerformances) | |
| 2619 | + billingKjbsyjEntities.Add(new LqKdKjbsyjEntity | |
| 2619 | 2620 | { |
| 2620 | - billingKjbsyjEntities.Add(new LqKdKjbsyjEntity | |
| 2621 | - { | |
| 2622 | - Id = YitIdHelper.NextId().ToString(), | |
| 2623 | - Glkdbh = billingId, | |
| 2624 | - Kjbls = kjbs.TechTeacherId, | |
| 2625 | - Kjblsxm = kjbs.TechTeacherName, | |
| 2626 | - Kjblszh = kjbs.TechTeacherAccount, | |
| 2627 | - Kjblsyj = kjbs.PerformanceAmount.ToString(), | |
| 2628 | - Yjsj = transferTime, | |
| 2629 | - Kdpxid = billingPxmxEntity.Id, | |
| 2630 | - LaborCost = kjbs.LaborCost, | |
| 2631 | - IsEffective = StatusEnum.有效.GetHashCode() | |
| 2632 | - }); | |
| 2633 | - } | |
| 2621 | + Id = YitIdHelper.NextId().ToString(), | |
| 2622 | + Glkdbh = billingId, | |
| 2623 | + Kjbls = kjbs.Kjbls, | |
| 2624 | + Kjblsxm = kjbs.Kjblsxm, | |
| 2625 | + Kjblszh = kjbs.Kjblszh, | |
| 2626 | + Kjblsyj = kjbs.Kjblsyj.ToString(), | |
| 2627 | + Yjsj = transferTime, | |
| 2628 | + Kdpxid = billingPxmxEntity.Id, | |
| 2629 | + IsEffective = StatusEnum.有效.GetHashCode() | |
| 2630 | + }); | |
| 2634 | 2631 | } |
| 2635 | 2632 | } |
| 2636 | 2633 | |
| ... | ... | @@ -2669,6 +2666,361 @@ namespace NCC.Extend.LqKdKdjlb |
| 2669 | 2666 | } |
| 2670 | 2667 | #endregion |
| 2671 | 2668 | |
| 2669 | + // #region 会员转卡操作 | |
| 2670 | + // /// <summary> | |
| 2671 | + // /// 会员转卡操作 | |
| 2672 | + // /// </summary> | |
| 2673 | + // /// <remarks> | |
| 2674 | + // /// 转卡是指一个会员把自己剩余的某些品项,转给另外一个会员 | |
| 2675 | + // /// 转卡会员转出的品项,就做退卡操作 | |
| 2676 | + // /// 被转卡会员收到的品项,做开卡操作 | |
| 2677 | + // /// | |
| 2678 | + // /// 示例请求: | |
| 2679 | + // /// ```json | |
| 2680 | + // /// { | |
| 2681 | + // /// "fromMemberId": "member001", | |
| 2682 | + // /// "toMemberId": "member002", | |
| 2683 | + // /// "storeId": "store001", | |
| 2684 | + // /// "signatureFile": "签名文件路径", | |
| 2685 | + // /// "remarks": "转卡备注", | |
| 2686 | + // /// "transferItems": [ | |
| 2687 | + // /// { | |
| 2688 | + // /// "billingItemId": "item001", | |
| 2689 | + // /// "transferQuantity": 5, | |
| 2690 | + // /// "itemId": "px001", | |
| 2691 | + // /// "itemName": "美容项目", | |
| 2692 | + // /// "itemPrice": 100.00, | |
| 2693 | + // /// "sourceType": "转卡", | |
| 2694 | + // /// "healthTeacherPerformances": [ | |
| 2695 | + // /// { | |
| 2696 | + // /// "healthTeacherId": "jks001", | |
| 2697 | + // /// "healthTeacherName": "张医生", | |
| 2698 | + // /// "healthTeacherAccount": "zhang001", | |
| 2699 | + // /// "performanceAmount": 50.00, | |
| 2700 | + // /// "laborCost": 20.00, | |
| 2701 | + // /// "itemQuantity": 5 | |
| 2702 | + // /// } | |
| 2703 | + // /// ], | |
| 2704 | + // /// "techTeacherPerformances": [ | |
| 2705 | + // /// { | |
| 2706 | + // /// "techTeacherId": "kjbs001", | |
| 2707 | + // /// "techTeacherName": "李老师", | |
| 2708 | + // /// "techTeacherAccount": "li001", | |
| 2709 | + // /// "performanceAmount": 30.00, | |
| 2710 | + // /// "laborCost": 10.00, | |
| 2711 | + // /// "itemQuantity": 5 | |
| 2712 | + // /// } | |
| 2713 | + // /// ] | |
| 2714 | + // /// } | |
| 2715 | + // /// ] | |
| 2716 | + // /// } | |
| 2717 | + // /// ``` | |
| 2718 | + // /// | |
| 2719 | + // /// 参数说明: | |
| 2720 | + // /// - fromMemberId: 转出会员ID | |
| 2721 | + // /// - toMemberId: 转入会员ID | |
| 2722 | + // /// - storeId: 门店ID | |
| 2723 | + // /// - signatureFile: 转出会员签名 | |
| 2724 | + // /// - remarks: 转卡备注 | |
| 2725 | + // /// - transferItems: 转出品项列表 | |
| 2726 | + // /// - billingItemId: 开单品项明细ID | |
| 2727 | + // /// - transferQuantity: 转出数量 | |
| 2728 | + // /// - itemId: 品项ID | |
| 2729 | + // /// - itemName: 品项名称 | |
| 2730 | + // /// - itemPrice: 品项价格 | |
| 2731 | + // /// - sourceType: 来源类型 | |
| 2732 | + // /// - healthTeacherPerformances: 健康师业绩列表 | |
| 2733 | + // /// - healthTeacherId: 健康师ID | |
| 2734 | + // /// - healthTeacherName: 健康师姓名 | |
| 2735 | + // /// - healthTeacherAccount: 健康师账号 | |
| 2736 | + // /// - performanceAmount: 业绩金额 | |
| 2737 | + // /// - laborCost: 人工成本 | |
| 2738 | + // /// - itemQuantity: 品项数量 | |
| 2739 | + // /// - techTeacherPerformances: 科技部老师业绩列表 | |
| 2740 | + // /// - techTeacherId: 科技部老师ID | |
| 2741 | + // /// - techTeacherName: 科技部老师姓名 | |
| 2742 | + // /// - techTeacherAccount: 科技部老师账号 | |
| 2743 | + // /// - performanceAmount: 业绩金额 | |
| 2744 | + // /// - laborCost: 人工成本 | |
| 2745 | + // /// - itemQuantity: 品项数量 | |
| 2746 | + // /// </remarks> | |
| 2747 | + // /// <param name="input">转卡输入参数</param> | |
| 2748 | + // /// <returns>转卡结果</returns> | |
| 2749 | + // /// <response code="200">转卡成功</response> | |
| 2750 | + // /// <response code="400">参数错误或业务规则验证失败</response> | |
| 2751 | + // /// <response code="500">服务器错误</response> | |
| 2752 | + // [HttpPost("TransferCard")] | |
| 2753 | + // public async Task<TransferCardOutput> TransferCard([FromBody] TransferCardInput input) | |
| 2754 | + // { | |
| 2755 | + // if (input == null) | |
| 2756 | + // { | |
| 2757 | + // throw NCCException.Oh("转卡参数不能为空"); | |
| 2758 | + // } | |
| 2759 | + | |
| 2760 | + // var userInfo = await _userManager.GetUserInfo(); | |
| 2761 | + // var transferTime = DateTime.Now; | |
| 2762 | + | |
| 2763 | + // try | |
| 2764 | + // { | |
| 2765 | + // // 开启事务 | |
| 2766 | + // _db.BeginTran(); | |
| 2767 | + | |
| 2768 | + // // 1. 验证转出和转入会员是否存在 | |
| 2769 | + // var fromMember = await _db.Queryable<LqKhxxEntity>().Where(x => x.Id == input.FromMemberId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync(); | |
| 2770 | + // if (fromMember == null) | |
| 2771 | + // { | |
| 2772 | + // throw NCCException.Oh("转出会员不存在或已失效"); | |
| 2773 | + // } | |
| 2774 | + // var toMember = await _db.Queryable<LqKhxxEntity>().Where(x => x.Id == input.ToMemberId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync(); | |
| 2775 | + // if (toMember == null) | |
| 2776 | + // { | |
| 2777 | + // throw NCCException.Oh("转入会员不存在或已失效"); | |
| 2778 | + // } | |
| 2779 | + | |
| 2780 | + // // 2. 验证转出品项的余额是否足够 | |
| 2781 | + // foreach (var item in input.TransferItems) | |
| 2782 | + // { | |
| 2783 | + // var billingItem = await _db.Queryable<LqKdPxmxEntity>().Where(x => x.Id == item.BillingItemId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync(); | |
| 2784 | + // if (billingItem == null) | |
| 2785 | + // { | |
| 2786 | + // throw NCCException.Oh($"品项明细不存在:{item.ItemName}"); | |
| 2787 | + // } | |
| 2788 | + | |
| 2789 | + // // 查询剩余数量 | |
| 2790 | + // var remainingCount = await GetItemRemainingCount(item.BillingItemId); | |
| 2791 | + // if (remainingCount < item.TransferQuantity) | |
| 2792 | + // { | |
| 2793 | + // throw NCCException.Oh($"品项 {item.ItemName} 剩余数量不足,当前剩余:{remainingCount},需要转出:{item.TransferQuantity}"); | |
| 2794 | + // } | |
| 2795 | + // } | |
| 2796 | + | |
| 2797 | + // // 3. 创建退卡记录(转出方) | |
| 2798 | + // var refundId = YitIdHelper.NextId().ToString(); | |
| 2799 | + // var totalRefundAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity); | |
| 2800 | + // var refundEntity = new LqHytkHytkEntity | |
| 2801 | + // { | |
| 2802 | + // Id = refundId, | |
| 2803 | + // F_CreateTime = transferTime, | |
| 2804 | + // F_CreateUser = userInfo.userId, | |
| 2805 | + // IsEffective = StatusEnum.有效.GetHashCode(), | |
| 2806 | + // Czry = userInfo.userId, | |
| 2807 | + // Hy = input.FromMemberId, | |
| 2808 | + // Hymc = fromMember.Khmc, | |
| 2809 | + // Md = input.StoreId, | |
| 2810 | + // SignatureFile = input.SignatureFile, | |
| 2811 | + // Tkje = totalRefundAmount, | |
| 2812 | + // ActualRefundAmount = totalRefundAmount, // 转卡时实退金额等于退卡总金额 | |
| 2813 | + // Tkyy = "转卡", | |
| 2814 | + // Bz = $"转卡给会员:{toMember.Khmc},{input.Remarks}" | |
| 2815 | + // }; | |
| 2816 | + // await _db.Insertable(refundEntity).ExecuteCommandAsync(); | |
| 2817 | + | |
| 2818 | + // // 4. 创建退卡品项明细和业绩记录 | |
| 2819 | + // var refundMxEntities = new List<LqHytkMxEntity>(); | |
| 2820 | + // var refundJksyjEntities = new List<LqHytkJksyjEntity>(); | |
| 2821 | + // var refundKjbsyjEntities = new List<LqHytkKjbsyjEntity>(); | |
| 2822 | + | |
| 2823 | + // foreach (var item in input.TransferItems) | |
| 2824 | + // { | |
| 2825 | + // var refundMxEntity = new LqHytkMxEntity | |
| 2826 | + // { | |
| 2827 | + // Id = YitIdHelper.NextId().ToString(), | |
| 2828 | + // RefundInfoId = refundId, | |
| 2829 | + // BillingItemId = item.BillingItemId, | |
| 2830 | + // CreateTime = transferTime, | |
| 2831 | + // CreateUser = userInfo.userId, | |
| 2832 | + // Px = item.ItemId, | |
| 2833 | + // Pxmc = item.ItemName, | |
| 2834 | + // Pxjg = item.ItemPrice, | |
| 2835 | + // Tkje = item.ItemPrice * item.TransferQuantity, | |
| 2836 | + // ProjectNumber = item.TransferQuantity, | |
| 2837 | + // SourceType = item.SourceType, | |
| 2838 | + // TotalPrice = item.ItemPrice * item.TransferQuantity, | |
| 2839 | + // IsEffective = StatusEnum.有效.GetHashCode() | |
| 2840 | + // }; | |
| 2841 | + // refundMxEntities.Add(refundMxEntity); | |
| 2842 | + | |
| 2843 | + // // 创建退卡健康师业绩记录 | |
| 2844 | + // if (item.HealthTeacherPerformances != null && item.HealthTeacherPerformances.Any()) | |
| 2845 | + // { | |
| 2846 | + // foreach (var jks in item.HealthTeacherPerformances) | |
| 2847 | + // { | |
| 2848 | + // refundJksyjEntities.Add(new LqHytkJksyjEntity | |
| 2849 | + // { | |
| 2850 | + // Id = YitIdHelper.NextId().ToString(), | |
| 2851 | + // Gltkbh = refundId, | |
| 2852 | + // Jks = jks.HealthTeacherId, | |
| 2853 | + // Jksxm = jks.HealthTeacherName, | |
| 2854 | + // Jkszh = jks.HealthTeacherAccount, | |
| 2855 | + // Jksyj = jks.PerformanceAmount, | |
| 2856 | + // Tksj = transferTime, | |
| 2857 | + // F_jsjid = jks.HealthTeacherId, | |
| 2858 | + // F_tkpxid = refundMxEntity.Id, | |
| 2859 | + // F_LaborCost = jks.LaborCost, | |
| 2860 | + // F_tkpxNumber = jks.ItemQuantity, | |
| 2861 | + // F_CreateTime = transferTime, | |
| 2862 | + // F_CreateUser = userInfo.userId, | |
| 2863 | + // CardReturn = refundMxEntity.Id, | |
| 2864 | + // IsEffective = StatusEnum.有效.GetHashCode() | |
| 2865 | + // }); | |
| 2866 | + // } | |
| 2867 | + // } | |
| 2868 | + | |
| 2869 | + // // 创建退卡科技部老师业绩记录 | |
| 2870 | + // if (item.TechTeacherPerformances != null && item.TechTeacherPerformances.Any()) | |
| 2871 | + // { | |
| 2872 | + // foreach (var kjbs in item.TechTeacherPerformances) | |
| 2873 | + // { | |
| 2874 | + // refundKjbsyjEntities.Add(new LqHytkKjbsyjEntity | |
| 2875 | + // { | |
| 2876 | + // Id = YitIdHelper.NextId().ToString(), | |
| 2877 | + // Gltkbh = refundId, | |
| 2878 | + // Kjbls = kjbs.TechTeacherId, | |
| 2879 | + // Kjblsxm = kjbs.TechTeacherName, | |
| 2880 | + // Kjblszh = kjbs.TechTeacherAccount, | |
| 2881 | + // Kjblsyj = kjbs.PerformanceAmount, | |
| 2882 | + // Tksj = transferTime, | |
| 2883 | + // F_tkpxid = refundMxEntity.Id, | |
| 2884 | + // F_LaborCost = kjbs.LaborCost, | |
| 2885 | + // F_tkpxNumber = kjbs.ItemQuantity, | |
| 2886 | + // F_CreateTime = transferTime, | |
| 2887 | + // F_CreateUser = userInfo.userId, | |
| 2888 | + // CardReturn = refundMxEntity.Id, | |
| 2889 | + // IsEffective = StatusEnum.有效.GetHashCode() | |
| 2890 | + // }); | |
| 2891 | + // } | |
| 2892 | + // } | |
| 2893 | + // } | |
| 2894 | + | |
| 2895 | + // await _db.Insertable(refundMxEntities).ExecuteCommandAsync(); | |
| 2896 | + // if (refundJksyjEntities.Any()) | |
| 2897 | + // { | |
| 2898 | + // await _db.Insertable(refundJksyjEntities).ExecuteCommandAsync(); | |
| 2899 | + // } | |
| 2900 | + // if (refundKjbsyjEntities.Any()) | |
| 2901 | + // { | |
| 2902 | + // await _db.Insertable(refundKjbsyjEntities).ExecuteCommandAsync(); | |
| 2903 | + // } | |
| 2904 | + | |
| 2905 | + // // 5. 创建开卡记录(转入方) | |
| 2906 | + // var billingId = YitIdHelper.NextId().ToString(); | |
| 2907 | + // var billingEntity = new LqKdKdjlbEntity | |
| 2908 | + // { | |
| 2909 | + // Id = billingId, | |
| 2910 | + // CreateTime = transferTime, | |
| 2911 | + // UpdateTime = transferTime, | |
| 2912 | + // IsEffective = StatusEnum.有效.GetHashCode(), | |
| 2913 | + // CreateUser = userInfo.userId, | |
| 2914 | + // Kdhy = input.ToMemberId, | |
| 2915 | + // Djmd = input.StoreId, | |
| 2916 | + // Sfyj = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity), | |
| 2917 | + // Bz = $"从会员 {fromMember.Khmc} 转入,{input.Remarks}" | |
| 2918 | + // }; | |
| 2919 | + // await _db.Insertable(billingEntity).ExecuteCommandAsync(); | |
| 2920 | + // // 6. 创建开单品项明细和业绩记录 | |
| 2921 | + // var billingPxmxEntities = new List<LqKdPxmxEntity>(); | |
| 2922 | + // var billingJksyjEntities = new List<LqKdJksyjEntity>(); | |
| 2923 | + // var billingKjbsyjEntities = new List<LqKdKjbsyjEntity>(); | |
| 2924 | + | |
| 2925 | + // foreach (var item in input.TransferItems) | |
| 2926 | + // { | |
| 2927 | + // var billingPxmxEntity = new LqKdPxmxEntity | |
| 2928 | + // { | |
| 2929 | + // Id = YitIdHelper.NextId().ToString(), | |
| 2930 | + // Glkdbh = billingId, | |
| 2931 | + // Px = item.ItemId, | |
| 2932 | + // Pxmc = item.ItemName, | |
| 2933 | + // Pxjg = item.ItemPrice, | |
| 2934 | + // MemberId = input.ToMemberId, | |
| 2935 | + // CreateTIme = transferTime, | |
| 2936 | + // ProjectNumber = item.TransferQuantity, | |
| 2937 | + // IsEnabled = StatusEnum.有效.GetHashCode(), | |
| 2938 | + // SourceType = item.SourceType, | |
| 2939 | + // TotalPrice = item.ItemPrice * item.TransferQuantity, | |
| 2940 | + // ActualPrice = item.ItemPrice * item.TransferQuantity, | |
| 2941 | + // IsEffective = StatusEnum.有效.GetHashCode(), | |
| 2942 | + // Remark = $"从会员 {fromMember.Khmc} 转入" | |
| 2943 | + // }; | |
| 2944 | + // billingPxmxEntities.Add(billingPxmxEntity); | |
| 2945 | + | |
| 2946 | + // // 创建开卡健康师业绩记录 | |
| 2947 | + // if (item.HealthTeacherPerformances != null && item.HealthTeacherPerformances.Any()) | |
| 2948 | + // { | |
| 2949 | + // foreach (var jks in item.HealthTeacherPerformances) | |
| 2950 | + // { | |
| 2951 | + // billingJksyjEntities.Add(new LqKdJksyjEntity | |
| 2952 | + // { | |
| 2953 | + // Id = YitIdHelper.NextId().ToString(), | |
| 2954 | + // Glkdbh = billingId, | |
| 2955 | + // Jks = jks.HealthTeacherId, | |
| 2956 | + // Jksxm = jks.HealthTeacherName, | |
| 2957 | + // Jkszh = jks.HealthTeacherAccount, | |
| 2958 | + // Jksyj = jks.PerformanceAmount.ToString(), | |
| 2959 | + // Yjsj = transferTime, | |
| 2960 | + // Jsj_id = jks.HealthTeacherId, | |
| 2961 | + // Kdpxid = billingPxmxEntity.Id, | |
| 2962 | + // IsEffective = StatusEnum.有效.GetHashCode() | |
| 2963 | + // }); | |
| 2964 | + // } | |
| 2965 | + // } | |
| 2966 | + | |
| 2967 | + // // 创建开卡科技部老师业绩记录 | |
| 2968 | + // if (item.TechTeacherPerformances != null && item.TechTeacherPerformances.Any()) | |
| 2969 | + // { | |
| 2970 | + // foreach (var kjbs in item.TechTeacherPerformances) | |
| 2971 | + // { | |
| 2972 | + // billingKjbsyjEntities.Add(new LqKdKjbsyjEntity | |
| 2973 | + // { | |
| 2974 | + // Id = YitIdHelper.NextId().ToString(), | |
| 2975 | + // Glkdbh = billingId, | |
| 2976 | + // Kjbls = kjbs.TechTeacherId, | |
| 2977 | + // Kjblsxm = kjbs.TechTeacherName, | |
| 2978 | + // Kjblszh = kjbs.TechTeacherAccount, | |
| 2979 | + // Kjblsyj = kjbs.PerformanceAmount.ToString(), | |
| 2980 | + // Yjsj = transferTime, | |
| 2981 | + // Kdpxid = billingPxmxEntity.Id, | |
| 2982 | + // LaborCost = kjbs.LaborCost, | |
| 2983 | + // IsEffective = StatusEnum.有效.GetHashCode() | |
| 2984 | + // }); | |
| 2985 | + // } | |
| 2986 | + // } | |
| 2987 | + // } | |
| 2988 | + | |
| 2989 | + // await _db.Insertable(billingPxmxEntities).ExecuteCommandAsync(); | |
| 2990 | + // if (billingJksyjEntities.Any()) | |
| 2991 | + // { | |
| 2992 | + // await _db.Insertable(billingJksyjEntities).ExecuteCommandAsync(); | |
| 2993 | + // } | |
| 2994 | + // if (billingKjbsyjEntities.Any()) | |
| 2995 | + // { | |
| 2996 | + // await _db.Insertable(billingKjbsyjEntities).ExecuteCommandAsync(); | |
| 2997 | + // } | |
| 2998 | + // // 提交事务 | |
| 2999 | + // _db.CommitTran(); | |
| 3000 | + | |
| 3001 | + // return new TransferCardOutput | |
| 3002 | + // { | |
| 3003 | + // Success = true, | |
| 3004 | + // TransferId = refundId, | |
| 3005 | + // RefundId = refundId, | |
| 3006 | + // BillingId = billingId, | |
| 3007 | + // TotalAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity), | |
| 3008 | + // TotalQuantity = input.TransferItems.Sum(x => x.TransferQuantity), | |
| 3009 | + // FromMemberName = fromMember.Khmc, | |
| 3010 | + // ToMemberName = toMember.Khmc, | |
| 3011 | + // TransferTime = transferTime, | |
| 3012 | + // Message = "转卡操作成功" | |
| 3013 | + // }; | |
| 3014 | + // } | |
| 3015 | + // catch (Exception ex) | |
| 3016 | + // { | |
| 3017 | + // _db.RollbackTran(); | |
| 3018 | + // _logger.LogError(ex, "转卡操作失败:{Message}", ex.Message); | |
| 3019 | + // throw NCCException.Oh($"转卡操作失败:{ex.Message}"); | |
| 3020 | + // } | |
| 3021 | + // } | |
| 3022 | + // #endregion | |
| 3023 | + | |
| 2672 | 3024 | #region 获取品项剩余数量 |
| 2673 | 3025 | /// <summary> |
| 2674 | 3026 | /// 获取品项剩余数量 | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
| ... | ... | @@ -531,7 +531,7 @@ namespace NCC.Extend.LqTkjlb |
| 531 | 531 | |
| 532 | 532 | #region 漏斗统计 |
| 533 | 533 | /// <summary> |
| 534 | - /// 获取拓客活动漏斗统计数据 | |
| 534 | + /// 获取拓客活动漏斗统计数据(优化版本) | |
| 535 | 535 | /// </summary> |
| 536 | 536 | /// <param name="eventId">活动ID</param> |
| 537 | 537 | /// <returns>漏斗统计数据</returns> |
| ... | ... | @@ -540,31 +540,49 @@ namespace NCC.Extend.LqTkjlb |
| 540 | 540 | { |
| 541 | 541 | try |
| 542 | 542 | { |
| 543 | + // 优化版本:使用子查询减少JOIN复杂度 | |
| 543 | 544 | var sql = @" |
| 544 | 545 | SELECT |
| 545 | 546 | md.F_Id as store_id, |
| 546 | 547 | md.dm as store_name, |
| 547 | - COUNT(DISTINCT tk.F_Id) as tk_count, -- 拓客数量 | |
| 548 | - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as yy_count, -- 预约人数(已确认) | |
| 549 | - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as hk_count, -- 耗卡人数 | |
| 550 | - COALESCE(SUM(CASE WHEN xh.F_Id IS NOT NULL THEN xh.xfje END), 0) as hk_amount, -- 耗卡金额 | |
| 551 | - ROUND( | |
| 552 | - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 / | |
| 553 | - COUNT(DISTINCT tk.F_Id), 2 | |
| 554 | - ) as yy_conversion_rate, -- 预约转化率(预约人数/拓客数量) | |
| 555 | - ROUND( | |
| 556 | - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 / | |
| 557 | - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END), 2 | |
| 558 | - ) as hk_conversion_rate -- 耗卡转化率(耗卡人数/预约人数) | |
| 559 | - FROM lq_tkjlb tk | |
| 560 | - JOIN lq_mdxx md ON tk.F_StoreId = md.F_Id | |
| 561 | - LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk | |
| 562 | - AND yy.F_Status = '已确认' | |
| 563 | - LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy | |
| 564 | - AND xh.F_IsEffective = 1 | |
| 565 | - WHERE tk.F_EventId = @eventId | |
| 566 | - GROUP BY md.F_Id, md.dm | |
| 567 | - ORDER BY tk_count DESC"; | |
| 548 | + tk_stats.tk_count, | |
| 549 | + tk_stats.yaoy_count, | |
| 550 | + tk_stats.yy_count, | |
| 551 | + tk_stats.hk_count, | |
| 552 | + tk_stats.kd_count, | |
| 553 | + tk_stats.hk_amount, | |
| 554 | + tk_stats.kd_amount, | |
| 555 | + CASE | |
| 556 | + WHEN tk_stats.tk_count > 0 | |
| 557 | + THEN ROUND(tk_stats.yy_count * 100.0 / tk_stats.tk_count, 2) | |
| 558 | + ELSE 0 | |
| 559 | + END as yy_conversion_rate, | |
| 560 | + CASE | |
| 561 | + WHEN tk_stats.yy_count > 0 | |
| 562 | + THEN ROUND(tk_stats.hk_count * 100.0 / tk_stats.yy_count, 2) | |
| 563 | + ELSE 0 | |
| 564 | + END as hk_conversion_rate | |
| 565 | + FROM lq_mdxx md | |
| 566 | + LEFT JOIN ( | |
| 567 | + SELECT | |
| 568 | + tk.F_StoreId, | |
| 569 | + COUNT(DISTINCT tk.F_Id) as tk_count, | |
| 570 | + COUNT(DISTINCT yy.F_Id) as yaoy_count, | |
| 571 | + COUNT(DISTINCT yyjl.F_Id) as yy_count, | |
| 572 | + COUNT(DISTINCT xh.F_Id) as hk_count, | |
| 573 | + COUNT(DISTINCT kd.F_Id) as kd_count, | |
| 574 | + COALESCE(SUM(xh.xfje), 0) as hk_amount, | |
| 575 | + COALESCE(SUM(kd.sfyj), 0) as kd_amount | |
| 576 | + FROM lq_tkjlb tk | |
| 577 | + LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId | |
| 578 | + LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认' | |
| 579 | + LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1 | |
| 580 | + LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1 | |
| 581 | + WHERE tk.F_EventId = @eventId | |
| 582 | + GROUP BY tk.F_StoreId | |
| 583 | + ) tk_stats ON md.F_Id = tk_stats.F_StoreId | |
| 584 | + WHERE tk_stats.F_StoreId IS NOT NULL | |
| 585 | + ORDER BY tk_stats.tk_count DESC"; | |
| 568 | 586 | |
| 569 | 587 | var result = await _db.Ado.SqlQueryAsync<dynamic>(sql, new { eventId }); |
| 570 | 588 | |
| ... | ... | @@ -582,7 +600,7 @@ namespace NCC.Extend.LqTkjlb |
| 582 | 600 | } |
| 583 | 601 | |
| 584 | 602 | /// <summary> |
| 585 | - /// 获取拓客活动总体漏斗统计 | |
| 603 | + /// 获取拓客活动总体漏斗统计(优化版本) | |
| 586 | 604 | /// </summary> |
| 587 | 605 | /// <param name="eventId">活动ID</param> |
| 588 | 606 | /// <returns>总体漏斗统计数据</returns> |
| ... | ... | @@ -593,24 +611,39 @@ namespace NCC.Extend.LqTkjlb |
| 593 | 611 | { |
| 594 | 612 | var sql = @" |
| 595 | 613 | SELECT |
| 596 | - COUNT(DISTINCT tk.F_Id) as total_tk_count, -- 总拓客数量 | |
| 597 | - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as total_yy_count, -- 总预约人数 | |
| 598 | - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as total_hk_count, -- 总耗卡人数 | |
| 599 | - COALESCE(SUM(CASE WHEN xh.F_Id IS NOT NULL THEN xh.xfje END), 0) as total_hk_amount, -- 总耗卡金额 | |
| 600 | - ROUND( | |
| 601 | - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 / | |
| 602 | - COUNT(DISTINCT tk.F_Id), 2 | |
| 603 | - ) as overall_yy_conversion_rate, -- 总体预约转化率 | |
| 604 | - ROUND( | |
| 605 | - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 / | |
| 606 | - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END), 2 | |
| 607 | - ) as overall_hk_conversion_rate -- 总体耗卡转化率 | |
| 608 | - FROM lq_tkjlb tk | |
| 609 | - LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk | |
| 610 | - AND yy.F_Status = '已确认' | |
| 611 | - LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy | |
| 612 | - AND xh.F_IsEffective = 1 | |
| 613 | - WHERE tk.F_EventId = @eventId"; | |
| 614 | + SUM(tk_count) as total_tk_count, | |
| 615 | + SUM(yaoy_count) as total_yaoy_count, | |
| 616 | + SUM(yy_count) as total_yy_count, | |
| 617 | + SUM(hk_count) as total_hk_count, | |
| 618 | + SUM(kd_count) as total_kd_count, | |
| 619 | + SUM(hk_amount) as total_hk_amount, | |
| 620 | + SUM(kd_amount) as total_kd_amount, | |
| 621 | + CASE | |
| 622 | + WHEN SUM(tk_count) > 0 | |
| 623 | + THEN ROUND(SUM(yy_count) * 100.0 / SUM(tk_count), 2) | |
| 624 | + ELSE 0 | |
| 625 | + END as overall_yy_conversion_rate, | |
| 626 | + CASE | |
| 627 | + WHEN SUM(yy_count) > 0 | |
| 628 | + THEN ROUND(SUM(hk_count) * 100.0 / SUM(yy_count), 2) | |
| 629 | + ELSE 0 | |
| 630 | + END as overall_hk_conversion_rate | |
| 631 | + FROM ( | |
| 632 | + SELECT | |
| 633 | + COUNT(DISTINCT tk.F_Id) as tk_count, | |
| 634 | + COUNT(DISTINCT yy.F_Id) as yaoy_count, | |
| 635 | + COUNT(DISTINCT yyjl.F_Id) as yy_count, | |
| 636 | + COUNT(DISTINCT xh.F_Id) as hk_count, | |
| 637 | + COUNT(DISTINCT kd.F_Id) as kd_count, | |
| 638 | + COALESCE(SUM(xh.xfje), 0) as hk_amount, | |
| 639 | + COALESCE(SUM(kd.sfyj), 0) as kd_amount | |
| 640 | + FROM lq_tkjlb tk | |
| 641 | + LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId | |
| 642 | + LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认' | |
| 643 | + LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1 | |
| 644 | + LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1 | |
| 645 | + WHERE tk.F_EventId = @eventId | |
| 646 | + ) stats"; | |
| 614 | 647 | |
| 615 | 648 | var result = await _db.Ado.SqlQueryAsync<dynamic>(sql, new { eventId }); |
| 616 | 649 | |
| ... | ... | @@ -626,6 +659,113 @@ namespace NCC.Extend.LqTkjlb |
| 626 | 659 | throw NCCException.Oh("获取总体漏斗统计数据失败:" + ex.Message); |
| 627 | 660 | } |
| 628 | 661 | } |
| 662 | + | |
| 663 | + /// <summary> | |
| 664 | + /// 获取拓客活动漏斗统计数据(高性能版本 - 分步查询) | |
| 665 | + /// </summary> | |
| 666 | + /// <param name="eventId">活动ID</param> | |
| 667 | + /// <returns>漏斗统计数据</returns> | |
| 668 | + [HttpGet("GetFunnelStatisticsFast/{eventId}")] | |
| 669 | + public async Task<dynamic> GetFunnelStatisticsFast(string eventId) | |
| 670 | + { | |
| 671 | + try | |
| 672 | + { | |
| 673 | + // 第一步:获取拓客基础数据 | |
| 674 | + var tkSql = @" | |
| 675 | + SELECT | |
| 676 | + tk.F_StoreId, | |
| 677 | + md.dm as store_name, | |
| 678 | + COUNT(DISTINCT tk.F_Id) as tk_count | |
| 679 | + FROM lq_tkjlb tk | |
| 680 | + JOIN lq_mdxx md ON tk.F_StoreId = md.F_Id | |
| 681 | + WHERE tk.F_EventId = @eventId | |
| 682 | + GROUP BY tk.F_StoreId, md.dm"; | |
| 683 | + | |
| 684 | + var tkData = await _db.Ado.SqlQueryAsync<dynamic>(tkSql, new { eventId }); | |
| 685 | + var tkDict = tkData.ToDictionary(x => (string)x.F_StoreId, x => x); | |
| 686 | + | |
| 687 | + // 第二步:获取邀约数据 | |
| 688 | + var yaoySql = @" | |
| 689 | + SELECT | |
| 690 | + tk.F_StoreId, | |
| 691 | + COUNT(DISTINCT yy.F_Id) as yaoy_count | |
| 692 | + FROM lq_tkjlb tk | |
| 693 | + LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId | |
| 694 | + WHERE tk.F_EventId = @eventId | |
| 695 | + GROUP BY tk.F_StoreId"; | |
| 696 | + | |
| 697 | + var yaoyData = await _db.Ado.SqlQueryAsync<dynamic>(yaoySql, new { eventId }); | |
| 698 | + var yaoyDict = yaoyData.ToDictionary(x => (string)x.F_StoreId, x => (int)x.yaoy_count); | |
| 699 | + | |
| 700 | + // 第三步:获取预约数据 | |
| 701 | + var yySql = @" | |
| 702 | + SELECT | |
| 703 | + tk.F_StoreId, | |
| 704 | + COUNT(DISTINCT yyjl.F_Id) as yy_count | |
| 705 | + FROM lq_tkjlb tk | |
| 706 | + LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认' | |
| 707 | + WHERE tk.F_EventId = @eventId | |
| 708 | + GROUP BY tk.F_StoreId"; | |
| 709 | + | |
| 710 | + var yyData = await _db.Ado.SqlQueryAsync<dynamic>(yySql, new { eventId }); | |
| 711 | + var yyDict = yyData.ToDictionary(x => (string)x.F_StoreId, x => (int)x.yy_count); | |
| 712 | + | |
| 713 | + // 第四步:获取耗卡数据 | |
| 714 | + var hkSql = @" | |
| 715 | + SELECT | |
| 716 | + tk.F_StoreId, | |
| 717 | + COUNT(DISTINCT xh.F_Id) as hk_count, | |
| 718 | + COALESCE(SUM(xh.xfje), 0) as hk_amount | |
| 719 | + FROM lq_tkjlb tk | |
| 720 | + LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1 | |
| 721 | + WHERE tk.F_EventId = @eventId | |
| 722 | + GROUP BY tk.F_StoreId"; | |
| 723 | + | |
| 724 | + var hkData = await _db.Ado.SqlQueryAsync<dynamic>(hkSql, new { eventId }); | |
| 725 | + var hkDict = hkData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.hk_count, amount = (decimal)x.hk_amount }); | |
| 726 | + | |
| 727 | + // 第五步:获取开单数据 | |
| 728 | + var kdSql = @" | |
| 729 | + SELECT | |
| 730 | + tk.F_StoreId, | |
| 731 | + COUNT(DISTINCT kd.F_Id) as kd_count, | |
| 732 | + COALESCE(SUM(kd.sfyj), 0) as kd_amount | |
| 733 | + FROM lq_tkjlb tk | |
| 734 | + LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1 | |
| 735 | + WHERE tk.F_EventId = @eventId | |
| 736 | + GROUP BY tk.F_StoreId"; | |
| 737 | + | |
| 738 | + var kdData = await _db.Ado.SqlQueryAsync<dynamic>(kdSql, new { eventId }); | |
| 739 | + var kdDict = kdData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.kd_count, amount = (decimal)x.kd_amount }); | |
| 740 | + | |
| 741 | + // 合并结果 | |
| 742 | + var result = tkDict.Values.Select(tk => new | |
| 743 | + { | |
| 744 | + store_id = tk.F_StoreId, | |
| 745 | + store_name = tk.store_name, | |
| 746 | + tk_count = (int)tk.tk_count, | |
| 747 | + yaoy_count = yaoyDict.ContainsKey(tk.F_StoreId) ? yaoyDict[tk.F_StoreId] : 0, | |
| 748 | + yy_count = yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0, | |
| 749 | + hk_count = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].count : 0, | |
| 750 | + kd_count = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].count : 0, | |
| 751 | + hk_amount = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].amount : 0m, | |
| 752 | + kd_amount = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].amount : 0m, | |
| 753 | + 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, | |
| 754 | + 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 | |
| 755 | + }).OrderByDescending(x => x.tk_count).ToList(); | |
| 756 | + | |
| 757 | + return new | |
| 758 | + { | |
| 759 | + success = true, | |
| 760 | + data = result, | |
| 761 | + message = "获取漏斗统计数据成功(高性能版本)" | |
| 762 | + }; | |
| 763 | + } | |
| 764 | + catch (Exception ex) | |
| 765 | + { | |
| 766 | + throw NCCException.Oh("获取漏斗统计数据失败:" + ex.Message); | |
| 767 | + } | |
| 768 | + } | |
| 629 | 769 | #endregion |
| 630 | 770 | |
| 631 | 771 | #region 门店顾客详情 | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqXmzlService.cs
| ... | ... | @@ -292,13 +292,13 @@ namespace NCC.Extend.LqXmzl |
| 292 | 292 | /// </summary> |
| 293 | 293 | /// <param name="fieldName">字段名称,支持:fl1、fl2、fl3、fl4、fl、qt1、beautyType、sourceType</param> |
| 294 | 294 | /// <returns>去重后的字段数据</returns> |
| 295 | - [HttpPost("GetDistinctFieldData")] | |
| 296 | - public async Task<dynamic> GetDistinctFieldData([FromBody] string fieldName) | |
| 295 | + [HttpGet("GetDistinctFieldData")] | |
| 296 | + public async Task<dynamic> GetDistinctFieldData([FromQuery] string fieldName) | |
| 297 | 297 | { |
| 298 | 298 | try |
| 299 | 299 | { |
| 300 | 300 | // 验证字段名称 |
| 301 | - var validFields = new[] { "fl1", "fl2", "fl3", "fl4", "fl", "qt1", "beautyType", "sourceType" }; | |
| 301 | + var validFields = new[] { "fl1", "fl2", "fl3", "fl4", "fl", "qt1", "qt2", "beautyType", "sourceType" }; | |
| 302 | 302 | if (!validFields.Contains(fieldName)) |
| 303 | 303 | { |
| 304 | 304 | throw NCCException.Oh($"无效的字段名称: {fieldName}。支持的字段: {string.Join(", ", validFields)}"); |
| ... | ... | @@ -350,6 +350,13 @@ namespace NCC.Extend.LqXmzl |
| 350 | 350 | .Distinct() |
| 351 | 351 | .ToListAsync(); |
| 352 | 352 | break; |
| 353 | + case "qt2": | |
| 354 | + distinctValues = await _db.Queryable<LqXmzlEntity>() | |
| 355 | + .Where(p => !string.IsNullOrEmpty(p.Qt2)) | |
| 356 | + .Select(p => p.Qt2) | |
| 357 | + .Distinct() | |
| 358 | + .ToListAsync(); | |
| 359 | + break; | |
| 353 | 360 | case "beautyType": |
| 354 | 361 | distinctValues = await _db.Queryable<LqXmzlEntity>() |
| 355 | 362 | .Where(p => !string.IsNullOrEmpty(p.BeautyType)) | ... | ... |