Commit 8514f46544def94ef639ababadd29b7523f896ea
1 parent
873e7a7d
feat: 优化业务逻辑和功能完善
- 更新项目规则文档 - 优化会员信息相关接口和DTO - 优化开单记录、耗卡、退卡等业务逻辑 - 新增开单记录按会员ID查询卡项接口 - 优化健康师统计输出 - 优化消耗反馈查询逻辑
Showing
17 changed files
with
513 additions
and
21 deletions
.vscode/launch.json
0 → 100644
| 1 | +{ | ||
| 2 | + "version": "0.2.0", | ||
| 3 | + "configurations": [ | ||
| 4 | + { | ||
| 5 | + // Use IntelliSense to find out which attributes exist for C# debugging | ||
| 6 | + // Use hover for the description of the existing attributes | ||
| 7 | + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md | ||
| 8 | + "name": ".NET Core Launch (web)", | ||
| 9 | + "type": "coreclr", | ||
| 10 | + "request": "launch", | ||
| 11 | + "preLaunchTask": "build", | ||
| 12 | + // If you have changed target frameworks, make sure to update the program path. | ||
| 13 | + "program": "${workspaceFolder}/netcore/src/Application/NCC.API/bin/Debug/net6.0/NCC.API.dll", | ||
| 14 | + "args": [], | ||
| 15 | + "cwd": "${workspaceFolder}/netcore/src/Application/NCC.API", | ||
| 16 | + "stopAtEntry": false, | ||
| 17 | + // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser | ||
| 18 | + "serverReadyAction": { | ||
| 19 | + "action": "openExternally", | ||
| 20 | + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" | ||
| 21 | + }, | ||
| 22 | + "env": { | ||
| 23 | + "ASPNETCORE_ENVIRONMENT": "Development" | ||
| 24 | + }, | ||
| 25 | + "sourceFileMap": { | ||
| 26 | + "/Views": "${workspaceFolder}/Views" | ||
| 27 | + } | ||
| 28 | + }, | ||
| 29 | + { | ||
| 30 | + "name": ".NET Core Attach", | ||
| 31 | + "type": "coreclr", | ||
| 32 | + "request": "attach" | ||
| 33 | + } | ||
| 34 | + ] | ||
| 35 | +} | ||
| 0 | \ No newline at end of file | 36 | \ No newline at end of file |
.vscode/tasks.json
0 → 100644
| 1 | +{ | ||
| 2 | + "version": "2.0.0", | ||
| 3 | + "tasks": [ | ||
| 4 | + { | ||
| 5 | + "label": "build", | ||
| 6 | + "command": "dotnet", | ||
| 7 | + "type": "process", | ||
| 8 | + "args": [ | ||
| 9 | + "build", | ||
| 10 | + "${workspaceFolder}/netcore/src/Application/NCC.API/NCC.API.csproj", | ||
| 11 | + "/property:GenerateFullPaths=true", | ||
| 12 | + "/consoleloggerparameters:NoSummary" | ||
| 13 | + ], | ||
| 14 | + "problemMatcher": "$msCompile" | ||
| 15 | + }, | ||
| 16 | + { | ||
| 17 | + "label": "publish", | ||
| 18 | + "command": "dotnet", | ||
| 19 | + "type": "process", | ||
| 20 | + "args": [ | ||
| 21 | + "publish", | ||
| 22 | + "${workspaceFolder}/netcore/src/Application/NCC.API/NCC.API.csproj", | ||
| 23 | + "/property:GenerateFullPaths=true", | ||
| 24 | + "/consoleloggerparameters:NoSummary" | ||
| 25 | + ], | ||
| 26 | + "problemMatcher": "$msCompile" | ||
| 27 | + }, | ||
| 28 | + { | ||
| 29 | + "label": "watch", | ||
| 30 | + "command": "dotnet", | ||
| 31 | + "type": "process", | ||
| 32 | + "args": [ | ||
| 33 | + "watch", | ||
| 34 | + "run", | ||
| 35 | + "${workspaceFolder}/netcore/src/Application/NCC.API/NCC.API.csproj", | ||
| 36 | + "/property:GenerateFullPaths=true", | ||
| 37 | + "/consoleloggerparameters:NoSummary" | ||
| 38 | + ], | ||
| 39 | + "problemMatcher": "$msCompile" | ||
| 40 | + } | ||
| 41 | + ] | ||
| 42 | +} | ||
| 0 | \ No newline at end of file | 43 | \ No newline at end of file |
PROJECT_RULES.md
| @@ -35,6 +35,7 @@ | @@ -35,6 +35,7 @@ | ||
| 35 | - **图标显示**: 所有列表数据都要有图标,不同颜色区分类型 | 35 | - **图标显示**: 所有列表数据都要有图标,不同颜色区分类型 |
| 36 | - **空值显示**: 没有信息的字段显示"无" | 36 | - **空值显示**: 没有信息的字段显示"无" |
| 37 | - **列表规范**: 列表数据不能换行 | 37 | - **列表规范**: 列表数据不能换行 |
| 38 | +- **弹窗显示**: 弹窗需要使用圆角 12px | ||
| 38 | 39 | ||
| 39 | ### 性能要求 | 40 | ### 性能要求 |
| 40 | - 启用懒加载和代码分割 | 41 | - 启用懒加载和代码分割 |
antis-ncc-admin/.env.development
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | 2 | ||
| 3 | VUE_CLI_BABEL_TRANSPILE_MODULES = true | 3 | VUE_CLI_BABEL_TRANSPILE_MODULES = true |
| 4 | # VUE_APP_BASE_API = 'https://erp.lvqianmeiye.com' | 4 | # VUE_APP_BASE_API = 'https://erp.lvqianmeiye.com' |
| 5 | -VUE_APP_BASE_API = 'http://erp_test.lvqianmeiye.com' | ||
| 6 | -# VUE_APP_BASE_API = 'http://localhost:2011' | 5 | +# VUE_APP_BASE_API = 'http://erp_test.lvqianmeiye.com' |
| 6 | +VUE_APP_BASE_API = 'http://localhost:2011' | ||
| 7 | # VUE_APP_BASE_API = 'http://localhost:2011' | 7 | # VUE_APP_BASE_API = 'http://localhost:2011' |
| 8 | VUE_APP_BASE_WSS = 'ws://192.168.110.45:2011/websocket' | 8 | VUE_APP_BASE_WSS = 'ws://192.168.110.45:2011/websocket' |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemsByMemberIdQueryInput.cs
0 → 100644
| 1 | +using System; | ||
| 2 | +using NCC.Common.Filter; | ||
| 3 | + | ||
| 4 | +namespace NCC.Extend.Entitys.Dto.LqKdKdjlb | ||
| 5 | +{ | ||
| 6 | + /// <summary> | ||
| 7 | + /// 会员开单品项列表查询输入 | ||
| 8 | + /// </summary> | ||
| 9 | + public class BillingItemsByMemberIdQueryInput : PageInputBase | ||
| 10 | + { | ||
| 11 | + /// <summary> | ||
| 12 | + /// 会员ID | ||
| 13 | + /// </summary> | ||
| 14 | + public string MemberId { get; set; } | ||
| 15 | + | ||
| 16 | + /// <summary> | ||
| 17 | + /// 品项分类 | ||
| 18 | + /// </summary> | ||
| 19 | + public string ItemCategory { get; set; } | ||
| 20 | + | ||
| 21 | + /// <summary> | ||
| 22 | + /// 开始时间(业绩时间) | ||
| 23 | + /// </summary> | ||
| 24 | + public DateTime? StartTime { get; set; } | ||
| 25 | + | ||
| 26 | + /// <summary> | ||
| 27 | + /// 结束时间(业绩时间) | ||
| 28 | + /// </summary> | ||
| 29 | + public DateTime? EndTime { get; set; } | ||
| 30 | + | ||
| 31 | + /// <summary> | ||
| 32 | + /// 最小实付金额 | ||
| 33 | + /// </summary> | ||
| 34 | + public decimal? MinActualPrice { get; set; } | ||
| 35 | + | ||
| 36 | + /// <summary> | ||
| 37 | + /// 最大实付金额 | ||
| 38 | + /// </summary> | ||
| 39 | + public decimal? MaxActualPrice { get; set; } | ||
| 40 | + | ||
| 41 | + /// <summary> | ||
| 42 | + /// 开单编号 | ||
| 43 | + /// </summary> | ||
| 44 | + public string BillingId { get; set; } | ||
| 45 | + } | ||
| 46 | +} |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/HealthCoachStatisticsOutput.cs
| @@ -89,5 +89,10 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb | @@ -89,5 +89,10 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb | ||
| 89 | /// 消耗项目数 - 统计该健康师在指定时间周期内消耗的项目总次数 | 89 | /// 消耗项目数 - 统计该健康师在指定时间周期内消耗的项目总次数 |
| 90 | /// </summary> | 90 | /// </summary> |
| 91 | public decimal projectCount { get; set; } | 91 | public decimal projectCount { get; set; } |
| 92 | + | ||
| 93 | + /// <summary> | ||
| 94 | + /// 退卡金额 - 统计该健康师在指定时间周期内的退卡业绩总金额 | ||
| 95 | + /// </summary> | ||
| 96 | + public decimal refundAmount { get; set; } | ||
| 92 | } | 97 | } |
| 93 | } | 98 | } |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/LqKhxxInfoOutput.cs
| @@ -151,6 +151,11 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx | @@ -151,6 +151,11 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx | ||
| 151 | public int isTechMember { get; set; } | 151 | public int isTechMember { get; set; } |
| 152 | 152 | ||
| 153 | /// <summary> | 153 | /// <summary> |
| 154 | + /// 是否教育部会员(0-否,1-是) | ||
| 155 | + /// </summary> | ||
| 156 | + public int isEducationMember { get; set; } | ||
| 157 | + | ||
| 158 | + /// <summary> | ||
| 154 | /// 成为生美会员时间 | 159 | /// 成为生美会员时间 |
| 155 | /// </summary> | 160 | /// </summary> |
| 156 | public DateTime? beautyMemberTime { get; set; } | 161 | public DateTime? beautyMemberTime { get; set; } |
| @@ -166,6 +171,11 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx | @@ -166,6 +171,11 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx | ||
| 166 | public DateTime? techMemberTime { get; set; } | 171 | public DateTime? techMemberTime { get; set; } |
| 167 | 172 | ||
| 168 | /// <summary> | 173 | /// <summary> |
| 174 | + /// 成为教育部会员时间 | ||
| 175 | + /// </summary> | ||
| 176 | + public DateTime? educationMemberTime { get; set; } | ||
| 177 | + | ||
| 178 | + /// <summary> | ||
| 169 | /// 首次到店时间 | 179 | /// 首次到店时间 |
| 170 | /// </summary> | 180 | /// </summary> |
| 171 | public DateTime? firstVisitTime { get; set; } | 181 | public DateTime? firstVisitTime { get; set; } |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/LqKhxxListOutput.cs
| @@ -178,6 +178,11 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx | @@ -178,6 +178,11 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx | ||
| 178 | public int isTechMember { get; set; } | 178 | public int isTechMember { get; set; } |
| 179 | 179 | ||
| 180 | /// <summary> | 180 | /// <summary> |
| 181 | + /// 是否教育部会员(0-否,1-是) | ||
| 182 | + /// </summary> | ||
| 183 | + public int isEducationMember { get; set; } | ||
| 184 | + | ||
| 185 | + /// <summary> | ||
| 181 | /// 成为生美会员时间 | 186 | /// 成为生美会员时间 |
| 182 | /// </summary> | 187 | /// </summary> |
| 183 | public DateTime? beautyMemberTime { get; set; } | 188 | public DateTime? beautyMemberTime { get; set; } |
| @@ -193,6 +198,11 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx | @@ -193,6 +198,11 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx | ||
| 193 | public DateTime? techMemberTime { get; set; } | 198 | public DateTime? techMemberTime { get; set; } |
| 194 | 199 | ||
| 195 | /// <summary> | 200 | /// <summary> |
| 201 | + /// 成为教育部会员时间 | ||
| 202 | + /// </summary> | ||
| 203 | + public DateTime? educationMemberTime { get; set; } | ||
| 204 | + | ||
| 205 | + /// <summary> | ||
| 196 | /// 首次到店时间 | 206 | /// 首次到店时间 |
| 197 | /// </summary> | 207 | /// </summary> |
| 198 | public DateTime? firstVisitTime { get; set; } | 208 | public DateTime? firstVisitTime { get; set; } |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/LqKhxxListQueryInput.cs
| @@ -83,6 +83,15 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx | @@ -83,6 +83,15 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx | ||
| 83 | /// </summary> | 83 | /// </summary> |
| 84 | public string tjr { get; set; } | 84 | public string tjr { get; set; } |
| 85 | 85 | ||
| 86 | + /// <summary> | ||
| 87 | + /// 是否科技部会员 | ||
| 88 | + /// </summary> | ||
| 89 | + public int? IsTechMemberbh { get; set; } | ||
| 90 | + | ||
| 91 | + /// <summary> | ||
| 92 | + /// 是否教育部会员 | ||
| 93 | + /// </summary> | ||
| 94 | + public int? IsEducationMember { get; set; } | ||
| 86 | 95 | ||
| 87 | /// <summary> | 96 | /// <summary> |
| 88 | /// 进店渠道 | 97 | /// 进店渠道 |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhFeedback/LqXhFeedbackListQueryInput.cs
| @@ -13,6 +13,11 @@ namespace NCC.Extend.Entitys.Dto.LqXhFeedback | @@ -13,6 +13,11 @@ namespace NCC.Extend.Entitys.Dto.LqXhFeedback | ||
| 13 | public string ConsumeId { get; set; } | 13 | public string ConsumeId { get; set; } |
| 14 | 14 | ||
| 15 | /// <summary> | 15 | /// <summary> |
| 16 | + /// 会员ID | ||
| 17 | + /// </summary> | ||
| 18 | + public string MemberId { get; set; } | ||
| 19 | + | ||
| 20 | + /// <summary> | ||
| 16 | /// 添加人ID | 21 | /// 添加人ID |
| 17 | /// </summary> | 22 | /// </summary> |
| 18 | public string CreateUser { get; set; } | 23 | public string CreateUser { get; set; } |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_khxx/LqKhxxEntity.cs
| @@ -184,6 +184,18 @@ namespace NCC.Extend.Entitys.lq_khxx | @@ -184,6 +184,18 @@ namespace NCC.Extend.Entitys.lq_khxx | ||
| 184 | public DateTime? TechMemberTime { get; set; } | 184 | public DateTime? TechMemberTime { get; set; } |
| 185 | 185 | ||
| 186 | /// <summary> | 186 | /// <summary> |
| 187 | + /// 是否教育部会员(0-否,1-是) | ||
| 188 | + /// </summary> | ||
| 189 | + [SugarColumn(ColumnName = "F_IsEducationMember")] | ||
| 190 | + public int IsEducationMember { get; set; } = 0; | ||
| 191 | + | ||
| 192 | + /// <summary> | ||
| 193 | + /// 成为教育部会员时间 | ||
| 194 | + /// </summary> | ||
| 195 | + [SugarColumn(ColumnName = "F_EducationMemberTime")] | ||
| 196 | + public DateTime? EducationMemberTime { get; set; } | ||
| 197 | + | ||
| 198 | + /// <summary> | ||
| 187 | /// 首次到店时间 | 199 | /// 首次到店时间 |
| 188 | /// </summary> | 200 | /// </summary> |
| 189 | [SugarColumn(ColumnName = "F_FirstVisitTime")] | 201 | [SugarColumn(ColumnName = "F_FirstVisitTime")] |
netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs
| @@ -435,6 +435,8 @@ namespace NCC.Extend.LqHytkHytk | @@ -435,6 +435,8 @@ namespace NCC.Extend.LqHytkHytk | ||
| 435 | F_CreateUser = userInfo.userId, | 435 | F_CreateUser = userInfo.userId, |
| 436 | CardReturn = lqHytkMxEntity.Id, | 436 | CardReturn = lqHytkMxEntity.Id, |
| 437 | IsEffective = StatusEnum.有效.GetHashCode(), | 437 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 438 | + ItemCategory = lqHytkMxEntity.ItemCategory, | ||
| 439 | + ItemId = lqHytkMxEntity.Px, | ||
| 438 | } | 440 | } |
| 439 | ); | 441 | ); |
| 440 | } | 442 | } |
| @@ -462,6 +464,8 @@ namespace NCC.Extend.LqHytkHytk | @@ -462,6 +464,8 @@ namespace NCC.Extend.LqHytkHytk | ||
| 462 | F_CreateUser = userInfo.userId, | 464 | F_CreateUser = userInfo.userId, |
| 463 | CardReturn = lqHytkMxEntity.Id, | 465 | CardReturn = lqHytkMxEntity.Id, |
| 464 | IsEffective = StatusEnum.有效.GetHashCode(), | 466 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 467 | + ItemCategory = lqHytkMxEntity.ItemCategory, | ||
| 468 | + ItemId = lqHytkMxEntity.Px, | ||
| 465 | } | 469 | } |
| 466 | ); | 470 | ); |
| 467 | } | 471 | } |
| @@ -586,6 +590,8 @@ namespace NCC.Extend.LqHytkHytk | @@ -586,6 +590,8 @@ namespace NCC.Extend.LqHytkHytk | ||
| 586 | F_tkpxNumber = ijks_tem.F_tkpxNumber, | 590 | F_tkpxNumber = ijks_tem.F_tkpxNumber, |
| 587 | F_CreateTime = DateTime.Now, | 591 | F_CreateTime = DateTime.Now, |
| 588 | F_CreateUser = userInfo.userId, | 592 | F_CreateUser = userInfo.userId, |
| 593 | + ItemCategory = lqHytkMxEntity.ItemCategory, | ||
| 594 | + ItemId = lqHytkMxEntity.Px, | ||
| 589 | } | 595 | } |
| 590 | ); | 596 | ); |
| 591 | } | 597 | } |
| @@ -611,6 +617,8 @@ namespace NCC.Extend.LqHytkHytk | @@ -611,6 +617,8 @@ namespace NCC.Extend.LqHytkHytk | ||
| 611 | F_tkpxNumber = ikjbs_tem.F_tkpxNumber, | 617 | F_tkpxNumber = ikjbs_tem.F_tkpxNumber, |
| 612 | F_CreateTime = DateTime.Now, | 618 | F_CreateTime = DateTime.Now, |
| 613 | F_CreateUser = userInfo.userId, | 619 | F_CreateUser = userInfo.userId, |
| 620 | + ItemCategory = lqHytkMxEntity.ItemCategory, | ||
| 621 | + ItemId = lqHytkMxEntity.Px, | ||
| 614 | } | 622 | } |
| 615 | ); | 623 | ); |
| 616 | } | 624 | } |
netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
| @@ -953,6 +953,8 @@ namespace NCC.Extend.LqKdKdjlb | @@ -953,6 +953,8 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 953 | Kdpxid = lqKdPxmxEntity.Id, | 953 | Kdpxid = lqKdPxmxEntity.Id, |
| 954 | IsEffective = StatusEnum.有效.GetHashCode(), | 954 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 955 | ActivityId = input.activityId, | 955 | ActivityId = input.activityId, |
| 956 | + ItemCategory = lqKdPxmxEntity.ItemCategory, | ||
| 957 | + ItemId = lqKdPxmxEntity.Px, | ||
| 956 | }); | 958 | }); |
| 957 | } | 959 | } |
| 958 | } | 960 | } |
| @@ -974,6 +976,8 @@ namespace NCC.Extend.LqKdKdjlb | @@ -974,6 +976,8 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 974 | Kdpxid = lqKdPxmxEntity.Id, | 976 | Kdpxid = lqKdPxmxEntity.Id, |
| 975 | IsEffective = StatusEnum.有效.GetHashCode(), | 977 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 976 | ActivityId = input.activityId, | 978 | ActivityId = input.activityId, |
| 979 | + ItemCategory = lqKdPxmxEntity.ItemCategory, | ||
| 980 | + ItemId = lqKdPxmxEntity.Px, | ||
| 977 | } | 981 | } |
| 978 | ); | 982 | ); |
| 979 | } | 983 | } |
| @@ -1750,6 +1754,8 @@ namespace NCC.Extend.LqKdKdjlb | @@ -1750,6 +1754,8 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 1750 | Kdpxid = lqKdPxmxEntity.Id, | 1754 | Kdpxid = lqKdPxmxEntity.Id, |
| 1751 | IsEffective = StatusEnum.有效.GetHashCode(), | 1755 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 1752 | ActivityId = input.activityId, | 1756 | ActivityId = input.activityId, |
| 1757 | + ItemCategory = lqKdPxmxEntity.ItemCategory, | ||
| 1758 | + ItemId = lqKdPxmxEntity.Px, | ||
| 1753 | }); | 1759 | }); |
| 1754 | } | 1760 | } |
| 1755 | } | 1761 | } |
| @@ -1771,6 +1777,8 @@ namespace NCC.Extend.LqKdKdjlb | @@ -1771,6 +1777,8 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 1771 | Kdpxid = lqKdPxmxEntity.Id, | 1777 | Kdpxid = lqKdPxmxEntity.Id, |
| 1772 | IsEffective = StatusEnum.有效.GetHashCode(), | 1778 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 1773 | ActivityId = input.activityId, | 1779 | ActivityId = input.activityId, |
| 1780 | + ItemCategory = lqKdPxmxEntity.ItemCategory, | ||
| 1781 | + ItemId = lqKdPxmxEntity.Px, | ||
| 1774 | } | 1782 | } |
| 1775 | ); | 1783 | ); |
| 1776 | } | 1784 | } |
| @@ -2308,6 +2316,48 @@ namespace NCC.Extend.LqKdKdjlb | @@ -2308,6 +2316,48 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 2308 | } | 2316 | } |
| 2309 | #endregion | 2317 | #endregion |
| 2310 | 2318 | ||
| 2319 | + #region 根据会员id获取会员的开单品项列表 | ||
| 2320 | + /// <summary> | ||
| 2321 | + /// 根据会员id获取会员的开单品项列表 | ||
| 2322 | + /// </summary> | ||
| 2323 | + /// <param name="input">查询参数</param> | ||
| 2324 | + /// <returns>会员的开单品项列表</returns> | ||
| 2325 | + [HttpPost("GetBillingItemsByMemberId")] | ||
| 2326 | + public async Task<dynamic> GetBillingItemsByMemberId([FromBody] BillingItemsByMemberIdQueryInput input) | ||
| 2327 | + { | ||
| 2328 | + try | ||
| 2329 | + { | ||
| 2330 | + var query = _db.Queryable<LqKdPxmxEntity>() | ||
| 2331 | + .Where(p => p.MemberId == input.MemberId) | ||
| 2332 | + .WhereIF(!string.IsNullOrEmpty(input.ItemCategory), p => p.ItemCategory == input.ItemCategory) | ||
| 2333 | + .WhereIF(!string.IsNullOrEmpty(input.BillingId), p => p.Glkdbh == input.BillingId) | ||
| 2334 | + .WhereIF(input.StartTime.HasValue, p => p.Yjsj >= input.StartTime.Value) | ||
| 2335 | + .WhereIF(input.EndTime.HasValue, p => p.Yjsj <= input.EndTime.Value) | ||
| 2336 | + .WhereIF(input.MinActualPrice.HasValue, p => p.ActualPrice >= input.MinActualPrice.Value) | ||
| 2337 | + .WhereIF(input.MaxActualPrice.HasValue, p => p.ActualPrice <= input.MaxActualPrice.Value) | ||
| 2338 | + .OrderBy(p => p.Yjsj, OrderByType.Desc); | ||
| 2339 | + | ||
| 2340 | + var list = await query.ToPageListAsync(input.currentPage, input.pageSize); | ||
| 2341 | + var totalCount = await query.CountAsync(); | ||
| 2342 | + | ||
| 2343 | + return new | ||
| 2344 | + { | ||
| 2345 | + list = list, | ||
| 2346 | + pagination = new | ||
| 2347 | + { | ||
| 2348 | + pageIndex = input.currentPage, | ||
| 2349 | + pageSize = input.pageSize, | ||
| 2350 | + totalCount = totalCount | ||
| 2351 | + } | ||
| 2352 | + }; | ||
| 2353 | + } | ||
| 2354 | + catch (Exception ex) | ||
| 2355 | + { | ||
| 2356 | + throw NCCException.Oh($"获取会员开单品项列表失败: {ex.Message}"); | ||
| 2357 | + } | ||
| 2358 | + } | ||
| 2359 | + #endregion | ||
| 2360 | + | ||
| 2311 | #region 根据开单id获取当前开单欠款信息 | 2361 | #region 根据开单id获取当前开单欠款信息 |
| 2312 | /// <summary> | 2362 | /// <summary> |
| 2313 | /// 根据开单id获取当前开单欠款信息 | 2363 | /// 根据开单id获取当前开单欠款信息 |
| @@ -3173,6 +3223,7 @@ namespace NCC.Extend.LqKdKdjlb | @@ -3173,6 +3223,7 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 3173 | /// - HeadCount: 人头(按客户去重) | 3223 | /// - HeadCount: 人头(按客户去重) |
| 3174 | /// - PersonCount: 人次(按客户+日期去重,同一客户不同天算多次) | 3224 | /// - PersonCount: 人次(按客户+日期去重,同一客户不同天算多次) |
| 3175 | /// - ProjectCount: 消耗项目数(项目总次数) | 3225 | /// - ProjectCount: 消耗项目数(项目总次数) |
| 3226 | + /// - RefundAmount: 退卡金额(健康师退卡业绩总金额) | ||
| 3176 | /// </remarks> | 3227 | /// </remarks> |
| 3177 | /// <param name="input">查询参数</param> | 3228 | /// <param name="input">查询参数</param> |
| 3178 | /// <returns>健康师统计数据列表</returns> | 3229 | /// <returns>健康师统计数据列表</returns> |
| @@ -3217,7 +3268,10 @@ namespace NCC.Extend.LqKdKdjlb | @@ -3217,7 +3268,10 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 3217 | CAST(COALESCE(personcount_stats.PersonCount, 0) AS DECIMAL(18,2)) as PersonCount, | 3268 | CAST(COALESCE(personcount_stats.PersonCount, 0) AS DECIMAL(18,2)) as PersonCount, |
| 3218 | CAST(COALESCE(invalid_headcount_stats.HeadCount, 0) AS DECIMAL(18,2)) as InvalidHeadCount, | 3269 | CAST(COALESCE(invalid_headcount_stats.HeadCount, 0) AS DECIMAL(18,2)) as InvalidHeadCount, |
| 3219 | CAST(COALESCE(invalid_personcount_stats.PersonCount, 0) AS DECIMAL(18,2)) as InvalidPersonCount, | 3270 | CAST(COALESCE(invalid_personcount_stats.PersonCount, 0) AS DECIMAL(18,2)) as InvalidPersonCount, |
| 3220 | - CAST(COALESCE(consume_stats.ProjectCount, 0) AS DECIMAL(18,2)) as ProjectCount | 3271 | + CAST(COALESCE(consume_stats.ProjectCount, 0) AS DECIMAL(18,2)) as ProjectCount, |
| 3272 | + | ||
| 3273 | + -- 退卡金额 | ||
| 3274 | + COALESCE(refund_stats.RefundAmount, 0) as RefundAmount | ||
| 3221 | 3275 | ||
| 3222 | FROM BASE_USER u | 3276 | FROM BASE_USER u |
| 3223 | LEFT JOIN lq_mdxx md ON u.F_MDID = md.F_Id | 3277 | LEFT JOIN lq_mdxx md ON u.F_MDID = md.F_Id |
| @@ -3382,6 +3436,19 @@ namespace NCC.Extend.LqKdKdjlb | @@ -3382,6 +3436,19 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 3382 | GROUP BY F_PersonId | 3436 | GROUP BY F_PersonId |
| 3383 | ) invalid_personcount_stats ON u.F_Id = invalid_personcount_stats.EmployeeId | 3437 | ) invalid_personcount_stats ON u.F_Id = invalid_personcount_stats.EmployeeId |
| 3384 | 3438 | ||
| 3439 | + -- 退卡统计子查询 | ||
| 3440 | + LEFT JOIN ( | ||
| 3441 | + SELECT | ||
| 3442 | + jkszh as EmployeeId, | ||
| 3443 | + SUM(CAST(jksyj AS DECIMAL(18,2))) as RefundAmount | ||
| 3444 | + FROM lq_hytk_jksyj | ||
| 3445 | + WHERE jkszh IS NOT NULL | ||
| 3446 | + AND F_IsEffective = 1 | ||
| 3447 | + AND tksj >= @startTime | ||
| 3448 | + AND tksj <= @endTime | ||
| 3449 | + GROUP BY jkszh | ||
| 3450 | + ) refund_stats ON u.F_Id = refund_stats.EmployeeId | ||
| 3451 | + | ||
| 3385 | WHERE u.F_GW = '健康师' | 3452 | WHERE u.F_GW = '健康师' |
| 3386 | "; | 3453 | "; |
| 3387 | 3454 | ||
| @@ -3966,5 +4033,101 @@ namespace NCC.Extend.LqKdKdjlb | @@ -3966,5 +4033,101 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 3966 | } | 4033 | } |
| 3967 | #endregion | 4034 | #endregion |
| 3968 | 4035 | ||
| 4036 | + #region 清空欠款 | ||
| 4037 | + /// <summary> | ||
| 4038 | + /// 清空欠款(减免剩余欠款) | ||
| 4039 | + /// </summary> | ||
| 4040 | + /// <remarks> | ||
| 4041 | + /// 返回参数说明: | ||
| 4042 | + /// - billingId: 开单ID | ||
| 4043 | + /// - original: 原始数据(zdyj-整单业绩, qk-欠款, paidDebt-已交欠款, remainingDebt-剩余欠款) | ||
| 4044 | + /// - updated: 更新后数据(zdyj-整单业绩, qk-欠款, paidDebt-已交欠款, remainingDebt-剩余欠款) | ||
| 4045 | + /// - reducedAmount: 减免金额 | ||
| 4046 | + /// </remarks> | ||
| 4047 | + /// <param name="id">开单记录ID</param> | ||
| 4048 | + /// <returns>操作结果</returns> | ||
| 4049 | + /// <response code="200">成功清空欠款</response> | ||
| 4050 | + /// <response code="400">参数错误或无剩余欠款</response> | ||
| 4051 | + /// <response code="404">开单记录不存在</response> | ||
| 4052 | + /// <response code="500">服务器错误</response> | ||
| 4053 | + [HttpPost("clear-debt/{id}")] | ||
| 4054 | + public async Task<dynamic> ClearDebt(string id) | ||
| 4055 | + { | ||
| 4056 | + try | ||
| 4057 | + { | ||
| 4058 | + // 1. 参数验证 | ||
| 4059 | + if (string.IsNullOrEmpty(id)) | ||
| 4060 | + { | ||
| 4061 | + throw NCCException.Oh("开单ID不能为空"); | ||
| 4062 | + } | ||
| 4063 | + // 2. 查询开单记录 | ||
| 4064 | + var entity = await _db.Queryable<LqKdKdjlbEntity>().FirstAsync(p => p.Id == id); | ||
| 4065 | + | ||
| 4066 | + if (entity == null) | ||
| 4067 | + { | ||
| 4068 | + throw NCCException.Oh("开单记录不存在"); | ||
| 4069 | + } | ||
| 4070 | + // 3. 验证开单是否有效 | ||
| 4071 | + if (entity.IsEffective != StatusEnum.有效.GetHashCode()) | ||
| 4072 | + { | ||
| 4073 | + throw NCCException.Oh("开单记录已作废,无法清空欠款"); | ||
| 4074 | + } | ||
| 4075 | + // 4. 计算剩余欠款 | ||
| 4076 | + var remainingDebt = entity.Qk - entity.PaidDebt; | ||
| 4077 | + | ||
| 4078 | + // 5. 验证是否有剩余欠款 | ||
| 4079 | + if (remainingDebt <= 0) | ||
| 4080 | + { | ||
| 4081 | + return new | ||
| 4082 | + { | ||
| 4083 | + billingId = id, | ||
| 4084 | + totalDebt = entity.Qk, | ||
| 4085 | + paidDebt = entity.PaidDebt, | ||
| 4086 | + remainingDebt = remainingDebt, | ||
| 4087 | + message = "该开单无剩余欠款,无需清空" | ||
| 4088 | + }; | ||
| 4089 | + } | ||
| 4090 | + | ||
| 4091 | + // 6. 记录原始数据(用于返回) | ||
| 4092 | + var originalZdyj = entity.Zdyj; | ||
| 4093 | + var originalQk = entity.Qk; | ||
| 4094 | + // 7. 执行欠款减免 | ||
| 4095 | + // 从整单业绩中减去剩余欠款 | ||
| 4096 | + entity.Zdyj = entity.Zdyj - remainingDebt; | ||
| 4097 | + // 欠款金额调整为已交金额(让剩余欠款归零) | ||
| 4098 | + entity.Qk = entity.PaidDebt; | ||
| 4099 | + // 更新时间 | ||
| 4100 | + entity.UpdateTime = DateTime.Now; | ||
| 4101 | + // 8. 更新数据库 | ||
| 4102 | + await _db.Updateable(entity).UpdateColumns(it => new { it.Zdyj, it.Qk, it.UpdateTime }).ExecuteCommandAsync(); | ||
| 4103 | + // 9. 返回结果 | ||
| 4104 | + return new | ||
| 4105 | + { | ||
| 4106 | + billingId = id, | ||
| 4107 | + original = new | ||
| 4108 | + { | ||
| 4109 | + zdyj = originalZdyj, | ||
| 4110 | + qk = originalQk, | ||
| 4111 | + paidDebt = entity.PaidDebt, | ||
| 4112 | + remainingDebt = remainingDebt | ||
| 4113 | + }, | ||
| 4114 | + updated = new | ||
| 4115 | + { | ||
| 4116 | + zdyj = entity.Zdyj, | ||
| 4117 | + qk = entity.Qk, | ||
| 4118 | + paidDebt = entity.PaidDebt, | ||
| 4119 | + remainingDebt = entity.Qk - entity.PaidDebt | ||
| 4120 | + }, | ||
| 4121 | + reducedAmount = remainingDebt | ||
| 4122 | + }; | ||
| 4123 | + } | ||
| 4124 | + catch (Exception ex) | ||
| 4125 | + { | ||
| 4126 | + _logger.LogError(ex, $"清空欠款失败 - 开单ID: {id}"); | ||
| 4127 | + throw NCCException.Oh($"清空欠款失败: {ex.Message}"); | ||
| 4128 | + } | ||
| 4129 | + } | ||
| 4130 | + #endregion | ||
| 4131 | + | ||
| 3969 | } | 4132 | } |
| 3970 | } | 4133 | } |
netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
| @@ -116,6 +116,8 @@ namespace NCC.Extend.LqKhxx | @@ -116,6 +116,8 @@ namespace NCC.Extend.LqKhxx | ||
| 116 | DateTime? endZcsj = queryZcsj != null ? Ext.GetDateTime(queryZcsj.Last()) : null; | 116 | DateTime? endZcsj = queryZcsj != null ? Ext.GetDateTime(queryZcsj.Last()) : null; |
| 117 | var data = await _db.Queryable<LqKhxxEntity>() | 117 | var data = await _db.Queryable<LqKhxxEntity>() |
| 118 | .WhereIF(!string.IsNullOrEmpty(input.keyWord), p => p.Khmc.Contains(input.keyWord) || p.Sjh.Contains(input.keyWord) || p.Dah.Contains(input.keyWord)) | 118 | .WhereIF(!string.IsNullOrEmpty(input.keyWord), p => p.Khmc.Contains(input.keyWord) || p.Sjh.Contains(input.keyWord) || p.Dah.Contains(input.keyWord)) |
| 119 | + .WhereIF(input.IsTechMemberbh.HasValue, p => p.IsTechMember == input.IsTechMemberbh) | ||
| 120 | + .WhereIF(input.IsEducationMember.HasValue, p => p.IsEducationMember == input.IsEducationMember) | ||
| 119 | .WhereIF(!string.IsNullOrEmpty(input.id), p => p.Id.Contains(input.id)) | 121 | .WhereIF(!string.IsNullOrEmpty(input.id), p => p.Id.Contains(input.id)) |
| 120 | .WhereIF(!string.IsNullOrEmpty(input.khmc), p => p.Khmc.Contains(input.khmc)) | 122 | .WhereIF(!string.IsNullOrEmpty(input.khmc), p => p.Khmc.Contains(input.khmc)) |
| 121 | .WhereIF(!string.IsNullOrEmpty(input.sjh), p => p.Sjh.Contains(input.sjh)) | 123 | .WhereIF(!string.IsNullOrEmpty(input.sjh), p => p.Sjh.Contains(input.sjh)) |
| @@ -163,9 +165,11 @@ namespace NCC.Extend.LqKhxx | @@ -163,9 +165,11 @@ namespace NCC.Extend.LqKhxx | ||
| 163 | isBeautyMember = it.IsBeautyMember, | 165 | isBeautyMember = it.IsBeautyMember, |
| 164 | isMedicalMember = it.IsMedicalMember, | 166 | isMedicalMember = it.IsMedicalMember, |
| 165 | isTechMember = it.IsTechMember, | 167 | isTechMember = it.IsTechMember, |
| 168 | + isEducationMember = it.IsEducationMember, | ||
| 166 | beautyMemberTime = it.BeautyMemberTime, | 169 | beautyMemberTime = it.BeautyMemberTime, |
| 167 | medicalMemberTime = it.MedicalMemberTime, | 170 | medicalMemberTime = it.MedicalMemberTime, |
| 168 | techMemberTime = it.TechMemberTime, | 171 | techMemberTime = it.TechMemberTime, |
| 172 | + educationMemberTime = it.EducationMemberTime, | ||
| 169 | firstVisitTime = it.FirstVisitTime, | 173 | firstVisitTime = it.FirstVisitTime, |
| 170 | lastVisitTime = it.LastVisitTime, | 174 | lastVisitTime = it.LastVisitTime, |
| 171 | visitDays = it.VisitDays, | 175 | visitDays = it.VisitDays, |
| @@ -1636,7 +1640,6 @@ namespace NCC.Extend.LqKhxx | @@ -1636,7 +1640,6 @@ namespace NCC.Extend.LqKhxx | ||
| 1636 | var techThreshold = MemberInfoUpdateConfig.TechMemberAmountThreshold; | 1640 | var techThreshold = MemberInfoUpdateConfig.TechMemberAmountThreshold; |
| 1637 | var minSleepThreshold = MemberInfoUpdateConfig.SleepDaysThresholds.Min(); | 1641 | var minSleepThreshold = MemberInfoUpdateConfig.SleepDaysThresholds.Min(); |
| 1638 | var now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); | 1642 | var now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); |
| 1639 | - | ||
| 1640 | // 构建SQL更新语句 | 1643 | // 构建SQL更新语句 |
| 1641 | var updateSql = $@" | 1644 | var updateSql = $@" |
| 1642 | UPDATE lq_khxx kh | 1645 | UPDATE lq_khxx kh |
netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
| @@ -741,6 +741,24 @@ namespace NCC.Extend.LqTkjlb | @@ -741,6 +741,24 @@ namespace NCC.Extend.LqTkjlb | ||
| 741 | /// <summary> | 741 | /// <summary> |
| 742 | /// 获取拓客活动漏斗统计数据(高性能版本 - 分步查询) | 742 | /// 获取拓客活动漏斗统计数据(高性能版本 - 分步查询) |
| 743 | /// </summary> | 743 | /// </summary> |
| 744 | + /// <remarks> | ||
| 745 | + /// 统计指定活动的漏斗转化数据 | ||
| 746 | + /// | ||
| 747 | + /// 返回字段说明: | ||
| 748 | + /// - store_id: 门店ID | ||
| 749 | + /// - store_name: 门店名称 | ||
| 750 | + /// - tk_count: 拓客数量(活动拓客总人数) | ||
| 751 | + /// - yaoy_count: 邀约数量(已邀约人数) | ||
| 752 | + /// - yy_count: 预约数量(已确认预约人数) | ||
| 753 | + /// - hk_count: 耗卡数量(实际到店耗卡人数) | ||
| 754 | + /// - kd_count: 开单数量(实际成交开单人数) | ||
| 755 | + /// - hk_amount: 耗卡金额(总耗卡业绩) | ||
| 756 | + /// - kd_amount: 开单金额(总成交业绩) | ||
| 757 | + /// - yy_conversion_rate: 预约转化率 (预约数量/拓客数量) | ||
| 758 | + /// - hk_conversion_rate: 耗卡转化率 (耗卡数量/预约数量) | ||
| 759 | + /// - visit_rate: 到店率 (耗卡数量/拓客数量) | ||
| 760 | + /// - deal_rate: 成交率 (开单数量/耗卡数量) | ||
| 761 | + /// </remarks> | ||
| 744 | /// <param name="eventId">活动ID</param> | 762 | /// <param name="eventId">活动ID</param> |
| 745 | /// <returns>漏斗统计数据</returns> | 763 | /// <returns>漏斗统计数据</returns> |
| 746 | [HttpGet("GetFunnelStatisticsFast/{eventId}")] | 764 | [HttpGet("GetFunnelStatisticsFast/{eventId}")] |
| @@ -803,6 +821,7 @@ namespace NCC.Extend.LqTkjlb | @@ -803,6 +821,7 @@ namespace NCC.Extend.LqTkjlb | ||
| 803 | var hkDict = hkData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.hk_count, amount = (decimal)x.hk_amount }); | 821 | var hkDict = hkData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.hk_count, amount = (decimal)x.hk_amount }); |
| 804 | 822 | ||
| 805 | // 第五步:获取开单数据(按会员ID去重,但金额不去重) | 823 | // 第五步:获取开单数据(按会员ID去重,但金额不去重) |
| 824 | + // 修改:增加 sfyj > 0 的条件 | ||
| 806 | var kdSql = @" | 825 | var kdSql = @" |
| 807 | SELECT | 826 | SELECT |
| 808 | tk.F_StoreId, | 827 | tk.F_StoreId, |
| @@ -810,26 +829,40 @@ namespace NCC.Extend.LqTkjlb | @@ -810,26 +829,40 @@ namespace NCC.Extend.LqTkjlb | ||
| 810 | COALESCE(SUM(kd.sfyj), 0) as kd_amount | 829 | COALESCE(SUM(kd.sfyj), 0) as kd_amount |
| 811 | FROM lq_tkjlb tk | 830 | FROM lq_tkjlb tk |
| 812 | LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1 | 831 | LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1 |
| 813 | - WHERE tk.F_EventId = @eventId AND kd.F_Id IS NOT NULL | 832 | + WHERE tk.F_EventId = @eventId AND kd.F_Id IS NOT NULL AND kd.sfyj > 0 |
| 814 | GROUP BY tk.F_StoreId"; | 833 | GROUP BY tk.F_StoreId"; |
| 815 | 834 | ||
| 816 | var kdData = await _db.Ado.SqlQueryAsync<dynamic>(kdSql, new { eventId }); | 835 | var kdData = await _db.Ado.SqlQueryAsync<dynamic>(kdSql, new { eventId }); |
| 817 | var kdDict = kdData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.kd_count, amount = (decimal)x.kd_amount }); | 836 | var kdDict = kdData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.kd_count, amount = (decimal)x.kd_amount }); |
| 818 | 837 | ||
| 819 | // 合并结果 | 838 | // 合并结果 |
| 820 | - var result = tkDict.Values.Select(tk => new | 839 | + var result = tkDict.Values.Select(tk => |
| 821 | { | 840 | { |
| 822 | - store_id = tk.F_StoreId, | ||
| 823 | - store_name = tk.store_name, | ||
| 824 | - tk_count = (int)tk.tk_count, | ||
| 825 | - yaoy_count = yaoyDict.ContainsKey(tk.F_StoreId) ? yaoyDict[tk.F_StoreId] : 0, | ||
| 826 | - yy_count = yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0, | ||
| 827 | - hk_count = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].count : 0, | ||
| 828 | - kd_count = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].count : 0, | ||
| 829 | - hk_amount = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].amount : 0m, | ||
| 830 | - kd_amount = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].amount : 0m, | ||
| 831 | - 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, | ||
| 832 | - 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 | 841 | + var tkCount = (int)tk.tk_count; |
| 842 | + var yyCount = yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0; | ||
| 843 | + var hkCount = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].count : 0; | ||
| 844 | + var kdCount = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].count : 0; | ||
| 845 | + | ||
| 846 | + return new | ||
| 847 | + { | ||
| 848 | + store_id = tk.F_StoreId, | ||
| 849 | + store_name = tk.store_name, | ||
| 850 | + tk_count = tkCount, | ||
| 851 | + yaoy_count = yaoyDict.ContainsKey(tk.F_StoreId) ? yaoyDict[tk.F_StoreId] : 0, | ||
| 852 | + yy_count = yyCount, | ||
| 853 | + hk_count = hkCount, | ||
| 854 | + kd_count = kdCount, | ||
| 855 | + hk_amount = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].amount : 0m, | ||
| 856 | + kd_amount = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].amount : 0m, | ||
| 857 | + // 预约转化率 = 预约 / 拓客 | ||
| 858 | + yy_conversion_rate = tkCount > 0 ? Math.Round(yyCount * 100.0 / tkCount, 2) : 0, | ||
| 859 | + // 耗卡转化率 = 耗卡 / 预约 | ||
| 860 | + hk_conversion_rate = yyCount > 0 ? Math.Round(hkCount * 100.0 / yyCount, 2) : 0, | ||
| 861 | + // 到店率 = 耗卡 / 拓客 | ||
| 862 | + visit_rate = tkCount > 0 ? Math.Round(hkCount * 100.0 / tkCount, 2) : 0, | ||
| 863 | + // 成交率 = 开单 / 耗卡 | ||
| 864 | + deal_rate = hkCount > 0 ? Math.Round(kdCount * 100.0 / hkCount, 2) : 0 | ||
| 865 | + }; | ||
| 833 | }).OrderByDescending(x => x.tk_count).ToList(); | 866 | }).OrderByDescending(x => x.tk_count).ToList(); |
| 834 | 867 | ||
| 835 | return new | 868 | return new |
| @@ -868,7 +901,7 @@ namespace NCC.Extend.LqTkjlb | @@ -868,7 +901,7 @@ namespace NCC.Extend.LqTkjlb | ||
| 868 | -- 预约信息 | 901 | -- 预约信息 |
| 869 | yy.F_Id as yy_id, -- 预约ID | 902 | yy.F_Id as yy_id, -- 预约ID |
| 870 | yy.F_Status as yy_status, -- 预约状态 | 903 | yy.F_Status as yy_status, -- 预约状态 |
| 871 | - yy.F_CreateTime as yy_time, -- 预约时间 | 904 | + yy.czsj as yy_time, -- 预约操作时间 |
| 872 | yy.yysj as appointment_time, -- 预约到店时间 | 905 | yy.yysj as appointment_time, -- 预约到店时间 |
| 873 | -- 耗卡信息(聚合) | 906 | -- 耗卡信息(聚合) |
| 874 | xh_summary.total_consume_amount, -- 耗卡总金额 | 907 | xh_summary.total_consume_amount, -- 耗卡总金额 |
| @@ -891,7 +924,7 @@ namespace NCC.Extend.LqTkjlb | @@ -891,7 +924,7 @@ namespace NCC.Extend.LqTkjlb | ||
| 891 | ELSE '未预约' | 924 | ELSE '未预约' |
| 892 | END as appointment_status, -- 预约状态描述 | 925 | END as appointment_status, -- 预约状态描述 |
| 893 | CASE | 926 | CASE |
| 894 | - WHEN xh_summary.total_consume_amount > 0 THEN '已耗卡' | 927 | + WHEN xh_summary.consume_count > 0 THEN '已耗卡' |
| 895 | ELSE '未耗卡' | 928 | ELSE '未耗卡' |
| 896 | END as consume_status, -- 耗卡状态描述 | 929 | END as consume_status, -- 耗卡状态描述 |
| 897 | CASE | 930 | CASE |
| @@ -905,14 +938,14 @@ namespace NCC.Extend.LqTkjlb | @@ -905,14 +938,14 @@ namespace NCC.Extend.LqTkjlb | ||
| 905 | AND yy.F_Status = '已确认' | 938 | AND yy.F_Status = '已确认' |
| 906 | LEFT JOIN ( | 939 | LEFT JOIN ( |
| 907 | SELECT | 940 | SELECT |
| 908 | - hy as member_id, | 941 | + hyzh as member_id, |
| 909 | SUM(COALESCE(xfje, 0)) as total_consume_amount, | 942 | SUM(COALESCE(xfje, 0)) as total_consume_amount, |
| 910 | COUNT(*) as consume_count, | 943 | COUNT(*) as consume_count, |
| 911 | MIN(hksj) as first_consume_time, | 944 | MIN(hksj) as first_consume_time, |
| 912 | MAX(hksj) as last_consume_time | 945 | MAX(hksj) as last_consume_time |
| 913 | FROM lq_xh_hyhk | 946 | FROM lq_xh_hyhk |
| 914 | WHERE F_IsEffective = 1 | 947 | WHERE F_IsEffective = 1 |
| 915 | - GROUP BY hy | 948 | + GROUP BY hyzh |
| 916 | ) xh_summary ON tk.F_MemberId = xh_summary.member_id | 949 | ) xh_summary ON tk.F_MemberId = xh_summary.member_id |
| 917 | LEFT JOIN ( | 950 | LEFT JOIN ( |
| 918 | SELECT | 951 | SELECT |
| @@ -962,6 +995,34 @@ namespace NCC.Extend.LqTkjlb | @@ -962,6 +995,34 @@ namespace NCC.Extend.LqTkjlb | ||
| 962 | /// <summary> | 995 | /// <summary> |
| 963 | /// 获取门店拓客活动顾客详情(分页) | 996 | /// 获取门店拓客活动顾客详情(分页) |
| 964 | /// </summary> | 997 | /// </summary> |
| 998 | + /// <remarks> | ||
| 999 | + /// 返回字段说明: | ||
| 1000 | + /// - tk_id: 拓客记录ID | ||
| 1001 | + /// - customer_phone: 顾客手机号 | ||
| 1002 | + /// - member_id: 会员ID | ||
| 1003 | + /// - customer_name: 顾客姓名 | ||
| 1004 | + /// - tk_time: 拓客时间 | ||
| 1005 | + /// - yaoy_id: 邀约ID | ||
| 1006 | + /// - yaoy_time: 邀约创建时间 | ||
| 1007 | + /// - yaoy_appointment_time: 邀约预约时间 | ||
| 1008 | + /// - yy_id: 预约ID | ||
| 1009 | + /// - yy_status: 预约状态 | ||
| 1010 | + /// - yy_time: 预约创建时间 | ||
| 1011 | + /// - appointment_time: 预约到店时间 | ||
| 1012 | + /// - total_consume_amount: 耗卡总金额 | ||
| 1013 | + /// - consume_count: 耗卡次数 | ||
| 1014 | + /// - first_consume_time: 首次耗卡时间 | ||
| 1015 | + /// - last_consume_time: 最后耗卡时间 | ||
| 1016 | + /// - total_billing_amount: 开卡总金额 | ||
| 1017 | + /// - total_debt_amount: 总欠款金额 | ||
| 1018 | + /// - billing_count: 开卡次数 | ||
| 1019 | + /// - first_billing_time: 首次开卡时间 | ||
| 1020 | + /// - last_billing_time: 最后开卡时间 | ||
| 1021 | + /// - invitation_status: 邀约状态描述 (已邀约/未邀约) | ||
| 1022 | + /// - appointment_status: 预约状态描述 (已预约/未预约) | ||
| 1023 | + /// - consume_status: 耗卡状态描述 (已耗卡/未耗卡) | ||
| 1024 | + /// - billing_status: 开卡状态描述 (已开卡/未开卡) | ||
| 1025 | + /// </remarks> | ||
| 965 | /// <param name="eventId">活动ID</param> | 1026 | /// <param name="eventId">活动ID</param> |
| 966 | /// <param name="storeId">门店ID</param> | 1027 | /// <param name="storeId">门店ID</param> |
| 967 | /// <param name="pageIndex">页码</param> | 1028 | /// <param name="pageIndex">页码</param> |
netcore/src/Modularity/Extend/NCC.Extend/LqXhFeedbackService.cs
| @@ -303,5 +303,79 @@ namespace NCC.Extend | @@ -303,5 +303,79 @@ namespace NCC.Extend | ||
| 303 | } | 303 | } |
| 304 | } | 304 | } |
| 305 | #endregion | 305 | #endregion |
| 306 | + | ||
| 307 | + #region 获取耗卡反馈列表 | ||
| 308 | + /// <summary> | ||
| 309 | + /// 获取耗卡反馈列表 | ||
| 310 | + /// </summary> | ||
| 311 | + /// <remarks> | ||
| 312 | + /// 获取耗卡反馈列表,支持分页和条件查询 | ||
| 313 | + /// | ||
| 314 | + /// 示例请求: | ||
| 315 | + /// POST /api/Extend/LqXhFeedback/GetList | ||
| 316 | + /// { | ||
| 317 | + /// "currentPage": 1, | ||
| 318 | + /// "pageSize": 10, | ||
| 319 | + /// "memberId": "会员ID", | ||
| 320 | + /// "startTime": "2025-01-01", | ||
| 321 | + /// "endTime": "2025-01-31" | ||
| 322 | + /// } | ||
| 323 | + /// | ||
| 324 | + /// 参数说明: | ||
| 325 | + /// - currentPage: 当前页码 | ||
| 326 | + /// - pageSize: 每页条数 | ||
| 327 | + /// - memberId: 会员ID(可选) | ||
| 328 | + /// - consumeId: 耗卡记录ID(可选) | ||
| 329 | + /// - startTime: 开始时间(可选) | ||
| 330 | + /// - endTime: 结束时间(可选) | ||
| 331 | + /// </remarks> | ||
| 332 | + /// <param name="input">查询参数</param> | ||
| 333 | + /// <returns>耗卡反馈列表</returns> | ||
| 334 | + [HttpPost("GetList")] | ||
| 335 | + public async Task<dynamic> GetList([FromBody] LqXhFeedbackListQueryInput input) | ||
| 336 | + { | ||
| 337 | + try | ||
| 338 | + { | ||
| 339 | + var query = _db.Queryable<LqXhFeedbackEntity>() | ||
| 340 | + .WhereIF(!string.IsNullOrEmpty(input.MemberId), p => p.MemberId == input.MemberId) | ||
| 341 | + .WhereIF(!string.IsNullOrEmpty(input.ConsumeId), p => p.ConsumeId == input.ConsumeId) | ||
| 342 | + .WhereIF(!string.IsNullOrEmpty(input.CreateUser), p => p.CreateUser == input.CreateUser) | ||
| 343 | + .WhereIF(input.StartTime.HasValue, p => p.CreateTime >= input.StartTime.Value) | ||
| 344 | + .WhereIF(input.EndTime.HasValue, p => p.CreateTime <= input.EndTime.Value) | ||
| 345 | + .OrderBy(p => p.CreateTime, OrderByType.Desc); | ||
| 346 | + | ||
| 347 | + var list = await query.ToPageListAsync(input.currentPage, input.pageSize); | ||
| 348 | + var totalCount = await query.CountAsync(); | ||
| 349 | + | ||
| 350 | + var data = list.Adapt<List<LqXhFeedbackListOutput>>(); | ||
| 351 | + | ||
| 352 | + // 填充添加人姓名 | ||
| 353 | + if (data.Any()) | ||
| 354 | + { | ||
| 355 | + var userIds = data.Select(x => x.createUser).Distinct().ToList(); | ||
| 356 | + var users = await _db.Queryable<UserEntity>().Where(x => userIds.Contains(x.Id)).ToListAsync(); | ||
| 357 | + foreach (var item in data) | ||
| 358 | + { | ||
| 359 | + item.createUserName = users.FirstOrDefault(x => x.Id == item.createUser)?.RealName; | ||
| 360 | + } | ||
| 361 | + } | ||
| 362 | + | ||
| 363 | + return new | ||
| 364 | + { | ||
| 365 | + list = data, | ||
| 366 | + pagination = new | ||
| 367 | + { | ||
| 368 | + pageIndex = input.currentPage, | ||
| 369 | + pageSize = input.pageSize, | ||
| 370 | + totalCount = totalCount | ||
| 371 | + } | ||
| 372 | + }; | ||
| 373 | + } | ||
| 374 | + catch (Exception ex) | ||
| 375 | + { | ||
| 376 | + throw NCCException.Oh($"获取耗卡反馈列表失败: {ex.Message}"); | ||
| 377 | + } | ||
| 378 | + } | ||
| 379 | + #endregion | ||
| 306 | } | 380 | } |
| 307 | } | 381 | } |
netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
| @@ -968,6 +968,8 @@ namespace NCC.Extend.LqXhHyhk | @@ -968,6 +968,8 @@ namespace NCC.Extend.LqXhHyhk | ||
| 968 | IsAccompanied = ijks_tem.isAccompanied, | 968 | IsAccompanied = ijks_tem.isAccompanied, |
| 969 | AccompaniedProjectNumber = ijks_tem.accompaniedProjectNumber, | 969 | AccompaniedProjectNumber = ijks_tem.accompaniedProjectNumber, |
| 970 | IsEffective = StatusEnum.有效.GetHashCode(), | 970 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 971 | + ItemCategory = lqXhPxmxEntity.ItemCategory, | ||
| 972 | + ItemId = lqXhPxmxEntity.Px, | ||
| 971 | } | 973 | } |
| 972 | ); | 974 | ); |
| 973 | } | 975 | } |
| @@ -1003,6 +1005,8 @@ namespace NCC.Extend.LqXhHyhk | @@ -1003,6 +1005,8 @@ namespace NCC.Extend.LqXhHyhk | ||
| 1003 | OvertimeLaborCost = 0, | 1005 | OvertimeLaborCost = 0, |
| 1004 | LaborCost = ikjbs_tem.laborCost, | 1006 | LaborCost = ikjbs_tem.laborCost, |
| 1005 | IsEffective = StatusEnum.有效.GetHashCode(), | 1007 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 1008 | + ItemCategory = lqXhPxmxEntity.ItemCategory, | ||
| 1009 | + ItemId = lqXhPxmxEntity.Px, | ||
| 1006 | } | 1010 | } |
| 1007 | ); | 1011 | ); |
| 1008 | } | 1012 | } |
| @@ -1335,6 +1339,8 @@ namespace NCC.Extend.LqXhHyhk | @@ -1335,6 +1339,8 @@ namespace NCC.Extend.LqXhHyhk | ||
| 1335 | IsEffective = StatusEnum.有效.GetHashCode(), | 1339 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 1336 | IsAccompanied = ijks_tem.isAccompanied, | 1340 | IsAccompanied = ijks_tem.isAccompanied, |
| 1337 | AccompaniedProjectNumber = ijks_tem.accompaniedProjectNumber, | 1341 | AccompaniedProjectNumber = ijks_tem.accompaniedProjectNumber, |
| 1342 | + ItemCategory = lqXhPxmxEntity.ItemCategory, | ||
| 1343 | + ItemId = lqXhPxmxEntity.Px, | ||
| 1338 | } | 1344 | } |
| 1339 | ); | 1345 | ); |
| 1340 | } | 1346 | } |
| @@ -1369,6 +1375,8 @@ namespace NCC.Extend.LqXhHyhk | @@ -1369,6 +1375,8 @@ namespace NCC.Extend.LqXhHyhk | ||
| 1369 | OvertimeLaborCost = 0, | 1375 | OvertimeLaborCost = 0, |
| 1370 | LaborCost = ikjbs_tem.laborCost, | 1376 | LaborCost = ikjbs_tem.laborCost, |
| 1371 | IsEffective = StatusEnum.有效.GetHashCode(), | 1377 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 1378 | + ItemCategory = lqXhPxmxEntity.ItemCategory, | ||
| 1379 | + ItemId = lqXhPxmxEntity.Px, | ||
| 1372 | }); | 1380 | }); |
| 1373 | } | 1381 | } |
| 1374 | } | 1382 | } |