Commit f390c57fdd8643fc16957da3d0eff410b23c3e7b
Merge branch 'master' of http://39.98.150.180/antissoft/lvqianmeiye_ERP
Showing
32 changed files
with
1991 additions
and
118 deletions
netcore/src/Application/NCC.API/appsettings.json
| @@ -181,6 +181,11 @@ | @@ -181,6 +181,11 @@ | ||
| 181 | "scope": "snsapi_userinfo" | 181 | "scope": "snsapi_userinfo" |
| 182 | } | 182 | } |
| 183 | }, | 183 | }, |
| 184 | + "WeChatBot": { | ||
| 185 | + "BotApiUrl": "http://wx.lvqianmeiye.com/api/Bot/send-text", | ||
| 186 | + "WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=496f1add-122b-43fc-9e38-0ca79c48b33f", | ||
| 187 | + "WebhookUrlTest": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=6f8686ec-5011-4c1d-bae9-d82a2a2f4d83" | ||
| 188 | + }, | ||
| 184 | "NCC_App": { | 189 | "NCC_App": { |
| 185 | "CodeAreasName": "SubDev,Food,Extend,test", | 190 | "CodeAreasName": "SubDev,Food,Extend,test", |
| 186 | //系统文件路径(末尾必须带斜杆) | 191 | //系统文件路径(末尾必须带斜杆) |
netcore/src/Modularity/Common/NCC.Common/Extension/Ext.cs
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDailyReport/BusinessUnitBillingStatisticsInput.cs
0 → 100644
| 1 | +using System; | ||
| 2 | + | ||
| 3 | +namespace NCC.Extend.Entitys.Dto.LqDailyReport | ||
| 4 | +{ | ||
| 5 | + /// <summary> | ||
| 6 | + /// 事业部开单统计查询输入 | ||
| 7 | + /// </summary> | ||
| 8 | + public class BusinessUnitBillingStatisticsInput | ||
| 9 | + { | ||
| 10 | + /// <summary> | ||
| 11 | + /// 统计日期(格式:yyyy-MM-dd) | ||
| 12 | + /// </summary> | ||
| 13 | + public string Date { get; set; } | ||
| 14 | + } | ||
| 15 | +} | ||
| 16 | + |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDailyReport/BusinessUnitBillingStatisticsOutput.cs
0 → 100644
| 1 | +using System; | ||
| 2 | +using System.Collections.Generic; | ||
| 3 | + | ||
| 4 | +namespace NCC.Extend.Entitys.Dto.LqDailyReport | ||
| 5 | +{ | ||
| 6 | + /// <summary> | ||
| 7 | + /// 事业部开单统计输出 | ||
| 8 | + /// </summary> | ||
| 9 | + public class BusinessUnitBillingStatisticsOutput | ||
| 10 | + { | ||
| 11 | + /// <summary> | ||
| 12 | + /// 事业部ID | ||
| 13 | + /// </summary> | ||
| 14 | + public string BusinessUnitId { get; set; } | ||
| 15 | + | ||
| 16 | + /// <summary> | ||
| 17 | + /// 事业部名称 | ||
| 18 | + /// </summary> | ||
| 19 | + public string BusinessUnitName { get; set; } | ||
| 20 | + | ||
| 21 | + /// <summary> | ||
| 22 | + /// 总业绩 | ||
| 23 | + /// </summary> | ||
| 24 | + public decimal TotalPerformance { get; set; } | ||
| 25 | + | ||
| 26 | + /// <summary> | ||
| 27 | + /// 总单量 | ||
| 28 | + /// </summary> | ||
| 29 | + public int TotalOrderCount { get; set; } | ||
| 30 | + | ||
| 31 | + /// <summary> | ||
| 32 | + /// 开单列表 | ||
| 33 | + /// </summary> | ||
| 34 | + public List<BillingOrderInfo> Orders { get; set; } | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + /// <summary> | ||
| 38 | + /// 开单信息 | ||
| 39 | + /// </summary> | ||
| 40 | + public class BillingOrderInfo | ||
| 41 | + { | ||
| 42 | + /// <summary> | ||
| 43 | + /// 开单ID | ||
| 44 | + /// </summary> | ||
| 45 | + public string OrderId { get; set; } | ||
| 46 | + | ||
| 47 | + /// <summary> | ||
| 48 | + /// 门店名称 | ||
| 49 | + /// </summary> | ||
| 50 | + public string StoreName { get; set; } | ||
| 51 | + | ||
| 52 | + /// <summary> | ||
| 53 | + /// 健康师姓名(多个用逗号分隔) | ||
| 54 | + /// </summary> | ||
| 55 | + public string HealthTeacherNames { get; set; } | ||
| 56 | + | ||
| 57 | + /// <summary> | ||
| 58 | + /// 金额 | ||
| 59 | + /// </summary> | ||
| 60 | + public decimal Amount { get; set; } | ||
| 61 | + | ||
| 62 | + /// <summary> | ||
| 63 | + /// 开单时间 | ||
| 64 | + /// </summary> | ||
| 65 | + public DateTime? OrderTime { get; set; } | ||
| 66 | + } | ||
| 67 | +} | ||
| 68 | + |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs
| 1 | using System; | 1 | using System; |
| 2 | +using System.Collections.Generic; | ||
| 3 | +using NCC.Extend.Entitys.Dto.LqHytkMx; | ||
| 4 | +using NCC.Extend.Entitys.Dto.LqHytkJksyj; | ||
| 5 | +using NCC.Extend.Entitys.Dto.LqHytkKjbsyj; | ||
| 2 | 6 | ||
| 3 | namespace NCC.Extend.Entitys.Dto.LqHytkHytk | 7 | namespace NCC.Extend.Entitys.Dto.LqHytkHytk |
| 4 | { | 8 | { |
| @@ -102,5 +106,19 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk | @@ -102,5 +106,19 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk | ||
| 102 | /// </summary> | 106 | /// </summary> |
| 103 | public string cancelRemark { get; set; } | 107 | public string cancelRemark { get; set; } |
| 104 | 108 | ||
| 109 | + /// <summary> | ||
| 110 | + /// 退卡品项明细列表 | ||
| 111 | + /// </summary> | ||
| 112 | + public List<LqHytkMxInfoOutput> lqHytkMxList { get; set; } | ||
| 113 | + | ||
| 114 | + /// <summary> | ||
| 115 | + /// 健康师业绩列表 | ||
| 116 | + /// </summary> | ||
| 117 | + public List<LqHytkJksyjInfoOutput> lqHytkJksyjList { get; set; } | ||
| 118 | + | ||
| 119 | + /// <summary> | ||
| 120 | + /// 科技部老师业绩列表 | ||
| 121 | + /// </summary> | ||
| 122 | + public List<LqHytkKjbsyjInfoOutput> lqHytkKjbsyjList { get; set; } | ||
| 105 | } | 123 | } |
| 106 | } | 124 | } |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListQueryInput.cs
| @@ -93,5 +93,14 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk | @@ -93,5 +93,14 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk | ||
| 93 | /// </summary> | 93 | /// </summary> |
| 94 | public int isEffective { get; set; } = 0; | 94 | public int isEffective { get; set; } = 0; |
| 95 | 95 | ||
| 96 | + /// <summary> | ||
| 97 | + /// 健康师ID(可选,传入后只返回该健康师参与的退卡记录) | ||
| 98 | + /// </summary> | ||
| 99 | + public string jksId { get; set; } | ||
| 100 | + | ||
| 101 | + /// <summary> | ||
| 102 | + /// 科技部老师ID(可选,传入后只返回该老师参与的退卡记录) | ||
| 103 | + /// </summary> | ||
| 104 | + public string kjblsId { get; set; } | ||
| 96 | } | 105 | } |
| 97 | } | 106 | } |
| 98 | \ No newline at end of file | 107 | \ No newline at end of file |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListByJksQueryInput.cs
0 → 100644
| 1 | +using NCC.Common.Filter; | ||
| 2 | + | ||
| 3 | +namespace NCC.Extend.Entitys.Dto.LqKdKdjlb | ||
| 4 | +{ | ||
| 5 | + /// <summary> | ||
| 6 | + /// 根据健康师ID查询开单列表输入 | ||
| 7 | + /// </summary> | ||
| 8 | + public class LqKdKdjlbListByJksQueryInput : PageInputBase | ||
| 9 | + { | ||
| 10 | + /// <summary> | ||
| 11 | + /// 健康师ID(必填) | ||
| 12 | + /// </summary> | ||
| 13 | + public string jksId { get; set; } | ||
| 14 | + | ||
| 15 | + /// <summary> | ||
| 16 | + /// 开始时间(可选,格式:yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss) | ||
| 17 | + /// </summary> | ||
| 18 | + public string startTime { get; set; } | ||
| 19 | + | ||
| 20 | + /// <summary> | ||
| 21 | + /// 结束时间(可选,格式:yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss) | ||
| 22 | + /// </summary> | ||
| 23 | + public string endTime { get; set; } | ||
| 24 | + | ||
| 25 | + /// <summary> | ||
| 26 | + /// 门店ID(可选) | ||
| 27 | + /// </summary> | ||
| 28 | + public string djmd { get; set; } | ||
| 29 | + | ||
| 30 | + /// <summary> | ||
| 31 | + /// 是否有效(可选,0=全部,1=有效,2=无效,默认1) | ||
| 32 | + /// </summary> | ||
| 33 | + public int isEffective { get; set; } = 1; | ||
| 34 | + } | ||
| 35 | +} | ||
| 36 | + |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListByKjbQueryInput.cs
0 → 100644
| 1 | +using NCC.Common.Filter; | ||
| 2 | + | ||
| 3 | +namespace NCC.Extend.Entitys.Dto.LqKdKdjlb | ||
| 4 | +{ | ||
| 5 | + /// <summary> | ||
| 6 | + /// 根据科技部老师ID查询开单列表输入 | ||
| 7 | + /// </summary> | ||
| 8 | + public class LqKdKdjlbListByKjbQueryInput : PageInputBase | ||
| 9 | + { | ||
| 10 | + /// <summary> | ||
| 11 | + /// 科技部老师ID(必填) | ||
| 12 | + /// </summary> | ||
| 13 | + public string kjblsId { get; set; } | ||
| 14 | + | ||
| 15 | + /// <summary> | ||
| 16 | + /// 开始时间(可选,格式:yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss) | ||
| 17 | + /// </summary> | ||
| 18 | + public string startTime { get; set; } | ||
| 19 | + | ||
| 20 | + /// <summary> | ||
| 21 | + /// 结束时间(可选,格式:yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss) | ||
| 22 | + /// </summary> | ||
| 23 | + public string endTime { get; set; } | ||
| 24 | + | ||
| 25 | + /// <summary> | ||
| 26 | + /// 门店ID(可选) | ||
| 27 | + /// </summary> | ||
| 28 | + public string djmd { get; set; } | ||
| 29 | + | ||
| 30 | + /// <summary> | ||
| 31 | + /// 是否有效(可选,0=全部,1=有效,2=无效,默认1) | ||
| 32 | + /// </summary> | ||
| 33 | + public int isEffective { get; set; } = 1; | ||
| 34 | + } | ||
| 35 | +} | ||
| 36 | + |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListOutput.cs
| @@ -170,5 +170,15 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb | @@ -170,5 +170,15 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb | ||
| 170 | /// 开单品项明细列表 | 170 | /// 开单品项明细列表 |
| 171 | /// </summary> | 171 | /// </summary> |
| 172 | public List<LqKdPxmxInfoOutput> ItemDetails { get; set; } | 172 | public List<LqKdPxmxInfoOutput> ItemDetails { get; set; } |
| 173 | + | ||
| 174 | + /// <summary> | ||
| 175 | + /// 健康师业绩列表 | ||
| 176 | + /// </summary> | ||
| 177 | + public List<LqKdJksyjInfoOutput> lqKdJksyjList { get; set; } | ||
| 178 | + | ||
| 179 | + /// <summary> | ||
| 180 | + /// 科技部老师业绩列表 | ||
| 181 | + /// </summary> | ||
| 182 | + public List<LqKdKjbsyjInfoOutput> lqKdKjbsyjList { get; set; } | ||
| 173 | } | 183 | } |
| 174 | } | 184 | } |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListQueryInput.cs
| @@ -139,5 +139,14 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb | @@ -139,5 +139,14 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb | ||
| 139 | /// </summary> | 139 | /// </summary> |
| 140 | public int isEffective { get; set; } = 0; | 140 | public int isEffective { get; set; } = 0; |
| 141 | 141 | ||
| 142 | + /// <summary> | ||
| 143 | + /// 健康师ID(可选,传入后只返回该健康师参与的开单记录) | ||
| 144 | + /// </summary> | ||
| 145 | + public string jksId { get; set; } | ||
| 146 | + | ||
| 147 | + /// <summary> | ||
| 148 | + /// 科技部老师ID(可选,传入后只返回该老师参与的开单记录) | ||
| 149 | + /// </summary> | ||
| 150 | + public string kjblsId { get; set; } | ||
| 142 | } | 151 | } |
| 143 | } | 152 | } |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPackageInfo/ActivityStatisticsByItemOutput.cs
0 → 100644
| 1 | +using System.Collections.Generic; | ||
| 2 | + | ||
| 3 | +namespace NCC.Extend.Entitys.Dto.LqPackageInfo | ||
| 4 | +{ | ||
| 5 | + /// <summary> | ||
| 6 | + /// 营销活动按品项统计输出 | ||
| 7 | + /// </summary> | ||
| 8 | + public class ActivityStatisticsByItemOutput | ||
| 9 | + { | ||
| 10 | + /// <summary> | ||
| 11 | + /// 营销活动ID | ||
| 12 | + /// </summary> | ||
| 13 | + public string ActivityId { get; set; } | ||
| 14 | + | ||
| 15 | + /// <summary> | ||
| 16 | + /// 营销活动名称 | ||
| 17 | + /// </summary> | ||
| 18 | + public string ActivityName { get; set; } | ||
| 19 | + | ||
| 20 | + /// <summary> | ||
| 21 | + /// 品项统计列表 | ||
| 22 | + /// </summary> | ||
| 23 | + public List<ItemStatisticsItem> ItemList { get; set; } | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + /// <summary> | ||
| 27 | + /// 品项统计项 | ||
| 28 | + /// </summary> | ||
| 29 | + public class ItemStatisticsItem | ||
| 30 | + { | ||
| 31 | + /// <summary> | ||
| 32 | + /// 品项ID | ||
| 33 | + /// </summary> | ||
| 34 | + public string ItemId { get; set; } | ||
| 35 | + | ||
| 36 | + /// <summary> | ||
| 37 | + /// 品项名称 | ||
| 38 | + /// </summary> | ||
| 39 | + public string ItemName { get; set; } | ||
| 40 | + | ||
| 41 | + /// <summary> | ||
| 42 | + /// 销售数量(项目次数总和) | ||
| 43 | + /// </summary> | ||
| 44 | + public decimal SalesQuantity { get; set; } | ||
| 45 | + | ||
| 46 | + /// <summary> | ||
| 47 | + /// 销售金额 | ||
| 48 | + /// </summary> | ||
| 49 | + public decimal SalesAmount { get; set; } | ||
| 50 | + | ||
| 51 | + /// <summary> | ||
| 52 | + /// 开单数量(包含该品项的开单数) | ||
| 53 | + /// </summary> | ||
| 54 | + public int BillingCount { get; set; } | ||
| 55 | + | ||
| 56 | + /// <summary> | ||
| 57 | + /// 销售次数(品项明细记录数) | ||
| 58 | + /// </summary> | ||
| 59 | + public int SalesCount { get; set; } | ||
| 60 | + } | ||
| 61 | +} | ||
| 62 | + |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPackageInfo/ActivityStatisticsByStoreItemOutput.cs
0 → 100644
| 1 | +using System.Collections.Generic; | ||
| 2 | + | ||
| 3 | +namespace NCC.Extend.Entitys.Dto.LqPackageInfo | ||
| 4 | +{ | ||
| 5 | + /// <summary> | ||
| 6 | + /// 营销活动按门店品项统计输出 | ||
| 7 | + /// </summary> | ||
| 8 | + public class ActivityStatisticsByStoreItemOutput | ||
| 9 | + { | ||
| 10 | + /// <summary> | ||
| 11 | + /// 营销活动ID | ||
| 12 | + /// </summary> | ||
| 13 | + public string ActivityId { get; set; } | ||
| 14 | + | ||
| 15 | + /// <summary> | ||
| 16 | + /// 营销活动名称 | ||
| 17 | + /// </summary> | ||
| 18 | + public string ActivityName { get; set; } | ||
| 19 | + | ||
| 20 | + /// <summary> | ||
| 21 | + /// 门店品项统计列表 | ||
| 22 | + /// </summary> | ||
| 23 | + public List<StoreItemStatisticsItem> StoreItemList { get; set; } | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + /// <summary> | ||
| 27 | + /// 门店品项统计项 | ||
| 28 | + /// </summary> | ||
| 29 | + public class StoreItemStatisticsItem | ||
| 30 | + { | ||
| 31 | + /// <summary> | ||
| 32 | + /// 门店ID | ||
| 33 | + /// </summary> | ||
| 34 | + public string StoreId { get; set; } | ||
| 35 | + | ||
| 36 | + /// <summary> | ||
| 37 | + /// 门店名称 | ||
| 38 | + /// </summary> | ||
| 39 | + public string StoreName { get; set; } | ||
| 40 | + | ||
| 41 | + /// <summary> | ||
| 42 | + /// 品项ID | ||
| 43 | + /// </summary> | ||
| 44 | + public string ItemId { get; set; } | ||
| 45 | + | ||
| 46 | + /// <summary> | ||
| 47 | + /// 品项名称 | ||
| 48 | + /// </summary> | ||
| 49 | + public string ItemName { get; set; } | ||
| 50 | + | ||
| 51 | + /// <summary> | ||
| 52 | + /// 销售数量(项目次数总和) | ||
| 53 | + /// </summary> | ||
| 54 | + public decimal SalesQuantity { get; set; } | ||
| 55 | + | ||
| 56 | + /// <summary> | ||
| 57 | + /// 销售金额 | ||
| 58 | + /// </summary> | ||
| 59 | + public decimal SalesAmount { get; set; } | ||
| 60 | + | ||
| 61 | + /// <summary> | ||
| 62 | + /// 开单数量(包含该品项的开单数) | ||
| 63 | + /// </summary> | ||
| 64 | + public int BillingCount { get; set; } | ||
| 65 | + | ||
| 66 | + /// <summary> | ||
| 67 | + /// 销售次数(品项明细记录数) | ||
| 68 | + /// </summary> | ||
| 69 | + public int SalesCount { get; set; } | ||
| 70 | + } | ||
| 71 | +} | ||
| 72 | + |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPackageInfo/ActivityStatisticsByStoreOutput.cs
0 → 100644
| 1 | +using System.Collections.Generic; | ||
| 2 | + | ||
| 3 | +namespace NCC.Extend.Entitys.Dto.LqPackageInfo | ||
| 4 | +{ | ||
| 5 | + /// <summary> | ||
| 6 | + /// 营销活动按门店统计输出 | ||
| 7 | + /// </summary> | ||
| 8 | + public class ActivityStatisticsByStoreOutput | ||
| 9 | + { | ||
| 10 | + /// <summary> | ||
| 11 | + /// 营销活动ID | ||
| 12 | + /// </summary> | ||
| 13 | + public string ActivityId { get; set; } | ||
| 14 | + | ||
| 15 | + /// <summary> | ||
| 16 | + /// 营销活动名称 | ||
| 17 | + /// </summary> | ||
| 18 | + public string ActivityName { get; set; } | ||
| 19 | + | ||
| 20 | + /// <summary> | ||
| 21 | + /// 门店统计列表 | ||
| 22 | + /// </summary> | ||
| 23 | + public List<StoreStatisticsItem> StoreList { get; set; } | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + /// <summary> | ||
| 27 | + /// 门店统计项 | ||
| 28 | + /// </summary> | ||
| 29 | + public class StoreStatisticsItem | ||
| 30 | + { | ||
| 31 | + /// <summary> | ||
| 32 | + /// 门店ID | ||
| 33 | + /// </summary> | ||
| 34 | + public string StoreId { get; set; } | ||
| 35 | + | ||
| 36 | + /// <summary> | ||
| 37 | + /// 门店名称 | ||
| 38 | + /// </summary> | ||
| 39 | + public string StoreName { get; set; } | ||
| 40 | + | ||
| 41 | + /// <summary> | ||
| 42 | + /// 开单数量 | ||
| 43 | + /// </summary> | ||
| 44 | + public int BillingCount { get; set; } | ||
| 45 | + | ||
| 46 | + /// <summary> | ||
| 47 | + /// 开单金额 | ||
| 48 | + /// </summary> | ||
| 49 | + public decimal BillingAmount { get; set; } | ||
| 50 | + | ||
| 51 | + /// <summary> | ||
| 52 | + /// 欠款金额 | ||
| 53 | + /// </summary> | ||
| 54 | + public decimal DebtAmount { get; set; } | ||
| 55 | + | ||
| 56 | + /// <summary> | ||
| 57 | + /// 人头数(去重客户数) | ||
| 58 | + /// </summary> | ||
| 59 | + public int CustomerCount { get; set; } | ||
| 60 | + | ||
| 61 | + /// <summary> | ||
| 62 | + /// 项目数(品项项目次数总和) | ||
| 63 | + /// </summary> | ||
| 64 | + public decimal ItemCount { get; set; } | ||
| 65 | + } | ||
| 66 | +} | ||
| 67 | + |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/TechTeacherSimpleStatisticsOutput.cs
| @@ -41,5 +41,10 @@ namespace NCC.Extend.Entitys.Dto.LqStatistics | @@ -41,5 +41,10 @@ namespace NCC.Extend.Entitys.Dto.LqStatistics | ||
| 41 | /// 耗卡品项次数 | 41 | /// 耗卡品项次数 |
| 42 | /// </summary> | 42 | /// </summary> |
| 43 | public int ConsumeItemCount { get; set; } | 43 | public int ConsumeItemCount { get; set; } |
| 44 | + | ||
| 45 | + /// <summary> | ||
| 46 | + /// 消耗手工费(耗卡手工费) | ||
| 47 | + /// </summary> | ||
| 48 | + public decimal ConsumeLaborCost { get; set; } | ||
| 44 | } | 49 | } |
| 45 | } | 50 | } |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/MemberRemainingItemsOutput.cs
| @@ -25,6 +25,7 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk | @@ -25,6 +25,7 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk | ||
| 25 | public string MemberName { get; set; } | 25 | public string MemberName { get; set; } |
| 26 | 26 | ||
| 27 | /// <summary> | 27 | /// <summary> |
| 28 | + /// <summary> | ||
| 28 | /// 剩余品项列表 | 29 | /// 剩余品项列表 |
| 29 | /// </summary> | 30 | /// </summary> |
| 30 | /// <remarks>按剩余数量降序排列的品项列表</remarks> | 31 | /// <remarks>按剩余数量降序排列的品项列表</remarks> |
| @@ -71,6 +72,12 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk | @@ -71,6 +72,12 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk | ||
| 71 | public string SourceType { get; set; } | 72 | public string SourceType { get; set; } |
| 72 | 73 | ||
| 73 | /// <summary> | 74 | /// <summary> |
| 75 | + /// 备注 | ||
| 76 | + /// </summary> | ||
| 77 | + /// <example>备注</example> | ||
| 78 | + public string Remark { get; set; } | ||
| 79 | + | ||
| 80 | + /// <summary> | ||
| 74 | /// 总购买数量 | 81 | /// 总购买数量 |
| 75 | /// </summary> | 82 | /// </summary> |
| 76 | /// <remarks>该品项的总购买次数</remarks> | 83 | /// <remarks>该品项的总购买次数</remarks> |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqYaoyjl/LqYaoyjlListQueryInput.cs
| @@ -17,47 +17,50 @@ namespace NCC.Extend.Entitys.Dto.LqYaoyjl | @@ -17,47 +17,50 @@ namespace NCC.Extend.Entitys.Dto.LqYaoyjl | ||
| 17 | /// | 17 | /// |
| 18 | /// </summary> | 18 | /// </summary> |
| 19 | public int dataType { get; set; } | 19 | public int dataType { get; set; } |
| 20 | - | ||
| 21 | - | ||
| 22 | /// <summary> | 20 | /// <summary> |
| 23 | /// 邀约编号 | 21 | /// 邀约编号 |
| 24 | /// </summary> | 22 | /// </summary> |
| 25 | public string id { get; set; } | 23 | public string id { get; set; } |
| 26 | - | 24 | + |
| 27 | /// <summary> | 25 | /// <summary> |
| 28 | /// 邀约人 | 26 | /// 邀约人 |
| 29 | /// </summary> | 27 | /// </summary> |
| 30 | public string yyr { get; set; } | 28 | public string yyr { get; set; } |
| 31 | - | 29 | + |
| 32 | /// <summary> | 30 | /// <summary> |
| 33 | /// 邀约时间 | 31 | /// 邀约时间 |
| 34 | /// </summary> | 32 | /// </summary> |
| 35 | public string yysj { get; set; } | 33 | public string yysj { get; set; } |
| 36 | - | 34 | + |
| 37 | /// <summary> | 35 | /// <summary> |
| 38 | /// 邀约客户 | 36 | /// 邀约客户 |
| 39 | /// </summary> | 37 | /// </summary> |
| 40 | public string yykh { get; set; } | 38 | public string yykh { get; set; } |
| 41 | - | 39 | + |
| 42 | /// <summary> | 40 | /// <summary> |
| 43 | /// 邀约客户姓名 | 41 | /// 邀约客户姓名 |
| 44 | /// </summary> | 42 | /// </summary> |
| 45 | public string yykhxm { get; set; } | 43 | public string yykhxm { get; set; } |
| 46 | - | 44 | + |
| 47 | /// <summary> | 45 | /// <summary> |
| 48 | /// 电话是否有效 | 46 | /// 电话是否有效 |
| 49 | /// </summary> | 47 | /// </summary> |
| 50 | public string dhsfyx { get; set; } | 48 | public string dhsfyx { get; set; } |
| 51 | - | 49 | + |
| 52 | /// <summary> | 50 | /// <summary> |
| 53 | /// 联系时间 | 51 | /// 联系时间 |
| 54 | /// </summary> | 52 | /// </summary> |
| 55 | public string lxsj { get; set; } | 53 | public string lxsj { get; set; } |
| 56 | - | 54 | + |
| 57 | /// <summary> | 55 | /// <summary> |
| 58 | /// 联系记录 | 56 | /// 联系记录 |
| 59 | /// </summary> | 57 | /// </summary> |
| 60 | public string lxjl { get; set; } | 58 | public string lxjl { get; set; } |
| 61 | - | 59 | + |
| 60 | + /// <summary> | ||
| 61 | + /// 门店ID | ||
| 62 | + /// </summary> | ||
| 63 | + public string storeId { get; set; } | ||
| 64 | + | ||
| 62 | } | 65 | } |
| 63 | } | 66 | } |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/Dto/LqMdGeneralManagerLifeline/LqMdGeneralManagerLifelineCrInput.cs
| @@ -28,6 +28,12 @@ namespace NCC.Extend.Entitys.Dto.LqMdGeneralManagerLifeline | @@ -28,6 +28,12 @@ namespace NCC.Extend.Entitys.Dto.LqMdGeneralManagerLifeline | ||
| 28 | public string generalManagerId { get; set; } | 28 | public string generalManagerId { get; set; } |
| 29 | 29 | ||
| 30 | /// <summary> | 30 | /// <summary> |
| 31 | + /// 经理类型(0=经理,1=总经理) | ||
| 32 | + /// </summary> | ||
| 33 | + [Required(ErrorMessage = "经理类型不能为空")] | ||
| 34 | + public int managerType { get; set; } = 1; | ||
| 35 | + | ||
| 36 | + /// <summary> | ||
| 31 | /// 生命线1 | 37 | /// 生命线1 |
| 32 | /// </summary> | 38 | /// </summary> |
| 33 | [Required(ErrorMessage = "生命线1不能为空")] | 39 | [Required(ErrorMessage = "生命线1不能为空")] |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/Dto/LqMdGeneralManagerLifeline/LqMdGeneralManagerLifelineInfoOutput.cs
| @@ -28,6 +28,11 @@ namespace NCC.Extend.Entitys.Dto.LqMdGeneralManagerLifeline | @@ -28,6 +28,11 @@ namespace NCC.Extend.Entitys.Dto.LqMdGeneralManagerLifeline | ||
| 28 | public string generalManagerId { get; set; } | 28 | public string generalManagerId { get; set; } |
| 29 | 29 | ||
| 30 | /// <summary> | 30 | /// <summary> |
| 31 | + /// 经理类型(0=经理,1=总经理) | ||
| 32 | + /// </summary> | ||
| 33 | + public int managerType { get; set; } | ||
| 34 | + | ||
| 35 | + /// <summary> | ||
| 31 | /// 生命线1 | 36 | /// 生命线1 |
| 32 | /// </summary> | 37 | /// </summary> |
| 33 | public decimal lifeline1 { get; set; } | 38 | public decimal lifeline1 { get; set; } |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/Dto/LqMdGeneralManagerLifeline/LqMdGeneralManagerLifelineListOutput.cs
| @@ -28,6 +28,16 @@ namespace NCC.Extend.Entitys.Dto.LqMdGeneralManagerLifeline | @@ -28,6 +28,16 @@ namespace NCC.Extend.Entitys.Dto.LqMdGeneralManagerLifeline | ||
| 28 | public string generalManagerId { get; set; } | 28 | public string generalManagerId { get; set; } |
| 29 | 29 | ||
| 30 | /// <summary> | 30 | /// <summary> |
| 31 | + /// 经理类型(0=经理,1=总经理) | ||
| 32 | + /// </summary> | ||
| 33 | + public int managerType { get; set; } | ||
| 34 | + | ||
| 35 | + /// <summary> | ||
| 36 | + /// 经理类型(0=经理,1=总经理) | ||
| 37 | + /// </summary> | ||
| 38 | + public string managerTypeName { get; set; } | ||
| 39 | + | ||
| 40 | + /// <summary> | ||
| 31 | /// 生命线1 | 41 | /// 生命线1 |
| 32 | /// </summary> | 42 | /// </summary> |
| 33 | public decimal lifeline1 { get; set; } | 43 | public decimal lifeline1 { get; set; } |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/Dto/LqMdGeneralManagerLifeline/LqMdGeneralManagerLifelineUpInput.cs
| @@ -28,6 +28,12 @@ namespace NCC.Extend.Entitys.Dto.LqMdGeneralManagerLifeline | @@ -28,6 +28,12 @@ namespace NCC.Extend.Entitys.Dto.LqMdGeneralManagerLifeline | ||
| 28 | public string generalManagerId { get; set; } | 28 | public string generalManagerId { get; set; } |
| 29 | 29 | ||
| 30 | /// <summary> | 30 | /// <summary> |
| 31 | + /// 经理类型(0=经理,1=总经理) | ||
| 32 | + /// </summary> | ||
| 33 | + [Required(ErrorMessage = "经理类型不能为空")] | ||
| 34 | + public int managerType { get; set; } = 1; | ||
| 35 | + | ||
| 36 | + /// <summary> | ||
| 31 | /// 生命线1 | 37 | /// 生命线1 |
| 32 | /// </summary> | 38 | /// </summary> |
| 33 | [Required(ErrorMessage = "生命线1不能为空")] | 39 | [Required(ErrorMessage = "生命线1不能为空")] |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_md_general_manager_lifeline/LqMdGeneralManagerLifelineEntity.cs
| @@ -36,6 +36,12 @@ namespace NCC.Extend.Entitys.lq_md_general_manager_lifeline | @@ -36,6 +36,12 @@ namespace NCC.Extend.Entitys.lq_md_general_manager_lifeline | ||
| 36 | public string GeneralManagerId { get; set; } | 36 | public string GeneralManagerId { get; set; } |
| 37 | 37 | ||
| 38 | /// <summary> | 38 | /// <summary> |
| 39 | + /// 经理类型(0=经理,1=总经理) | ||
| 40 | + /// </summary> | ||
| 41 | + [SugarColumn(ColumnName = "F_ManagerType")] | ||
| 42 | + public int ManagerType { get; set; } = 1; | ||
| 43 | + | ||
| 44 | + /// <summary> | ||
| 39 | /// 生命线1 | 45 | /// 生命线1 |
| 40 | /// </summary> | 46 | /// </summary> |
| 41 | [SugarColumn(ColumnName = "F_Lifeline1")] | 47 | [SugarColumn(ColumnName = "F_Lifeline1")] |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Enum/ManagerTypeEnum.cs
0 → 100644
| 1 | +using System.ComponentModel; | ||
| 2 | + | ||
| 3 | +namespace NCC.Extend.Entitys.Enum | ||
| 4 | +{ | ||
| 5 | + /// <summary> | ||
| 6 | + /// 经理类型枚举 | ||
| 7 | + /// </summary> | ||
| 8 | + public enum ManagerTypeEnum | ||
| 9 | + { | ||
| 10 | + /// <summary> | ||
| 11 | + /// 经理 | ||
| 12 | + /// </summary> | ||
| 13 | + [Description("经理")] | ||
| 14 | + 经理 = 0, | ||
| 15 | + | ||
| 16 | + /// <summary> | ||
| 17 | + /// 总经理 | ||
| 18 | + /// </summary> | ||
| 19 | + [Description("总经理")] | ||
| 20 | + 总经理 = 1, | ||
| 21 | + } | ||
| 22 | +} | ||
| 23 | + |
netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs
| @@ -12,6 +12,7 @@ using SqlSugar; | @@ -12,6 +12,7 @@ using SqlSugar; | ||
| 12 | using System; | 12 | using System; |
| 13 | using System.Collections.Generic; | 13 | using System.Collections.Generic; |
| 14 | using System.Linq; | 14 | using System.Linq; |
| 15 | +using System.Text; | ||
| 15 | using System.Threading.Tasks; | 16 | using System.Threading.Tasks; |
| 16 | using Yitter.IdGenerator; | 17 | using Yitter.IdGenerator; |
| 17 | using NCC.Common.Helper; | 18 | using NCC.Common.Helper; |
| @@ -22,6 +23,10 @@ using NCC.DataEncryption; | @@ -22,6 +23,10 @@ using NCC.DataEncryption; | ||
| 22 | using NCC.ClayObject; | 23 | using NCC.ClayObject; |
| 23 | using NCC.Extend.Entitys.Dto.LqDailyReport; | 24 | using NCC.Extend.Entitys.Dto.LqDailyReport; |
| 24 | using NCC.Extend.Entitys.lq_kd_kdjlb; | 25 | using NCC.Extend.Entitys.lq_kd_kdjlb; |
| 26 | +using NCC.Extend.Entitys.lq_kd_jksyj; | ||
| 27 | +using NCC.Extend.Entitys.lq_mdxx; | ||
| 28 | +using NCC.System.Entitys.Permission; | ||
| 29 | +using NCC.Extend.Entitys.Enum; | ||
| 25 | using Microsoft.AspNetCore.Authorization; | 30 | using Microsoft.AspNetCore.Authorization; |
| 26 | 31 | ||
| 27 | namespace NCC.Extend | 32 | namespace NCC.Extend |
| @@ -752,7 +757,7 @@ namespace NCC.Extend | @@ -752,7 +757,7 @@ namespace NCC.Extend | ||
| 752 | managerFilter = $"AND target.F_GeneralManagerId = '{input.ManagerId}'"; | 757 | managerFilter = $"AND target.F_GeneralManagerId = '{input.ManagerId}'"; |
| 753 | } | 758 | } |
| 754 | 759 | ||
| 755 | - // SQL查询:获取经理汇总业绩 | 760 | + // SQL查询:获取经理汇总业绩(基于lq_md_general_manager_lifeline表中的经理和门店关系) |
| 756 | var sql = $@" | 761 | var sql = $@" |
| 757 | SELECT | 762 | SELECT |
| 758 | target.F_GeneralManagerId as ManagerId, | 763 | target.F_GeneralManagerId as ManagerId, |
| @@ -761,7 +766,7 @@ namespace NCC.Extend | @@ -761,7 +766,7 @@ namespace NCC.Extend | ||
| 761 | COALESCE(SUM(target.F_Lifeline2), 0) as TotalTarget2, | 766 | COALESCE(SUM(target.F_Lifeline2), 0) as TotalTarget2, |
| 762 | COALESCE(SUM(target.F_Lifeline3), 0) as TotalTarget3, | 767 | COALESCE(SUM(target.F_Lifeline3), 0) as TotalTarget3, |
| 763 | COUNT(DISTINCT target.F_StoreId) as StoreCount, | 768 | COUNT(DISTINCT target.F_StoreId) as StoreCount, |
| 764 | - -- 总完成业绩 | 769 | + -- 总完成业绩(基于lq_md_general_manager_lifeline表中的门店关系计算) |
| 765 | SUM(COALESCE(( | 770 | SUM(COALESCE(( |
| 766 | SELECT SUM(billing.sfyj) | 771 | SELECT SUM(billing.sfyj) |
| 767 | FROM lq_kd_kdjlb billing | 772 | FROM lq_kd_kdjlb billing |
| @@ -957,7 +962,267 @@ namespace NCC.Extend | @@ -957,7 +962,267 @@ namespace NCC.Extend | ||
| 957 | 962 | ||
| 958 | return outputList; | 963 | return outputList; |
| 959 | } | 964 | } |
| 965 | + | ||
| 966 | + /// <summary> | ||
| 967 | + /// 获取指定日期的事业部开单统计数据 | ||
| 968 | + /// </summary> | ||
| 969 | + /// <remarks> | ||
| 970 | + /// 统计指定日期的事业部开单数据,包括: | ||
| 971 | + /// - 只统计有效的开单(F_IsEffective = 1) | ||
| 972 | + /// - 只统计有金额的开单(sfyj > 0) | ||
| 973 | + /// - 只统计有效的健康师业绩(F_IsEffective = 1) | ||
| 974 | + /// - 如果有多个健康师就合并显示 | ||
| 975 | + /// - 按照事业部名称排序 | ||
| 976 | + /// - 每个事业部内的开单按照时间先后顺序进行排序 | ||
| 977 | + /// | ||
| 978 | + /// 示例请求: | ||
| 979 | + /// ```json | ||
| 980 | + /// { | ||
| 981 | + /// "date": "2025-11-10" | ||
| 982 | + /// } | ||
| 983 | + /// ``` | ||
| 984 | + /// </remarks> | ||
| 985 | + /// <param name="input">查询参数</param> | ||
| 986 | + /// <returns>事业部开单统计数据列表</returns> | ||
| 987 | + /// <response code="200">成功返回统计数据</response> | ||
| 988 | + /// <response code="400">日期格式错误或参数无效</response> | ||
| 989 | + /// <response code="500">服务器内部错误</response> | ||
| 990 | + [HttpPost("get-business-unit-billing-statistics")] | ||
| 991 | + [AllowAnonymous] | ||
| 992 | + public async Task<List<BusinessUnitBillingStatisticsOutput>> GetBusinessUnitBillingStatistics(BusinessUnitBillingStatisticsInput input) | ||
| 993 | + { | ||
| 994 | + try | ||
| 995 | + { | ||
| 996 | + // 1. 验证日期参数 | ||
| 997 | + if (string.IsNullOrEmpty(input.Date)) | ||
| 998 | + { | ||
| 999 | + throw NCCException.Oh("日期不能为空"); | ||
| 1000 | + } | ||
| 1001 | + | ||
| 1002 | + if (!DateTime.TryParse(input.Date, out var targetDate)) | ||
| 1003 | + { | ||
| 1004 | + throw NCCException.Oh("日期格式错误,请使用 yyyy-MM-dd 格式"); | ||
| 1005 | + } | ||
| 1006 | + | ||
| 1007 | + // 2. 查询指定日期的有效开单记录(有金额的) | ||
| 1008 | + var billingQuery = _db.Queryable<LqKdKdjlbEntity, LqMdxxEntity, OrganizeEntity>( | ||
| 1009 | + (billing, store, org) => billing.Djmd == store.Id && store.Syb == org.Id) | ||
| 1010 | + .Where((billing, store, org) => billing.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 1011 | + .Where((billing, store, org) => billing.Sfyj > 0) // 只统计有金额的开单 | ||
| 1012 | + .Where((billing, store, org) => billing.Kdrq.HasValue && billing.Kdrq.Value.Date == targetDate.Date) | ||
| 1013 | + .Where((billing, store, org) => org.Category == "department") | ||
| 1014 | + .Where((billing, store, org) => org.FullName.Contains("事业")) | ||
| 1015 | + .Select((billing, store, org) => new | ||
| 1016 | + { | ||
| 1017 | + OrderId = billing.Id, | ||
| 1018 | + StoreName = store.Dm, | ||
| 1019 | + BusinessUnitId = org.Id, | ||
| 1020 | + BusinessUnitName = org.FullName, | ||
| 1021 | + Amount = billing.Sfyj, | ||
| 1022 | + OrderTime = billing.Kdrq, | ||
| 1023 | + }) | ||
| 1024 | + .ToListAsync(); | ||
| 1025 | + | ||
| 1026 | + var billingRecords = await billingQuery; | ||
| 1027 | + | ||
| 1028 | + if (!billingRecords.Any()) | ||
| 1029 | + { | ||
| 1030 | + return new List<BusinessUnitBillingStatisticsOutput>(); | ||
| 1031 | + } | ||
| 1032 | + | ||
| 1033 | + // 3. 批量查询健康师信息 | ||
| 1034 | + var orderIds = billingRecords.Select(x => x.OrderId).Distinct().ToList(); | ||
| 1035 | + var healthTeachers = await _db.Queryable<LqKdJksyjEntity>() | ||
| 1036 | + .Where(x => orderIds.Contains(x.Glkdbh) && x.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 1037 | + .Select(x => new | ||
| 1038 | + { | ||
| 1039 | + OrderId = x.Glkdbh, | ||
| 1040 | + TeacherName = x.Jksxm, | ||
| 1041 | + }) | ||
| 1042 | + .ToListAsync(); | ||
| 1043 | + | ||
| 1044 | + // 4. 按开单ID分组健康师 | ||
| 1045 | + var healthTeacherDict = healthTeachers | ||
| 1046 | + .GroupBy(x => x.OrderId) | ||
| 1047 | + .ToDictionary( | ||
| 1048 | + g => g.Key, | ||
| 1049 | + g => string.Join("、", g.Select(x => x.TeacherName).Distinct()) | ||
| 1050 | + ); | ||
| 1051 | + | ||
| 1052 | + // 5. 按事业部分组统计 | ||
| 1053 | + var result = billingRecords | ||
| 1054 | + .GroupBy(x => new { x.BusinessUnitId, x.BusinessUnitName }) | ||
| 1055 | + .Select(g => new BusinessUnitBillingStatisticsOutput | ||
| 1056 | + { | ||
| 1057 | + BusinessUnitId = g.Key.BusinessUnitId, | ||
| 1058 | + BusinessUnitName = g.Key.BusinessUnitName, | ||
| 1059 | + TotalPerformance = g.Sum(x => x.Amount), | ||
| 1060 | + TotalOrderCount = g.Count(), | ||
| 1061 | + Orders = g.OrderBy(x => x.OrderTime ?? DateTime.MinValue) | ||
| 1062 | + .Select(x => new BillingOrderInfo | ||
| 1063 | + { | ||
| 1064 | + OrderId = x.OrderId, | ||
| 1065 | + StoreName = x.StoreName, | ||
| 1066 | + HealthTeacherNames = healthTeacherDict.GetValueOrDefault(x.OrderId, ""), | ||
| 1067 | + Amount = x.Amount, | ||
| 1068 | + OrderTime = x.OrderTime, | ||
| 1069 | + }) | ||
| 1070 | + .ToList(), | ||
| 1071 | + }) | ||
| 1072 | + .OrderBy(x => x.BusinessUnitName) // 按事业部名称排序 | ||
| 1073 | + .ToList(); | ||
| 1074 | + | ||
| 1075 | + return result; | ||
| 1076 | + } | ||
| 1077 | + catch (Exception ex) | ||
| 1078 | + { | ||
| 1079 | + throw NCCException.Oh($"获取事业部开单统计数据失败: {ex.Message}", ex); | ||
| 1080 | + } | ||
| 1081 | + } | ||
| 1082 | + | ||
| 1083 | + /// <summary> | ||
| 1084 | + /// 将事业部开单统计数据格式化为中文文本 | ||
| 1085 | + /// </summary> | ||
| 1086 | + /// <remarks> | ||
| 1087 | + /// 将结构化的统计数据格式化为中文文本格式,用于显示或发送消息。 | ||
| 1088 | + /// | ||
| 1089 | + /// 示例请求: | ||
| 1090 | + /// ```json | ||
| 1091 | + /// { | ||
| 1092 | + /// "date": "2025-11-10" | ||
| 1093 | + /// } | ||
| 1094 | + /// ``` | ||
| 1095 | + /// | ||
| 1096 | + /// 返回格式: | ||
| 1097 | + /// ``` | ||
| 1098 | + /// 11月8日 | ||
| 1099 | + /// | ||
| 1100 | + /// 今日总业绩:32317 | ||
| 1101 | + /// | ||
| 1102 | + /// 今日总单量:18 | ||
| 1103 | + /// | ||
| 1104 | + /// 绿纤人用结果捍卫尊严 | ||
| 1105 | + /// | ||
| 1106 | + /// 业绩捷报 | ||
| 1107 | + /// | ||
| 1108 | + /// ▃▃▃▃▃▃▃▃▃▃ | ||
| 1109 | + /// | ||
| 1110 | + /// 事业1部总业绩:4722 | ||
| 1111 | + /// | ||
| 1112 | + /// 事业1部总单量:4 | ||
| 1113 | + /// | ||
| 1114 | + /// 第1单:红光店马丽亚1000 | ||
| 1115 | + /// | ||
| 1116 | + /// 第2单:468店陈小琴、苟小春500 | ||
| 1117 | + /// | ||
| 1118 | + /// ... | ||
| 1119 | + /// ``` | ||
| 1120 | + /// </remarks> | ||
| 1121 | + /// <param name="input">查询参数</param> | ||
| 1122 | + /// <returns>格式化的中文文本</returns> | ||
| 1123 | + /// <response code="200">成功返回格式化文本</response> | ||
| 1124 | + /// <response code="400">日期格式错误或参数无效</response> | ||
| 1125 | + /// <response code="500">服务器内部错误</response> | ||
| 1126 | + [HttpPost("get-business-unit-billing-statistics-text")] | ||
| 1127 | + [AllowAnonymous] | ||
| 1128 | + public async Task<string> GetBusinessUnitBillingStatisticsText(BusinessUnitBillingStatisticsInput input) | ||
| 1129 | + { | ||
| 1130 | + try | ||
| 1131 | + { | ||
| 1132 | + // 1. 获取统计数据 | ||
| 1133 | + var statistics = await GetBusinessUnitBillingStatistics(input); | ||
| 1134 | + | ||
| 1135 | + if (!statistics.Any()) | ||
| 1136 | + { | ||
| 1137 | + return $"日期 {input.Date} 暂无开单数据"; | ||
| 1138 | + } | ||
| 1139 | + | ||
| 1140 | + // 2. 解析日期 | ||
| 1141 | + if (!DateTime.TryParse(input.Date, out var targetDate)) | ||
| 1142 | + { | ||
| 1143 | + throw NCCException.Oh("日期格式错误,请使用 yyyy-MM-dd 格式"); | ||
| 1144 | + } | ||
| 1145 | + | ||
| 1146 | + // 3. 计算总业绩和总单量 | ||
| 1147 | + var totalPerformance = statistics.Sum(x => x.TotalPerformance); | ||
| 1148 | + var totalOrderCount = statistics.Sum(x => x.TotalOrderCount); | ||
| 1149 | + | ||
| 1150 | + // 4. 格式化为中文文本 | ||
| 1151 | + var textBuilder = new StringBuilder(); | ||
| 1152 | + | ||
| 1153 | + // 日期(格式:11月8日) | ||
| 1154 | + textBuilder.AppendLine($"{targetDate.Month}月{targetDate.Day}日"); | ||
| 1155 | + textBuilder.AppendLine(); | ||
| 1156 | + | ||
| 1157 | + // 今日总业绩和总单量 | ||
| 1158 | + textBuilder.AppendLine($"今日总业绩:{totalPerformance:F0}"); | ||
| 1159 | + textBuilder.AppendLine(); | ||
| 1160 | + textBuilder.AppendLine($"今日总单量:{totalOrderCount}"); | ||
| 1161 | + textBuilder.AppendLine(); | ||
| 1162 | + | ||
| 1163 | + // 标语 | ||
| 1164 | + textBuilder.AppendLine("绿纤人用结果捍卫尊严 "); | ||
| 1165 | + textBuilder.AppendLine(); | ||
| 1166 | + textBuilder.AppendLine("业绩捷报 "); | ||
| 1167 | + textBuilder.AppendLine(); | ||
| 1168 | + | ||
| 1169 | + // 每个事业部的数据 | ||
| 1170 | + foreach (var unit in statistics) | ||
| 1171 | + { | ||
| 1172 | + // 分隔线 | ||
| 1173 | + textBuilder.AppendLine("▃▃▃▃▃▃▃▃▃▃"); | ||
| 1174 | + textBuilder.AppendLine(); | ||
| 1175 | + | ||
| 1176 | + // 事业部业绩和单量 | ||
| 1177 | + textBuilder.AppendLine($"{unit.BusinessUnitName}总业绩:{unit.TotalPerformance:F0}"); | ||
| 1178 | + textBuilder.AppendLine(); | ||
| 1179 | + textBuilder.AppendLine($"{unit.BusinessUnitName}总单量:{unit.TotalOrderCount}"); | ||
| 1180 | + textBuilder.AppendLine(); | ||
| 1181 | + | ||
| 1182 | + // 按门店分组订单 | ||
| 1183 | + var ordersByStore = unit.Orders | ||
| 1184 | + .GroupBy(x => x.StoreName) | ||
| 1185 | + .OrderBy(g => g.Key) // 按门店名称排序 | ||
| 1186 | + .ToList(); | ||
| 1187 | + | ||
| 1188 | + // 遍历每个门店的订单 | ||
| 1189 | + foreach (var storeGroup in ordersByStore) | ||
| 1190 | + { | ||
| 1191 | + // 每个门店的订单按时间排序 | ||
| 1192 | + var storeOrders = storeGroup | ||
| 1193 | + .OrderBy(x => x.OrderTime ?? DateTime.MinValue) | ||
| 1194 | + .ToList(); | ||
| 1195 | + | ||
| 1196 | + // 每个门店的订单单独编号(从第1单开始) | ||
| 1197 | + int orderIndex = 1; | ||
| 1198 | + foreach (var order in storeOrders) | ||
| 1199 | + { | ||
| 1200 | + var teacherNames = string.IsNullOrEmpty(order.HealthTeacherNames) ? "" : order.HealthTeacherNames; | ||
| 1201 | + // 格式:第1单:门店名健康师名金额(没有"、",没有"金额"字样,直接数字) | ||
| 1202 | + if (string.IsNullOrEmpty(teacherNames)) | ||
| 1203 | + { | ||
| 1204 | + textBuilder.AppendLine($"第{orderIndex}单:{order.StoreName}{order.Amount:F0}"); | ||
| 1205 | + } | ||
| 1206 | + else | ||
| 1207 | + { | ||
| 1208 | + textBuilder.AppendLine($"第{orderIndex}单:{order.StoreName}{teacherNames}{order.Amount:F0}"); | ||
| 1209 | + } | ||
| 1210 | + textBuilder.AppendLine(); | ||
| 1211 | + orderIndex++; | ||
| 1212 | + } | ||
| 1213 | + } | ||
| 1214 | + } | ||
| 1215 | + | ||
| 1216 | + return textBuilder.ToString().TrimEnd(); | ||
| 1217 | + } | ||
| 1218 | + catch (Exception ex) | ||
| 1219 | + { | ||
| 1220 | + throw NCCException.Oh($"获取事业部开单统计文本失败: {ex.Message}", ex); | ||
| 1221 | + } | ||
| 1222 | + } | ||
| 960 | #endregion | 1223 | #endregion |
| 1224 | + | ||
| 1225 | + | ||
| 961 | } | 1226 | } |
| 962 | } | 1227 | } |
| 963 | 1228 |
netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs
| @@ -70,8 +70,35 @@ namespace NCC.Extend.LqHytkHytk | @@ -70,8 +70,35 @@ namespace NCC.Extend.LqHytkHytk | ||
| 70 | /// <summary> | 70 | /// <summary> |
| 71 | /// 获取退卡信息列表 | 71 | /// 获取退卡信息列表 |
| 72 | /// </summary> | 72 | /// </summary> |
| 73 | + /// <remarks> | ||
| 74 | + /// 获取退卡记录列表,支持根据健康师ID或科技部老师ID筛选,返回品项明细、健康师业绩和科技部老师业绩 | ||
| 75 | + /// | ||
| 76 | + /// 示例请求: | ||
| 77 | + /// ```json | ||
| 78 | + /// GET /api/Extend/LqHytkHytk?jksId=健康师ID&kjblsId=科技部老师ID&currentPage=1&pageSize=10 | ||
| 79 | + /// ``` | ||
| 80 | + /// | ||
| 81 | + /// 参数说明: | ||
| 82 | + /// - jksId: 健康师ID(可选,传入后只返回该健康师参与的退卡记录) | ||
| 83 | + /// - kjblsId: 科技部老师ID(可选,传入后只返回该老师参与的退卡记录) | ||
| 84 | + /// - id: 退卡编号(可选) | ||
| 85 | + /// - md: 门店ID(可选) | ||
| 86 | + /// - hy: 会员ID(可选) | ||
| 87 | + /// - tksj: 退卡时间(可选,格式:yyyy-MM-dd,yyyy-MM-dd) | ||
| 88 | + /// - currentPage: 当前页码(必填) | ||
| 89 | + /// - pageSize: 每页数量(必填) | ||
| 90 | + /// | ||
| 91 | + /// 返回数据说明: | ||
| 92 | + /// - 退卡基本信息:id、门店信息、会员信息、退卡金额、退卡时间等 | ||
| 93 | + /// - lqHytkMxList: 退卡品项明细列表,每个明细包含品项信息、退款金额、项目次数等 | ||
| 94 | + /// - lqHytkJksyjList: 健康师业绩列表,每个业绩包含健康师信息、业绩金额、手工费、退卡品项次数等 | ||
| 95 | + /// - lqHytkKjbsyjList: 科技部老师业绩列表,每个业绩包含科技部老师信息、业绩金额、手工费、退卡品项次数等 | ||
| 96 | + /// </remarks> | ||
| 73 | /// <param name="input">查询参数</param> | 97 | /// <param name="input">查询参数</param> |
| 74 | - /// <returns></returns> | 98 | + /// <returns>分页的退卡记录列表,包含退卡基本信息、品项明细、健康师业绩、科技部老师业绩</returns> |
| 99 | + /// <response code="200">成功返回退卡列表</response> | ||
| 100 | + /// <response code="400">参数错误</response> | ||
| 101 | + /// <response code="500">服务器内部错误</response> | ||
| 75 | [HttpGet("")] | 102 | [HttpGet("")] |
| 76 | public async Task<dynamic> GetList([FromQuery] LqHytkHytkListQueryInput input) | 103 | public async Task<dynamic> GetList([FromQuery] LqHytkHytkListQueryInput input) |
| 77 | { | 104 | { |
| @@ -79,7 +106,48 @@ namespace NCC.Extend.LqHytkHytk | @@ -79,7 +106,48 @@ namespace NCC.Extend.LqHytkHytk | ||
| 79 | List<string> queryTksj = input.tksj != null ? input.tksj.Split(',').ToObeject<List<string>>() : null; | 106 | List<string> queryTksj = input.tksj != null ? input.tksj.Split(',').ToObeject<List<string>>() : null; |
| 80 | DateTime? startTksj = queryTksj != null ? Ext.GetDateTime(queryTksj.First()) : null; | 107 | DateTime? startTksj = queryTksj != null ? Ext.GetDateTime(queryTksj.First()) : null; |
| 81 | DateTime? endTksj = queryTksj != null ? Ext.GetDateTime(queryTksj.Last()) : null; | 108 | DateTime? endTksj = queryTksj != null ? Ext.GetDateTime(queryTksj.Last()) : null; |
| 82 | - var data = await _db.Queryable<LqHytkHytkEntity>() | 109 | + |
| 110 | + // 根据是否传入健康师ID或科技部老师ID,动态构建查询 | ||
| 111 | + ISugarQueryable<LqHytkHytkEntity> baseQuery = null; | ||
| 112 | + | ||
| 113 | + if (!string.IsNullOrEmpty(input.jksId) && !string.IsNullOrEmpty(input.kjblsId)) | ||
| 114 | + { | ||
| 115 | + // 同时传入健康师ID和科技部老师ID,需要同时关联两个业绩表(不过滤有效性) | ||
| 116 | + baseQuery = _db.Queryable<LqHytkJksyjEntity, LqHytkKjbsyjEntity, LqHytkHytkEntity>( | ||
| 117 | + (jksyj, kjbsyj, hytk) => jksyj.Gltkbh == hytk.Id && kjbsyj.Gltkbh == hytk.Id) | ||
| 118 | + .Where((jksyj, kjbsyj, hytk) => jksyj.Jkszh == input.jksId) | ||
| 119 | + .Where((jksyj, kjbsyj, hytk) => kjbsyj.Kjblszh == input.kjblsId) | ||
| 120 | + .Select((jksyj, kjbsyj, hytk) => hytk) | ||
| 121 | + .Distinct() | ||
| 122 | + .MergeTable(); | ||
| 123 | + } | ||
| 124 | + else if (!string.IsNullOrEmpty(input.jksId)) | ||
| 125 | + { | ||
| 126 | + // 只传入健康师ID,关联健康师业绩表(不过滤有效性) | ||
| 127 | + baseQuery = _db.Queryable<LqHytkJksyjEntity, LqHytkHytkEntity>( | ||
| 128 | + (jksyj, hytk) => jksyj.Gltkbh == hytk.Id) | ||
| 129 | + .Where((jksyj, hytk) => jksyj.Jkszh == input.jksId) | ||
| 130 | + .Select((jksyj, hytk) => hytk) | ||
| 131 | + .Distinct() | ||
| 132 | + .MergeTable(); | ||
| 133 | + } | ||
| 134 | + else if (!string.IsNullOrEmpty(input.kjblsId)) | ||
| 135 | + { | ||
| 136 | + // 只传入科技部老师ID,关联科技部老师业绩表(不过滤有效性) | ||
| 137 | + baseQuery = _db.Queryable<LqHytkKjbsyjEntity, LqHytkHytkEntity>( | ||
| 138 | + (kjbsyj, hytk) => kjbsyj.Gltkbh == hytk.Id) | ||
| 139 | + .Where((kjbsyj, hytk) => kjbsyj.Kjblszh == input.kjblsId) | ||
| 140 | + .Select((kjbsyj, hytk) => hytk) | ||
| 141 | + .Distinct() | ||
| 142 | + .MergeTable(); | ||
| 143 | + } | ||
| 144 | + else | ||
| 145 | + { | ||
| 146 | + // 没有传入健康师ID或科技部老师ID,使用原来的查询逻辑 | ||
| 147 | + baseQuery = _db.Queryable<LqHytkHytkEntity>(); | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + var data = await baseQuery | ||
| 83 | .WhereIF(!string.IsNullOrEmpty(input.id), p => p.Id.Contains(input.id)) | 151 | .WhereIF(!string.IsNullOrEmpty(input.id), p => p.Id.Contains(input.id)) |
| 84 | .WhereIF(!string.IsNullOrEmpty(input.md), p => p.Md.Equals(input.md)) | 152 | .WhereIF(!string.IsNullOrEmpty(input.md), p => p.Md.Equals(input.md)) |
| 85 | .WhereIF(!string.IsNullOrEmpty(input.mdbh), p => p.Mdbh.Contains(input.mdbh)) | 153 | .WhereIF(!string.IsNullOrEmpty(input.mdbh), p => p.Mdbh.Contains(input.mdbh)) |
| @@ -123,6 +191,104 @@ namespace NCC.Extend.LqHytkHytk | @@ -123,6 +191,104 @@ namespace NCC.Extend.LqHytkHytk | ||
| 123 | .MergeTable() | 191 | .MergeTable() |
| 124 | .OrderBy(sidx + " " + input.sort) | 192 | .OrderBy(sidx + " " + input.sort) |
| 125 | .ToPagedListAsync(input.currentPage, input.pageSize); | 193 | .ToPagedListAsync(input.currentPage, input.pageSize); |
| 194 | + | ||
| 195 | + // 获取当前页的退卡记录ID列表 | ||
| 196 | + var refundIds = data.list.Select(x => x.id).ToList(); | ||
| 197 | + | ||
| 198 | + // 批量查询品项明细(不过滤有效性,返回所有记录) | ||
| 199 | + var itemDetails = new List<LqHytkMxInfoOutput>(); | ||
| 200 | + if (refundIds.Any()) | ||
| 201 | + { | ||
| 202 | + itemDetails = await _db.Queryable<LqHytkMxEntity>() | ||
| 203 | + .Where(x => refundIds.Contains(x.RefundInfoId)) | ||
| 204 | + .Select(x => new LqHytkMxInfoOutput | ||
| 205 | + { | ||
| 206 | + id = x.Id, | ||
| 207 | + refundInfoId = x.RefundInfoId, | ||
| 208 | + billingItemId = x.BillingItemId, | ||
| 209 | + px = x.Px, | ||
| 210 | + pxmc = x.Pxmc, | ||
| 211 | + pxjg = x.Pxjg, | ||
| 212 | + tkje = x.Tkje, | ||
| 213 | + projectNumber = x.ProjectNumber, | ||
| 214 | + isEffective = x.IsEffective, | ||
| 215 | + sourceType = x.SourceType, | ||
| 216 | + totalPrice = x.TotalPrice | ||
| 217 | + }) | ||
| 218 | + .ToListAsync(); | ||
| 219 | + } | ||
| 220 | + | ||
| 221 | + // 批量查询健康师业绩(性能优化:一次性查询所有退卡的健康师业绩,不过滤有效性) | ||
| 222 | + var jksyjList = new List<LqHytkJksyjInfoOutput>(); | ||
| 223 | + if (refundIds.Any()) | ||
| 224 | + { | ||
| 225 | + jksyjList = await _db.Queryable<LqHytkJksyjEntity>() | ||
| 226 | + .Where(x => refundIds.Contains(x.Gltkbh)) | ||
| 227 | + .Select(x => new LqHytkJksyjInfoOutput | ||
| 228 | + { | ||
| 229 | + id = x.Id, | ||
| 230 | + gltkbh = x.Gltkbh, | ||
| 231 | + jks = x.Jks, | ||
| 232 | + jksxm = x.Jksxm, | ||
| 233 | + jkszh = x.Jkszh, | ||
| 234 | + jksyj = x.Jksyj, | ||
| 235 | + tksj = x.Tksj, | ||
| 236 | + F_jsjid = x.F_jsjid, | ||
| 237 | + F_tkpxid = x.F_tkpxid, | ||
| 238 | + F_LaborCost = x.F_LaborCost, | ||
| 239 | + F_tkpxNumber = x.F_tkpxNumber | ||
| 240 | + }) | ||
| 241 | + .ToListAsync(); | ||
| 242 | + } | ||
| 243 | + | ||
| 244 | + // 批量查询科技部老师业绩(性能优化:一次性查询所有退卡的科技部老师业绩,不过滤有效性) | ||
| 245 | + var kjbsyjList = new List<LqHytkKjbsyjInfoOutput>(); | ||
| 246 | + if (refundIds.Any()) | ||
| 247 | + { | ||
| 248 | + kjbsyjList = await _db.Queryable<LqHytkKjbsyjEntity>() | ||
| 249 | + .Where(x => refundIds.Contains(x.Gltkbh)) | ||
| 250 | + .Select(x => new LqHytkKjbsyjInfoOutput | ||
| 251 | + { | ||
| 252 | + id = x.Id, | ||
| 253 | + gltkbh = x.Gltkbh, | ||
| 254 | + kjbls = x.Kjbls, | ||
| 255 | + kjblsxm = x.Kjblsxm, | ||
| 256 | + kjblszh = x.Kjblszh, | ||
| 257 | + kjblsyj = x.Kjblsyj, | ||
| 258 | + tksj = x.Tksj, | ||
| 259 | + F_tkpxid = x.F_tkpxid, | ||
| 260 | + F_LaborCost = x.F_LaborCost, | ||
| 261 | + F_tkpxNumber = x.F_tkpxNumber | ||
| 262 | + }) | ||
| 263 | + .ToListAsync(); | ||
| 264 | + } | ||
| 265 | + | ||
| 266 | + // 按退卡ID分组品项明细 | ||
| 267 | + var itemDetailsGrouped = itemDetails.GroupBy(x => x.refundInfoId) | ||
| 268 | + .ToDictionary(g => g.Key, g => g.ToList()); | ||
| 269 | + | ||
| 270 | + // 按退卡ID分组健康师业绩 | ||
| 271 | + var jksyjGrouped = jksyjList.GroupBy(x => x.gltkbh) | ||
| 272 | + .ToDictionary(g => g.Key, g => g.ToList()); | ||
| 273 | + | ||
| 274 | + // 按退卡ID分组科技部老师业绩 | ||
| 275 | + var kjbsyjGrouped = kjbsyjList.GroupBy(x => x.gltkbh) | ||
| 276 | + .ToDictionary(g => g.Key, g => g.ToList()); | ||
| 277 | + | ||
| 278 | + // 为每个退卡记录分配品项明细、健康师业绩和科技部老师业绩 | ||
| 279 | + foreach (var item in data.list) | ||
| 280 | + { | ||
| 281 | + item.lqHytkMxList = itemDetailsGrouped.ContainsKey(item.id) | ||
| 282 | + ? itemDetailsGrouped[item.id] | ||
| 283 | + : new List<LqHytkMxInfoOutput>(); | ||
| 284 | + item.lqHytkJksyjList = jksyjGrouped.ContainsKey(item.id) | ||
| 285 | + ? jksyjGrouped[item.id] | ||
| 286 | + : new List<LqHytkJksyjInfoOutput>(); | ||
| 287 | + item.lqHytkKjbsyjList = kjbsyjGrouped.ContainsKey(item.id) | ||
| 288 | + ? kjbsyjGrouped[item.id] | ||
| 289 | + : new List<LqHytkKjbsyjInfoOutput>(); | ||
| 290 | + } | ||
| 291 | + | ||
| 126 | return PageResult<LqHytkHytkListOutput>.SqlSugarPageResult(data); | 292 | return PageResult<LqHytkHytkListOutput>.SqlSugarPageResult(data); |
| 127 | } | 293 | } |
| 128 | #endregion | 294 | #endregion |
netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
| @@ -45,6 +45,7 @@ using Yitter.IdGenerator; | @@ -45,6 +45,7 @@ using Yitter.IdGenerator; | ||
| 45 | using NCC.Extend.Entitys.lq_package_info; | 45 | using NCC.Extend.Entitys.lq_package_info; |
| 46 | using NCC.Extend.Entitys.lq_mdxx; | 46 | using NCC.Extend.Entitys.lq_mdxx; |
| 47 | using NCC.Extend.Entitys.lq_card_transfer_log; | 47 | using NCC.Extend.Entitys.lq_card_transfer_log; |
| 48 | +using NCC.Extend.Entitys.Dto.LqDailyReport; | ||
| 48 | 49 | ||
| 49 | namespace NCC.Extend.LqKdKdjlb | 50 | namespace NCC.Extend.LqKdKdjlb |
| 50 | { | 51 | { |
| @@ -64,6 +65,7 @@ namespace NCC.Extend.LqKdKdjlb | @@ -64,6 +65,7 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 64 | private readonly WeChatBotService _weChatBotService; | 65 | private readonly WeChatBotService _weChatBotService; |
| 65 | private readonly LqKdKdjlbStringGenerator _stringGenerator; | 66 | private readonly LqKdKdjlbStringGenerator _stringGenerator; |
| 66 | private readonly ILogger<LqKdKdjlbService> _logger; | 67 | private readonly ILogger<LqKdKdjlbService> _logger; |
| 68 | + private readonly LqDailyReportService _dailyReportService; | ||
| 67 | 69 | ||
| 68 | /// <summary> | 70 | /// <summary> |
| 69 | /// 初始化一个<see cref="LqKdKdjlbService"/>类型的新实例 | 71 | /// 初始化一个<see cref="LqKdKdjlbService"/>类型的新实例 |
| @@ -76,7 +78,8 @@ namespace NCC.Extend.LqKdKdjlb | @@ -76,7 +78,8 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 76 | IUserManager userManager, | 78 | IUserManager userManager, |
| 77 | WeChatBotService weChatBotService, | 79 | WeChatBotService weChatBotService, |
| 78 | LqKdKdjlbStringGenerator stringGenerator, | 80 | LqKdKdjlbStringGenerator stringGenerator, |
| 79 | - ILogger<LqKdKdjlbService> logger | 81 | + ILogger<LqKdKdjlbService> logger, |
| 82 | + LqDailyReportService dailyReportService | ||
| 80 | ) | 83 | ) |
| 81 | { | 84 | { |
| 82 | _lqKdKdjlbRepository = lqKdKdjlbRepository; | 85 | _lqKdKdjlbRepository = lqKdKdjlbRepository; |
| @@ -88,6 +91,7 @@ namespace NCC.Extend.LqKdKdjlb | @@ -88,6 +91,7 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 88 | _weChatBotService = weChatBotService; | 91 | _weChatBotService = weChatBotService; |
| 89 | _stringGenerator = stringGenerator; | 92 | _stringGenerator = stringGenerator; |
| 90 | _logger = logger; | 93 | _logger = logger; |
| 94 | + _dailyReportService = dailyReportService; | ||
| 91 | } | 95 | } |
| 92 | 96 | ||
| 93 | #region 获取开单记录表 | 97 | #region 获取开单记录表 |
| @@ -214,8 +218,49 @@ namespace NCC.Extend.LqKdKdjlb | @@ -214,8 +218,49 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 214 | List<string> queryKdrq = input.kdrq != null ? input.kdrq.Split(',').ToObeject<List<string>>() : null; | 218 | List<string> queryKdrq = input.kdrq != null ? input.kdrq.Split(',').ToObeject<List<string>>() : null; |
| 215 | DateTime? startKdrq = queryKdrq != null ? Ext.GetDateTime(queryKdrq.First()) : null; | 219 | DateTime? startKdrq = queryKdrq != null ? Ext.GetDateTime(queryKdrq.First()) : null; |
| 216 | DateTime? endKdrq = queryKdrq != null ? Ext.GetDateTime(queryKdrq.Last()) : null; | 220 | DateTime? endKdrq = queryKdrq != null ? Ext.GetDateTime(queryKdrq.Last()) : null; |
| 217 | - var data = await _db.Queryable<LqKdKdjlbEntity>() | ||
| 218 | - .WhereIF(!string.IsNullOrEmpty(input.keyword), p => p.Kdhyc.Contains(input.keyword) || p.Kdhysjh.Contains(input.keyword)) | 221 | + |
| 222 | + // 根据是否传入健康师ID或科技部老师ID,动态构建查询 | ||
| 223 | + ISugarQueryable<LqKdKdjlbEntity> baseQuery = null; | ||
| 224 | + | ||
| 225 | + if (!string.IsNullOrEmpty(input.jksId) && !string.IsNullOrEmpty(input.kjblsId)) | ||
| 226 | + { | ||
| 227 | + // 同时传入健康师ID和科技部老师ID,需要同时关联两个业绩表 | ||
| 228 | + baseQuery = _db.Queryable<LqKdJksyjEntity, LqKdKjbsyjEntity, LqKdKdjlbEntity>( | ||
| 229 | + (jksyj, kjbsyj, kdjlb) => jksyj.Glkdbh == kdjlb.Id && kjbsyj.Glkdbh == kdjlb.Id) | ||
| 230 | + .Where((jksyj, kjbsyj, kdjlb) => jksyj.Jkszh == input.jksId && jksyj.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 231 | + .Where((jksyj, kjbsyj, kdjlb) => kjbsyj.Kjbls == input.kjblsId && kjbsyj.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 232 | + .Select((jksyj, kjbsyj, kdjlb) => kdjlb) | ||
| 233 | + .Distinct() | ||
| 234 | + .MergeTable(); | ||
| 235 | + } | ||
| 236 | + else if (!string.IsNullOrEmpty(input.jksId)) | ||
| 237 | + { | ||
| 238 | + // 只传入健康师ID,关联健康师业绩表 | ||
| 239 | + baseQuery = _db.Queryable<LqKdJksyjEntity, LqKdKdjlbEntity>( | ||
| 240 | + (jksyj, kdjlb) => jksyj.Glkdbh == kdjlb.Id) | ||
| 241 | + .Where((jksyj, kdjlb) => jksyj.Jkszh == input.jksId && jksyj.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 242 | + .Select((jksyj, kdjlb) => kdjlb) | ||
| 243 | + .Distinct() | ||
| 244 | + .MergeTable(); | ||
| 245 | + } | ||
| 246 | + else if (!string.IsNullOrEmpty(input.kjblsId)) | ||
| 247 | + { | ||
| 248 | + // 只传入科技部老师ID,关联科技部老师业绩表 | ||
| 249 | + baseQuery = _db.Queryable<LqKdKjbsyjEntity, LqKdKdjlbEntity>( | ||
| 250 | + (kjbsyj, kdjlb) => kjbsyj.Glkdbh == kdjlb.Id) | ||
| 251 | + .Where((kjbsyj, kdjlb) => kjbsyj.Kjbls == input.kjblsId && kjbsyj.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 252 | + .Select((kjbsyj, kdjlb) => kdjlb) | ||
| 253 | + .Distinct() | ||
| 254 | + .MergeTable(); | ||
| 255 | + } | ||
| 256 | + else | ||
| 257 | + { | ||
| 258 | + // 没有传入健康师ID或科技部老师ID,使用原来的查询逻辑 | ||
| 259 | + baseQuery = _db.Queryable<LqKdKdjlbEntity>(); | ||
| 260 | + } | ||
| 261 | + | ||
| 262 | + var data = await baseQuery | ||
| 263 | + .WhereIF(!string.IsNullOrEmpty(input.keyword), p => p.Kdhyc.Contains(input.keyword) || p.Kdhysjh.Contains(input.keyword)) | ||
| 219 | .WhereIF(!string.IsNullOrEmpty(input.id), p => p.Id.Contains(input.id)) | 264 | .WhereIF(!string.IsNullOrEmpty(input.id), p => p.Id.Contains(input.id)) |
| 220 | .WhereIF(!string.IsNullOrEmpty(input.djmd), p => p.Djmd.Equals(input.djmd)) | 265 | .WhereIF(!string.IsNullOrEmpty(input.djmd), p => p.Djmd.Equals(input.djmd)) |
| 221 | .WhereIF(!string.IsNullOrEmpty(input.jsj), p => p.Jsj.Equals(input.jsj)) | 266 | .WhereIF(!string.IsNullOrEmpty(input.jsj), p => p.Jsj.Equals(input.jsj)) |
| @@ -308,18 +353,380 @@ namespace NCC.Extend.LqKdKdjlb | @@ -308,18 +353,380 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 308 | var itemDetailsGrouped = itemDetails.GroupBy(x => x.glkdbh) | 353 | var itemDetailsGrouped = itemDetails.GroupBy(x => x.glkdbh) |
| 309 | .ToDictionary(g => g.Key, g => g.ToList()); | 354 | .ToDictionary(g => g.Key, g => g.ToList()); |
| 310 | 355 | ||
| 311 | - // 为每个开单记录分配品项明细 | 356 | + // 批量查询健康师业绩(性能优化:一次性查询所有开单的健康师业绩) |
| 357 | + var jksyjList = new List<LqKdJksyjInfoOutput>(); | ||
| 358 | + if (billingIds.Any()) | ||
| 359 | + { | ||
| 360 | + jksyjList = await _db.Queryable<LqKdJksyjEntity>() | ||
| 361 | + .Where(x => billingIds.Contains(x.Glkdbh) && x.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 362 | + .Select(x => new LqKdJksyjInfoOutput | ||
| 363 | + { | ||
| 364 | + id = x.Id, | ||
| 365 | + glkdbh = x.Glkdbh, | ||
| 366 | + kdpxid = x.Kdpxid, | ||
| 367 | + jks = x.Jks, | ||
| 368 | + jksxm = x.Jksxm, | ||
| 369 | + jkszh = x.Jkszh, | ||
| 370 | + jksyj = x.Jksyj, | ||
| 371 | + yjsj = x.Yjsj, | ||
| 372 | + jsj_id = x.Jsj_id, | ||
| 373 | + isEffective = x.IsEffective | ||
| 374 | + }) | ||
| 375 | + .ToListAsync(); | ||
| 376 | + } | ||
| 377 | + | ||
| 378 | + // 批量查询科技部老师业绩(性能优化:一次性查询所有开单的科技部老师业绩) | ||
| 379 | + var kjbsyjList = new List<LqKdKjbsyjInfoOutput>(); | ||
| 380 | + if (billingIds.Any()) | ||
| 381 | + { | ||
| 382 | + kjbsyjList = await _db.Queryable<LqKdKjbsyjEntity>() | ||
| 383 | + .Where(x => billingIds.Contains(x.Glkdbh) && x.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 384 | + .Select(x => new LqKdKjbsyjInfoOutput | ||
| 385 | + { | ||
| 386 | + id = x.Id, | ||
| 387 | + glkdbh = x.Glkdbh, | ||
| 388 | + kdpxid = x.Kdpxid, | ||
| 389 | + kjbls = x.Kjbls, | ||
| 390 | + kjblsxm = x.Kjblsxm, | ||
| 391 | + kjblszh = x.Kjblszh, | ||
| 392 | + kjblsyj = x.Kjblsyj, | ||
| 393 | + yjsj = x.Yjsj, | ||
| 394 | + isEffective = x.IsEffective | ||
| 395 | + }) | ||
| 396 | + .ToListAsync(); | ||
| 397 | + } | ||
| 398 | + | ||
| 399 | + // 按开单ID分组健康师业绩 | ||
| 400 | + var jksyjGrouped = jksyjList.GroupBy(x => x.glkdbh) | ||
| 401 | + .ToDictionary(g => g.Key, g => g.ToList()); | ||
| 402 | + | ||
| 403 | + // 按开单ID分组科技部老师业绩 | ||
| 404 | + var kjbsyjGrouped = kjbsyjList.GroupBy(x => x.glkdbh) | ||
| 405 | + .ToDictionary(g => g.Key, g => g.ToList()); | ||
| 406 | + | ||
| 407 | + // 为每个开单记录分配品项明细、健康师业绩和科技部老师业绩 | ||
| 312 | foreach (var item in data.list) | 408 | foreach (var item in data.list) |
| 313 | { | 409 | { |
| 314 | item.ItemDetails = itemDetailsGrouped.ContainsKey(item.id) | 410 | item.ItemDetails = itemDetailsGrouped.ContainsKey(item.id) |
| 315 | ? itemDetailsGrouped[item.id] | 411 | ? itemDetailsGrouped[item.id] |
| 316 | : new List<LqKdPxmxInfoOutput>(); | 412 | : new List<LqKdPxmxInfoOutput>(); |
| 413 | + item.lqKdJksyjList = jksyjGrouped.ContainsKey(item.id) | ||
| 414 | + ? jksyjGrouped[item.id] | ||
| 415 | + : new List<LqKdJksyjInfoOutput>(); | ||
| 416 | + item.lqKdKjbsyjList = kjbsyjGrouped.ContainsKey(item.id) | ||
| 417 | + ? kjbsyjGrouped[item.id] | ||
| 418 | + : new List<LqKdKjbsyjInfoOutput>(); | ||
| 317 | } | 419 | } |
| 318 | 420 | ||
| 319 | return PageResult<LqKdKdjlbListOutput>.SqlSugarPageResult(data); | 421 | return PageResult<LqKdKdjlbListOutput>.SqlSugarPageResult(data); |
| 320 | } | 422 | } |
| 321 | #endregion | 423 | #endregion |
| 322 | 424 | ||
| 425 | + #region 根据健康师ID获取开单列表 | ||
| 426 | + /// <summary> | ||
| 427 | + /// 根据健康师ID获取开单列表 | ||
| 428 | + /// </summary> | ||
| 429 | + /// <remarks> | ||
| 430 | + /// 根据健康师ID查询该健康师参与的所有开单记录,支持时间周期查询和分页 | ||
| 431 | + /// | ||
| 432 | + /// 示例请求: | ||
| 433 | + /// GET /api/Extend/LqKdKdjlb/GetListByJksId?jksId=健康师ID&startTime=2025-01-01&endTime=2025-01-31&currentPage=1&pageSize=10 | ||
| 434 | + /// | ||
| 435 | + /// 参数说明: | ||
| 436 | + /// - jksId: 健康师ID(必填) | ||
| 437 | + /// - startTime: 开始时间(可选,格式:yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss) | ||
| 438 | + /// - endTime: 结束时间(可选,格式:yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss) | ||
| 439 | + /// - djmd: 门店ID(可选) | ||
| 440 | + /// - isEffective: 是否有效(可选,0=全部,1=有效,2=无效,默认1) | ||
| 441 | + /// - currentPage: 当前页码(必填) | ||
| 442 | + /// - pageSize: 每页数量(必填) | ||
| 443 | + /// | ||
| 444 | + /// 返回说明: | ||
| 445 | + /// - 返回格式与GetList接口相同,包含开单基本信息及品项明细列表 | ||
| 446 | + /// </remarks> | ||
| 447 | + /// <param name="input">查询参数</param> | ||
| 448 | + /// <returns>开单列表(分页)</returns> | ||
| 449 | + /// <response code="200">查询成功</response> | ||
| 450 | + /// <response code="400">参数错误</response> | ||
| 451 | + /// <response code="500">服务器内部错误</response> | ||
| 452 | + [HttpGet("GetListByJksId")] | ||
| 453 | + public async Task<dynamic> GetListByJksId([FromQuery] LqKdKdjlbListByJksQueryInput input) | ||
| 454 | + { | ||
| 455 | + try | ||
| 456 | + { | ||
| 457 | + if (string.IsNullOrEmpty(input.jksId)) | ||
| 458 | + { | ||
| 459 | + throw NCCException.Oh("健康师ID不能为空"); | ||
| 460 | + } | ||
| 461 | + var sidx = input.sidx == null ? "kdrq" : input.sidx; | ||
| 462 | + var sort = string.IsNullOrEmpty(input.sort) ? "DESC" : input.sort; | ||
| 463 | + // 解析时间范围 | ||
| 464 | + DateTime? startDate = null; | ||
| 465 | + DateTime? endDate = null; | ||
| 466 | + if (!string.IsNullOrEmpty(input.startTime)) | ||
| 467 | + { | ||
| 468 | + startDate = Ext.GetDateTime(input.startTime); | ||
| 469 | + } | ||
| 470 | + if (!string.IsNullOrEmpty(input.endTime)) | ||
| 471 | + { | ||
| 472 | + endDate = Ext.GetDateTime(input.endTime); | ||
| 473 | + // 如果只传了日期,则设置为当天的23:59:59 | ||
| 474 | + if (endDate.HasValue && !input.endTime.Contains(":")) | ||
| 475 | + { | ||
| 476 | + endDate = new DateTime(endDate.Value.Year, endDate.Value.Month, endDate.Value.Day, 23, 59, 59); | ||
| 477 | + } | ||
| 478 | + } | ||
| 479 | + | ||
| 480 | + // 通过健康师业绩表关联查询开单记录 | ||
| 481 | + var data = await _db.Queryable<LqKdJksyjEntity, LqKdKdjlbEntity>((jksyj, kdjlb) => jksyj.Glkdbh == kdjlb.Id) | ||
| 482 | + .Where((jksyj, kdjlb) => jksyj.Jkszh == input.jksId) | ||
| 483 | + .WhereIF(input.isEffective != 0, (jksyj, kdjlb) => jksyj.IsEffective == input.isEffective && kdjlb.IsEffective == input.isEffective) | ||
| 484 | + .WhereIF(input.isEffective == 0, (jksyj, kdjlb) => jksyj.IsEffective == StatusEnum.有效.GetHashCode() && kdjlb.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 485 | + .WhereIF(startDate.HasValue, (jksyj, kdjlb) => kdjlb.Kdrq >= startDate.Value) | ||
| 486 | + .WhereIF(endDate.HasValue, (jksyj, kdjlb) => kdjlb.Kdrq <= endDate.Value) | ||
| 487 | + .WhereIF(!string.IsNullOrEmpty(input.djmd), (jksyj, kdjlb) => kdjlb.Djmd == input.djmd) | ||
| 488 | + .Select((jksyj, kdjlb) => new LqKdKdjlbListOutput | ||
| 489 | + { | ||
| 490 | + id = kdjlb.Id, | ||
| 491 | + djmd = kdjlb.Djmd, | ||
| 492 | + jsj = kdjlb.Jsj, | ||
| 493 | + kdrq = kdjlb.Kdrq, | ||
| 494 | + gjlx = kdjlb.Gjlx, | ||
| 495 | + hgjg = kdjlb.Hgjg, | ||
| 496 | + zdyj = kdjlb.Zdyj, | ||
| 497 | + sfyj = kdjlb.Sfyj, | ||
| 498 | + qk = kdjlb.Qk, | ||
| 499 | + ckfs = kdjlb.Ckfs, | ||
| 500 | + fkfs = kdjlb.Fkfs, | ||
| 501 | + fkyy = kdjlb.Fkyy, | ||
| 502 | + fkpd = kdjlb.Fkpd, | ||
| 503 | + khly = kdjlb.Khly, | ||
| 504 | + tjr = kdjlb.Tjr, | ||
| 505 | + deductAmount = kdjlb.DeductAmount, | ||
| 506 | + paidDebt = kdjlb.PaidDebt, | ||
| 507 | + supplementBillingId = kdjlb.SupplementBillingId, | ||
| 508 | + sfskdd = kdjlb.Sfskdd, | ||
| 509 | + jj = kdjlb.Jj, | ||
| 510 | + bz = kdjlb.Bz, | ||
| 511 | + kdhy = kdjlb.Kdhy, | ||
| 512 | + kdhyc = SqlFunc.Subqueryable<LqKhxxEntity>().Where(x => x.Id == kdjlb.Kdhy).Select(x => x.Khmc), | ||
| 513 | + kdhysjh = SqlFunc.Subqueryable<LqKhxxEntity>().Where(x => x.Id == kdjlb.Kdhy).Select(x => x.Sjh), | ||
| 514 | + isEffective = kdjlb.IsEffective, | ||
| 515 | + createUser = kdjlb.CreateUser, | ||
| 516 | + createUserName = SqlFunc.Subqueryable<UserEntity>().Where(x => x.Id == kdjlb.CreateUser).Select(x => x.RealName), | ||
| 517 | + activityId = kdjlb.ActivityId, | ||
| 518 | + activityName = SqlFunc.Subqueryable<LqPackageInfoEntity>().Where(x => x.Id == kdjlb.ActivityId).Select(x => x.ActivityName), | ||
| 519 | + }) | ||
| 520 | + .MergeTable() | ||
| 521 | + .Distinct() // 去重,因为一个开单可能对应多个健康师业绩记录 | ||
| 522 | + .OrderBy($"{sidx} {sort}") | ||
| 523 | + .ToPagedListAsync(input.currentPage, input.pageSize); | ||
| 524 | + | ||
| 525 | + // 获取当前页的开单记录ID列表 | ||
| 526 | + var billingIds = data.list.Select(x => x.id).ToList(); | ||
| 527 | + | ||
| 528 | + // 批量查询品项明细 | ||
| 529 | + var itemDetails = new List<LqKdPxmxInfoOutput>(); | ||
| 530 | + if (billingIds.Any()) | ||
| 531 | + { | ||
| 532 | + itemDetails = await _db.Queryable<LqKdPxmxEntity>() | ||
| 533 | + .Where(x => billingIds.Contains(x.Glkdbh) && x.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 534 | + .Select(x => new LqKdPxmxInfoOutput | ||
| 535 | + { | ||
| 536 | + id = x.Id, | ||
| 537 | + glkdbh = x.Glkdbh, | ||
| 538 | + px = x.Px, | ||
| 539 | + pxmc = x.Pxmc, | ||
| 540 | + pxjg = x.Pxjg, | ||
| 541 | + projectNumber = x.ProjectNumber, | ||
| 542 | + isEnabled = x.IsEnabled, | ||
| 543 | + sourceType = x.SourceType, | ||
| 544 | + memberId = x.MemberId, | ||
| 545 | + createTime = x.CreateTIme, | ||
| 546 | + totalPrice = x.TotalPrice, | ||
| 547 | + actualPrice = x.ActualPrice, | ||
| 548 | + remark = x.Remark, | ||
| 549 | + isEffective = x.IsEffective | ||
| 550 | + }) | ||
| 551 | + .ToListAsync(); | ||
| 552 | + } | ||
| 553 | + | ||
| 554 | + // 按开单ID分组品项明细 | ||
| 555 | + var itemDetailsGrouped = itemDetails.GroupBy(x => x.glkdbh) | ||
| 556 | + .ToDictionary(g => g.Key, g => g.ToList()); | ||
| 557 | + | ||
| 558 | + // 为每个开单记录分配品项明细 | ||
| 559 | + foreach (var item in data.list) | ||
| 560 | + { | ||
| 561 | + item.ItemDetails = itemDetailsGrouped.ContainsKey(item.id) | ||
| 562 | + ? itemDetailsGrouped[item.id] | ||
| 563 | + : new List<LqKdPxmxInfoOutput>(); | ||
| 564 | + } | ||
| 565 | + | ||
| 566 | + return PageResult<LqKdKdjlbListOutput>.SqlSugarPageResult(data); | ||
| 567 | + } | ||
| 568 | + catch (Exception ex) | ||
| 569 | + { | ||
| 570 | + _logger.LogError(ex, $"根据健康师ID获取开单列表失败 - 健康师ID: {input?.jksId}, 开始时间: {input?.startTime}, 结束时间: {input?.endTime}"); | ||
| 571 | + throw NCCException.Oh($"根据健康师ID获取开单列表失败: {ex.Message}"); | ||
| 572 | + } | ||
| 573 | + } | ||
| 574 | + #endregion | ||
| 575 | + | ||
| 576 | + #region 根据科技部老师ID获取开单列表 | ||
| 577 | + /// <summary> | ||
| 578 | + /// 根据科技部老师ID获取开单列表 | ||
| 579 | + /// </summary> | ||
| 580 | + /// <remarks> | ||
| 581 | + /// 根据科技部老师ID查询该老师参与的所有开单记录,支持时间周期查询和分页 | ||
| 582 | + /// | ||
| 583 | + /// 示例请求: | ||
| 584 | + /// GET /api/Extend/LqKdKdjlb/GetListByKjbId?kjblsId=科技部老师ID&startTime=2025-01-01&endTime=2025-01-31&currentPage=1&pageSize=10 | ||
| 585 | + /// | ||
| 586 | + /// 参数说明: | ||
| 587 | + /// - kjblsId: 科技部老师ID(必填) | ||
| 588 | + /// - startTime: 开始时间(可选,格式:yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss) | ||
| 589 | + /// - endTime: 结束时间(可选,格式:yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss) | ||
| 590 | + /// - djmd: 门店ID(可选) | ||
| 591 | + /// - isEffective: 是否有效(可选,0=全部,1=有效,2=无效,默认1) | ||
| 592 | + /// - currentPage: 当前页码(必填) | ||
| 593 | + /// - pageSize: 每页数量(必填) | ||
| 594 | + /// | ||
| 595 | + /// 返回说明: | ||
| 596 | + /// - 返回格式与GetList接口相同,包含开单基本信息及品项明细列表 | ||
| 597 | + /// </remarks> | ||
| 598 | + /// <param name="input">查询参数</param> | ||
| 599 | + /// <returns>开单列表(分页)</returns> | ||
| 600 | + /// <response code="200">查询成功</response> | ||
| 601 | + /// <response code="400">参数错误</response> | ||
| 602 | + /// <response code="500">服务器内部错误</response> | ||
| 603 | + [HttpGet("GetListByKjbId")] | ||
| 604 | + public async Task<dynamic> GetListByKjbId([FromQuery] LqKdKdjlbListByKjbQueryInput input) | ||
| 605 | + { | ||
| 606 | + try | ||
| 607 | + { | ||
| 608 | + if (string.IsNullOrEmpty(input.kjblsId)) | ||
| 609 | + { | ||
| 610 | + throw NCCException.Oh("科技部老师ID不能为空"); | ||
| 611 | + } | ||
| 612 | + | ||
| 613 | + var sidx = input.sidx == null ? "kdrq" : input.sidx; | ||
| 614 | + var sort = string.IsNullOrEmpty(input.sort) ? "DESC" : input.sort; | ||
| 615 | + | ||
| 616 | + // 解析时间范围 | ||
| 617 | + DateTime? startDate = null; | ||
| 618 | + DateTime? endDate = null; | ||
| 619 | + if (!string.IsNullOrEmpty(input.startTime)) | ||
| 620 | + { | ||
| 621 | + startDate = Ext.GetDateTime(input.startTime); | ||
| 622 | + } | ||
| 623 | + if (!string.IsNullOrEmpty(input.endTime)) | ||
| 624 | + { | ||
| 625 | + endDate = Ext.GetDateTime(input.endTime); | ||
| 626 | + // 如果只传了日期,则设置为当天的23:59:59 | ||
| 627 | + if (endDate.HasValue && !input.endTime.Contains(":")) | ||
| 628 | + { | ||
| 629 | + endDate = new DateTime(endDate.Value.Year, endDate.Value.Month, endDate.Value.Day, 23, 59, 59); | ||
| 630 | + } | ||
| 631 | + } | ||
| 632 | + | ||
| 633 | + // 通过科技部老师业绩表关联查询开单记录 | ||
| 634 | + var data = await _db.Queryable<LqKdKjbsyjEntity, LqKdKdjlbEntity>( | ||
| 635 | + (kjbsyj, kdjlb) => kjbsyj.Glkdbh == kdjlb.Id) | ||
| 636 | + .Where((kjbsyj, kdjlb) => kjbsyj.Kjbls == input.kjblsId) | ||
| 637 | + .WhereIF(input.isEffective != 0, (kjbsyj, kdjlb) => kjbsyj.IsEffective == input.isEffective && kdjlb.IsEffective == input.isEffective) | ||
| 638 | + .WhereIF(input.isEffective == 0, (kjbsyj, kdjlb) => kjbsyj.IsEffective == StatusEnum.有效.GetHashCode() && kdjlb.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 639 | + .WhereIF(startDate.HasValue, (kjbsyj, kdjlb) => kdjlb.Kdrq >= startDate.Value) | ||
| 640 | + .WhereIF(endDate.HasValue, (kjbsyj, kdjlb) => kdjlb.Kdrq <= endDate.Value) | ||
| 641 | + .WhereIF(!string.IsNullOrEmpty(input.djmd), (kjbsyj, kdjlb) => kdjlb.Djmd == input.djmd) | ||
| 642 | + .Select((kjbsyj, kdjlb) => new LqKdKdjlbListOutput | ||
| 643 | + { | ||
| 644 | + id = kdjlb.Id, | ||
| 645 | + djmd = kdjlb.Djmd, | ||
| 646 | + jsj = kdjlb.Jsj, | ||
| 647 | + kdrq = kdjlb.Kdrq, | ||
| 648 | + gjlx = kdjlb.Gjlx, | ||
| 649 | + hgjg = kdjlb.Hgjg, | ||
| 650 | + zdyj = kdjlb.Zdyj, | ||
| 651 | + sfyj = kdjlb.Sfyj, | ||
| 652 | + qk = kdjlb.Qk, | ||
| 653 | + ckfs = kdjlb.Ckfs, | ||
| 654 | + fkfs = kdjlb.Fkfs, | ||
| 655 | + fkyy = kdjlb.Fkyy, | ||
| 656 | + fkpd = kdjlb.Fkpd, | ||
| 657 | + khly = kdjlb.Khly, | ||
| 658 | + tjr = kdjlb.Tjr, | ||
| 659 | + deductAmount = kdjlb.DeductAmount, | ||
| 660 | + paidDebt = kdjlb.PaidDebt, | ||
| 661 | + supplementBillingId = kdjlb.SupplementBillingId, | ||
| 662 | + sfskdd = kdjlb.Sfskdd, | ||
| 663 | + jj = kdjlb.Jj, | ||
| 664 | + bz = kdjlb.Bz, | ||
| 665 | + kdhy = kdjlb.Kdhy, | ||
| 666 | + kdhyc = SqlFunc.Subqueryable<LqKhxxEntity>().Where(x => x.Id == kdjlb.Kdhy).Select(x => x.Khmc), | ||
| 667 | + kdhysjh = SqlFunc.Subqueryable<LqKhxxEntity>().Where(x => x.Id == kdjlb.Kdhy).Select(x => x.Sjh), | ||
| 668 | + isEffective = kdjlb.IsEffective, | ||
| 669 | + createUser = kdjlb.CreateUser, | ||
| 670 | + createUserName = SqlFunc.Subqueryable<UserEntity>().Where(x => x.Id == kdjlb.CreateUser).Select(x => x.RealName), | ||
| 671 | + activityId = kdjlb.ActivityId, | ||
| 672 | + activityName = SqlFunc.Subqueryable<LqPackageInfoEntity>().Where(x => x.Id == kdjlb.ActivityId).Select(x => x.ActivityName), | ||
| 673 | + }) | ||
| 674 | + .MergeTable() | ||
| 675 | + .Distinct() // 去重,因为一个开单可能对应多个科技部老师业绩记录 | ||
| 676 | + .OrderBy($"{sidx} {sort}") | ||
| 677 | + .ToPagedListAsync(input.currentPage, input.pageSize); | ||
| 678 | + | ||
| 679 | + // 获取当前页的开单记录ID列表 | ||
| 680 | + var billingIds = data.list.Select(x => x.id).ToList(); | ||
| 681 | + | ||
| 682 | + // 批量查询品项明细 | ||
| 683 | + var itemDetails = new List<LqKdPxmxInfoOutput>(); | ||
| 684 | + if (billingIds.Any()) | ||
| 685 | + { | ||
| 686 | + itemDetails = await _db.Queryable<LqKdPxmxEntity>() | ||
| 687 | + .Where(x => billingIds.Contains(x.Glkdbh) && x.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 688 | + .Select(x => new LqKdPxmxInfoOutput | ||
| 689 | + { | ||
| 690 | + id = x.Id, | ||
| 691 | + glkdbh = x.Glkdbh, | ||
| 692 | + px = x.Px, | ||
| 693 | + pxmc = x.Pxmc, | ||
| 694 | + pxjg = x.Pxjg, | ||
| 695 | + projectNumber = x.ProjectNumber, | ||
| 696 | + isEnabled = x.IsEnabled, | ||
| 697 | + sourceType = x.SourceType, | ||
| 698 | + memberId = x.MemberId, | ||
| 699 | + createTime = x.CreateTIme, | ||
| 700 | + totalPrice = x.TotalPrice, | ||
| 701 | + actualPrice = x.ActualPrice, | ||
| 702 | + remark = x.Remark, | ||
| 703 | + isEffective = x.IsEffective | ||
| 704 | + }) | ||
| 705 | + .ToListAsync(); | ||
| 706 | + } | ||
| 707 | + | ||
| 708 | + // 按开单ID分组品项明细 | ||
| 709 | + var itemDetailsGrouped = itemDetails.GroupBy(x => x.glkdbh) | ||
| 710 | + .ToDictionary(g => g.Key, g => g.ToList()); | ||
| 711 | + | ||
| 712 | + // 为每个开单记录分配品项明细 | ||
| 713 | + foreach (var item in data.list) | ||
| 714 | + { | ||
| 715 | + item.ItemDetails = itemDetailsGrouped.ContainsKey(item.id) | ||
| 716 | + ? itemDetailsGrouped[item.id] | ||
| 717 | + : new List<LqKdPxmxInfoOutput>(); | ||
| 718 | + } | ||
| 719 | + | ||
| 720 | + return PageResult<LqKdKdjlbListOutput>.SqlSugarPageResult(data); | ||
| 721 | + } | ||
| 722 | + catch (Exception ex) | ||
| 723 | + { | ||
| 724 | + _logger.LogError(ex, $"根据科技部老师ID获取开单列表失败 - 科技部老师ID: {input?.kjblsId}, 开始时间: {input?.startTime}, 结束时间: {input?.endTime}"); | ||
| 725 | + throw NCCException.Oh($"根据科技部老师ID获取开单列表失败: {ex.Message}"); | ||
| 726 | + } | ||
| 727 | + } | ||
| 728 | + #endregion | ||
| 729 | + | ||
| 323 | #region 新建开单记录表 | 730 | #region 新建开单记录表 |
| 324 | /// <summary> | 731 | /// <summary> |
| 325 | /// 新建开单记录表 | 732 | /// 新建开单记录表 |
| @@ -563,6 +970,47 @@ namespace NCC.Extend.LqKdKdjlb | @@ -563,6 +970,47 @@ namespace NCC.Extend.LqKdKdjlb | ||
| 563 | // 字符串生成失败不影响主流程,只记录日志 | 970 | // 字符串生成失败不影响主流程,只记录日志 |
| 564 | Console.WriteLine($"生成开单记录字符串失败: {ex.Message}"); | 971 | Console.WriteLine($"生成开单记录字符串失败: {ex.Message}"); |
| 565 | } | 972 | } |
| 973 | + | ||
| 974 | + // 播报事业部开单统计数据 | ||
| 975 | + try | ||
| 976 | + { | ||
| 977 | + //判断如果开单金额大于0,则播报事业部开单统计数据 | ||
| 978 | + if (newEntity.Sfyj > 0 && newEntity.Kdrq.HasValue) | ||
| 979 | + { | ||
| 980 | + var billingDate = newEntity.Kdrq.Value.ToString("yyyy-MM-dd"); | ||
| 981 | + var statisticsInput = new BusinessUnitBillingStatisticsInput | ||
| 982 | + { | ||
| 983 | + Date = billingDate | ||
| 984 | + }; | ||
| 985 | + var statisticsText = await _dailyReportService.GetBusinessUnitBillingStatisticsText(statisticsInput); | ||
| 986 | + | ||
| 987 | + if (!string.IsNullOrEmpty(statisticsText) && !statisticsText.Contains("暂无开单数据")) | ||
| 988 | + { | ||
| 989 | + // 发送到企业微信群 | ||
| 990 | + try | ||
| 991 | + { | ||
| 992 | + var sendResult = await _weChatBotService.SendTextMessage(statisticsText); | ||
| 993 | + if (sendResult) | ||
| 994 | + { | ||
| 995 | + Console.WriteLine("事业部开单统计数据已成功发送到企业微信群"); | ||
| 996 | + } | ||
| 997 | + else | ||
| 998 | + { | ||
| 999 | + Console.WriteLine("事业部开单统计数据发送到企业微信群失败"); | ||
| 1000 | + } | ||
| 1001 | + } | ||
| 1002 | + catch (Exception wechatEx) | ||
| 1003 | + { | ||
| 1004 | + Console.WriteLine($"发送事业部开单统计数据异常: {wechatEx.Message}"); | ||
| 1005 | + } | ||
| 1006 | + } | ||
| 1007 | + } | ||
| 1008 | + } | ||
| 1009 | + catch (Exception ex) | ||
| 1010 | + { | ||
| 1011 | + // 播报失败不影响主流程,只记录日志 | ||
| 1012 | + Console.WriteLine($"播报事业部开单统计数据失败: {ex.Message}"); | ||
| 1013 | + } | ||
| 566 | } | 1014 | } |
| 567 | catch (Exception ex) | 1015 | catch (Exception ex) |
| 568 | { | 1016 | { |
netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
| @@ -551,7 +551,8 @@ namespace NCC.Extend.LqKhxx | @@ -551,7 +551,8 @@ namespace NCC.Extend.LqKhxx | ||
| 551 | x.Pxmc, | 551 | x.Pxmc, |
| 552 | x.Pxjg, | 552 | x.Pxjg, |
| 553 | x.SourceType, | 553 | x.SourceType, |
| 554 | - x.ProjectNumber | 554 | + x.ProjectNumber, |
| 555 | + x.Remark | ||
| 555 | }) | 556 | }) |
| 556 | .ToListAsync(); | 557 | .ToListAsync(); |
| 557 | 558 | ||
| @@ -600,6 +601,7 @@ namespace NCC.Extend.LqKhxx | @@ -600,6 +601,7 @@ namespace NCC.Extend.LqKhxx | ||
| 600 | ItemPrice = item.Pxjg, | 601 | ItemPrice = item.Pxjg, |
| 601 | SourceType = item.SourceType, | 602 | SourceType = item.SourceType, |
| 602 | TotalPurchased = item.ProjectNumber, | 603 | TotalPurchased = item.ProjectNumber, |
| 604 | + Remark = item.Remark, | ||
| 603 | ConsumedCount = consumedData.FirstOrDefault(c => c.BillingItemId == item.Id)?.TotalConsumed ?? 0, | 605 | ConsumedCount = consumedData.FirstOrDefault(c => c.BillingItemId == item.Id)?.TotalConsumed ?? 0, |
| 604 | RefundedCount = refundedData.FirstOrDefault(r => r.BillingItemId == item.Id)?.TotalRefunded ?? 0, | 606 | RefundedCount = refundedData.FirstOrDefault(r => r.BillingItemId == item.Id)?.TotalRefunded ?? 0, |
| 605 | DeductCount = deductData.FirstOrDefault(d => d.BillingItemId == item.Id)?.TotalDeduct ?? 0, | 607 | DeductCount = deductData.FirstOrDefault(d => d.BillingItemId == item.Id)?.TotalDeduct ?? 0, |
netcore/src/Modularity/Extend/NCC.Extend/LqMdGeneralManagerLifelineService.cs
| @@ -7,10 +7,12 @@ using Mapster; | @@ -7,10 +7,12 @@ using Mapster; | ||
| 7 | using Microsoft.AspNetCore.Mvc; | 7 | using Microsoft.AspNetCore.Mvc; |
| 8 | using NCC.Common.Core.Manager; | 8 | using NCC.Common.Core.Manager; |
| 9 | using NCC.Common.Enum; | 9 | using NCC.Common.Enum; |
| 10 | +using NCC.Common.Extension; | ||
| 10 | using NCC.Common.Filter; | 11 | using NCC.Common.Filter; |
| 11 | using NCC.Dependency; | 12 | using NCC.Dependency; |
| 12 | using NCC.DynamicApiController; | 13 | using NCC.DynamicApiController; |
| 13 | using NCC.Extend.Entitys.Dto.LqMdGeneralManagerLifeline; | 14 | using NCC.Extend.Entitys.Dto.LqMdGeneralManagerLifeline; |
| 15 | +using NCC.Extend.Entitys.Enum; | ||
| 14 | using NCC.Extend.Entitys.lq_md_general_manager_lifeline; | 16 | using NCC.Extend.Entitys.lq_md_general_manager_lifeline; |
| 15 | using NCC.Extend.Entitys.lq_md_target; | 17 | using NCC.Extend.Entitys.lq_md_target; |
| 16 | using NCC.Extend.Interfaces.LqMdGeneralManagerLifeline; | 18 | using NCC.Extend.Interfaces.LqMdGeneralManagerLifeline; |
| @@ -77,6 +79,7 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline | @@ -77,6 +79,7 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline | ||
| 77 | storeId = it.StoreId, | 79 | storeId = it.StoreId, |
| 78 | month = it.Month, | 80 | month = it.Month, |
| 79 | generalManagerId = it.GeneralManagerId, | 81 | generalManagerId = it.GeneralManagerId, |
| 82 | + managerType = it.ManagerType, | ||
| 80 | lifeline1 = it.Lifeline1, | 83 | lifeline1 = it.Lifeline1, |
| 81 | commissionRate1 = it.CommissionRate1, | 84 | commissionRate1 = it.CommissionRate1, |
| 82 | lifeline2 = it.Lifeline2, | 85 | lifeline2 = it.Lifeline2, |
| @@ -92,6 +95,21 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline | @@ -92,6 +95,21 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline | ||
| 92 | .MergeTable() | 95 | .MergeTable() |
| 93 | .OrderBy(sidx + " " + input.sort) | 96 | .OrderBy(sidx + " " + input.sort) |
| 94 | .ToPagedListAsync(input.currentPage, input.pageSize); | 97 | .ToPagedListAsync(input.currentPage, input.pageSize); |
| 98 | + | ||
| 99 | + // 设置经理类型中文名称 | ||
| 100 | + foreach (var item in data.list) | ||
| 101 | + { | ||
| 102 | + if (Enum.IsDefined(typeof(ManagerTypeEnum), item.managerType)) | ||
| 103 | + { | ||
| 104 | + var enumValue = (ManagerTypeEnum)item.managerType; | ||
| 105 | + item.managerTypeName = enumValue.GetDescription(); | ||
| 106 | + } | ||
| 107 | + else | ||
| 108 | + { | ||
| 109 | + item.managerTypeName = string.Empty; | ||
| 110 | + } | ||
| 111 | + } | ||
| 112 | + | ||
| 95 | return PageResult<LqMdGeneralManagerLifelineListOutput>.SqlSugarPageResult(data); | 113 | return PageResult<LqMdGeneralManagerLifelineListOutput>.SqlSugarPageResult(data); |
| 96 | } | 114 | } |
| 97 | #endregion | 115 | #endregion |
| @@ -273,6 +291,7 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline | @@ -273,6 +291,7 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline | ||
| 273 | Id = YitIdHelper.NextId().ToString(), | 291 | Id = YitIdHelper.NextId().ToString(), |
| 274 | StoreId = target.StoreId, | 292 | StoreId = target.StoreId, |
| 275 | Month = target.Month, | 293 | Month = target.Month, |
| 294 | + ManagerType = ManagerTypeEnum.总经理.GetHashCode(), | ||
| 276 | GeneralManagerId = target.BusinessUnitGeneralManager, | 295 | GeneralManagerId = target.BusinessUnitGeneralManager, |
| 277 | Lifeline1 = 0, | 296 | Lifeline1 = 0, |
| 278 | CommissionRate1 = 0, | 297 | CommissionRate1 = 0, |
| @@ -299,14 +318,15 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline | @@ -299,14 +318,15 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline | ||
| 299 | Id = YitIdHelper.NextId().ToString(), | 318 | Id = YitIdHelper.NextId().ToString(), |
| 300 | StoreId = target.StoreId, | 319 | StoreId = target.StoreId, |
| 301 | Month = target.Month, | 320 | Month = target.Month, |
| 321 | + ManagerType = ManagerTypeEnum.经理.GetHashCode(), | ||
| 302 | GeneralManagerId = target.BusinessUnitManager, | 322 | GeneralManagerId = target.BusinessUnitManager, |
| 303 | Lifeline1 = 0, | 323 | Lifeline1 = 0, |
| 304 | CommissionRate1 = 0, | 324 | CommissionRate1 = 0, |
| 305 | - Lifeline2 = null, | ||
| 306 | - CommissionRate2 = null, | ||
| 307 | - Lifeline3 = null, | ||
| 308 | - CommissionRate3 = null, | ||
| 309 | - Remark = null, | 325 | + Lifeline2 = 0, |
| 326 | + CommissionRate2 = 0, | ||
| 327 | + Lifeline3 = 0, | ||
| 328 | + CommissionRate3 = 0, | ||
| 329 | + Remark = "", | ||
| 310 | CreateTime = DateTime.Now, | 330 | CreateTime = DateTime.Now, |
| 311 | CreateUserId = userInfo.userId, | 331 | CreateUserId = userInfo.userId, |
| 312 | }); | 332 | }); |
| @@ -405,6 +425,7 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline | @@ -405,6 +425,7 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline | ||
| 405 | Id = YitIdHelper.NextId().ToString(), | 425 | Id = YitIdHelper.NextId().ToString(), |
| 406 | StoreId = p.StoreId, | 426 | StoreId = p.StoreId, |
| 407 | Month = targetMonthStr, | 427 | Month = targetMonthStr, |
| 428 | + ManagerType = p.ManagerType, | ||
| 408 | GeneralManagerId = p.GeneralManagerId, | 429 | GeneralManagerId = p.GeneralManagerId, |
| 409 | Lifeline1 = p.Lifeline1, | 430 | Lifeline1 = p.Lifeline1, |
| 410 | CommissionRate1 = p.CommissionRate1, | 431 | CommissionRate1 = p.CommissionRate1, |
netcore/src/Modularity/Extend/NCC.Extend/LqPackageInfoService.cs
| @@ -14,6 +14,9 @@ using NCC.Extend.Entitys.Enum; | @@ -14,6 +14,9 @@ using NCC.Extend.Entitys.Enum; | ||
| 14 | using NCC.Extend.Entitys.lq_package_info; | 14 | using NCC.Extend.Entitys.lq_package_info; |
| 15 | using NCC.Extend.Entitys.lq_package_item_detail; | 15 | using NCC.Extend.Entitys.lq_package_item_detail; |
| 16 | using NCC.Extend.Entitys.lq_xmzl; | 16 | using NCC.Extend.Entitys.lq_xmzl; |
| 17 | +using NCC.Extend.Entitys.lq_kd_kdjlb; | ||
| 18 | +using NCC.Extend.Entitys.lq_kd_pxmx; | ||
| 19 | +using NCC.Extend.Entitys.lq_mdxx; | ||
| 17 | using NCC.Extend.Interfaces.LqPackageInfo; | 20 | using NCC.Extend.Interfaces.LqPackageInfo; |
| 18 | using NCC.FriendlyException; | 21 | using NCC.FriendlyException; |
| 19 | using SqlSugar; | 22 | using SqlSugar; |
| @@ -693,5 +696,404 @@ namespace NCC.Extend.LqPackageInfo | @@ -693,5 +696,404 @@ namespace NCC.Extend.LqPackageInfo | ||
| 693 | } | 696 | } |
| 694 | #endregion | 697 | #endregion |
| 695 | 698 | ||
| 699 | + #region 营销活动按门店统计 | ||
| 700 | + /// <summary> | ||
| 701 | + /// 获取营销活动按门店统计数据 | ||
| 702 | + /// </summary> | ||
| 703 | + /// <remarks> | ||
| 704 | + /// 统计指定营销活动在各个门店的开单数据 | ||
| 705 | + /// 包括:开单数量、开单金额、欠款金额、人头数、项目数 | ||
| 706 | + /// | ||
| 707 | + /// 示例请求: | ||
| 708 | + /// ```json | ||
| 709 | + /// { | ||
| 710 | + /// "activityId": "营销活动ID", | ||
| 711 | + /// "startTime": "2025-10-01", | ||
| 712 | + /// "endTime": "2025-10-31", | ||
| 713 | + /// "storeIds": ["门店ID1", "门店ID2"] | ||
| 714 | + /// } | ||
| 715 | + /// ``` | ||
| 716 | + /// | ||
| 717 | + /// 返回字段说明: | ||
| 718 | + /// - ActivityId: 营销活动ID | ||
| 719 | + /// - ActivityName: 营销活动名称 | ||
| 720 | + /// - StoreList: 门店统计列表 | ||
| 721 | + /// - StoreId: 门店ID | ||
| 722 | + /// - StoreName: 门店名称 | ||
| 723 | + /// - BillingCount: 开单数量 | ||
| 724 | + /// - BillingAmount: 开单金额(实付业绩总和) | ||
| 725 | + /// - DebtAmount: 欠款金额 | ||
| 726 | + /// - CustomerCount: 人头数(去重客户数) | ||
| 727 | + /// - ItemCount: 项目数(品项项目次数总和,使用F_ProjectNumber字段) | ||
| 728 | + /// </remarks> | ||
| 729 | + /// <param name="input">查询参数</param> | ||
| 730 | + /// <returns>按门店统计数据</returns> | ||
| 731 | + /// <response code="200">成功返回统计数据</response> | ||
| 732 | + /// <response code="400">参数错误</response> | ||
| 733 | + /// <response code="500">服务器错误</response> | ||
| 734 | + [HttpPost("get-activity-statistics-by-store")] | ||
| 735 | + public async Task<object> GetActivityStatisticsByStore(ActivityStatisticsInput input) | ||
| 736 | + { | ||
| 737 | + try | ||
| 738 | + { | ||
| 739 | + // 1. 获取营销活动信息 | ||
| 740 | + var activity = await _db.Queryable<LqPackageInfoEntity>() | ||
| 741 | + .Where(x => x.Id == input.ActivityId && x.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 742 | + .FirstAsync(); | ||
| 743 | + | ||
| 744 | + if (activity == null) | ||
| 745 | + { | ||
| 746 | + throw NCCException.Oh("营销活动不存在或已失效"); | ||
| 747 | + } | ||
| 748 | + | ||
| 749 | + // 2. 设置时间范围(如果未提供,使用活动时间范围) | ||
| 750 | + var startTime = input.StartTime ?? activity.StartTime; | ||
| 751 | + var endTime = input.EndTime ?? activity.EndTime; | ||
| 752 | + | ||
| 753 | + // 3. 构建基础查询:开单记录 JOIN 门店表 | ||
| 754 | + var baseQuery = _db.Queryable<LqKdKdjlbEntity, LqMdxxEntity>( | ||
| 755 | + (kd, md) => kd.Djmd == md.Id) | ||
| 756 | + .Where((kd, md) => kd.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 757 | + .Where((kd, md) => kd.ActivityId == input.ActivityId) | ||
| 758 | + .Where((kd, md) => kd.Kdrq.HasValue && kd.Kdrq.Value >= startTime && kd.Kdrq.Value <= endTime); | ||
| 759 | + | ||
| 760 | + // 4. 门店筛选 | ||
| 761 | + if (input.StoreIds != null && input.StoreIds.Any()) | ||
| 762 | + { | ||
| 763 | + baseQuery = baseQuery.Where((kd, md) => input.StoreIds.Contains(kd.Djmd)); | ||
| 764 | + } | ||
| 765 | + | ||
| 766 | + // 5. 按门店分组统计(先获取基础统计数据) | ||
| 767 | + var storeStatistics = await baseQuery | ||
| 768 | + .GroupBy((kd, md) => new { StoreId = kd.Djmd, StoreName = md.Dm }) | ||
| 769 | + .Select((kd, md) => new | ||
| 770 | + { | ||
| 771 | + StoreId = kd.Djmd, | ||
| 772 | + StoreName = md.Dm ?? "", | ||
| 773 | + BillingCount = SqlFunc.AggregateCount(kd.Id), | ||
| 774 | + BillingAmount = SqlFunc.AggregateSum(kd.Sfyj), | ||
| 775 | + DebtAmount = SqlFunc.AggregateSum(kd.Qk) | ||
| 776 | + }) | ||
| 777 | + .ToListAsync(); | ||
| 778 | + | ||
| 779 | + // 6. 单独统计每个门店的人头数和项目数 | ||
| 780 | + var storeList = new List<StoreStatisticsItem>(); | ||
| 781 | + foreach (var stat in storeStatistics) | ||
| 782 | + { | ||
| 783 | + // 统计人头数(去重客户数) | ||
| 784 | + var customerCountQuery = _db.Queryable<LqKdKdjlbEntity>() | ||
| 785 | + .Where(kd => kd.Djmd == stat.StoreId | ||
| 786 | + && kd.ActivityId == input.ActivityId | ||
| 787 | + && kd.IsEffective == StatusEnum.有效.GetHashCode() | ||
| 788 | + && kd.Kdrq.HasValue && kd.Kdrq.Value >= startTime && kd.Kdrq.Value <= endTime); | ||
| 789 | + | ||
| 790 | + if (input.StoreIds != null && input.StoreIds.Any()) | ||
| 791 | + { | ||
| 792 | + customerCountQuery = customerCountQuery.Where(kd => input.StoreIds.Contains(kd.Djmd)); | ||
| 793 | + } | ||
| 794 | + | ||
| 795 | + var customerCount = await customerCountQuery | ||
| 796 | + .GroupBy(kd => kd.Kdhy) | ||
| 797 | + .Select(kd => kd.Kdhy) | ||
| 798 | + .CountAsync(); | ||
| 799 | + | ||
| 800 | + // 统计项目数(品项项目次数总和,使用F_ProjectNumber字段) | ||
| 801 | + var itemCountQuery = _db.Queryable<LqKdPxmxEntity, LqKdKdjlbEntity>( | ||
| 802 | + (px, kd) => px.Glkdbh == kd.Id) | ||
| 803 | + .Where((px, kd) => kd.Djmd == stat.StoreId | ||
| 804 | + && px.IsEffective == StatusEnum.有效.GetHashCode() | ||
| 805 | + && kd.IsEffective == StatusEnum.有效.GetHashCode() | ||
| 806 | + && kd.ActivityId == input.ActivityId | ||
| 807 | + && kd.Kdrq.HasValue && kd.Kdrq.Value >= startTime && kd.Kdrq.Value <= endTime); | ||
| 808 | + | ||
| 809 | + if (input.StoreIds != null && input.StoreIds.Any()) | ||
| 810 | + { | ||
| 811 | + itemCountQuery = itemCountQuery.Where((px, kd) => input.StoreIds.Contains(kd.Djmd)); | ||
| 812 | + } | ||
| 813 | + | ||
| 814 | + var itemCount = await itemCountQuery | ||
| 815 | + .Select((px, kd) => SqlFunc.AggregateSum(px.ProjectNumber)) | ||
| 816 | + .FirstAsync(); | ||
| 817 | + | ||
| 818 | + storeList.Add(new StoreStatisticsItem | ||
| 819 | + { | ||
| 820 | + StoreId = stat.StoreId ?? "", | ||
| 821 | + StoreName = stat.StoreName ?? "", | ||
| 822 | + BillingCount = stat.BillingCount, | ||
| 823 | + BillingAmount = stat.BillingAmount, | ||
| 824 | + DebtAmount = stat.DebtAmount, | ||
| 825 | + CustomerCount = customerCount, | ||
| 826 | + ItemCount = itemCount | ||
| 827 | + }); | ||
| 828 | + } | ||
| 829 | + | ||
| 830 | + // 7. 排序 | ||
| 831 | + storeList = storeList.OrderBy(x => x.StoreName).ToList(); | ||
| 832 | + | ||
| 833 | + // 7. 返回统计结果 | ||
| 834 | + return new ActivityStatisticsByStoreOutput | ||
| 835 | + { | ||
| 836 | + ActivityId = input.ActivityId, | ||
| 837 | + ActivityName = activity.ActivityName, | ||
| 838 | + StoreList = storeList | ||
| 839 | + }; | ||
| 840 | + } | ||
| 841 | + catch (Exception ex) | ||
| 842 | + { | ||
| 843 | + throw NCCException.Oh($"获取营销活动按门店统计数据失败: {ex.Message}"); | ||
| 844 | + } | ||
| 845 | + } | ||
| 846 | + #endregion | ||
| 847 | + | ||
| 848 | + #region 营销活动按品项统计 | ||
| 849 | + /// <summary> | ||
| 850 | + /// 获取营销活动按品项统计数据 | ||
| 851 | + /// </summary> | ||
| 852 | + /// <remarks> | ||
| 853 | + /// 统计指定营销活动各个品项的销售情况 | ||
| 854 | + /// 包括:销售数量、销售金额、开单数量、销售次数 | ||
| 855 | + /// | ||
| 856 | + /// 示例请求: | ||
| 857 | + /// ```json | ||
| 858 | + /// { | ||
| 859 | + /// "activityId": "营销活动ID", | ||
| 860 | + /// "startTime": "2025-10-01", | ||
| 861 | + /// "endTime": "2025-10-31" | ||
| 862 | + /// } | ||
| 863 | + /// ``` | ||
| 864 | + /// </remarks> | ||
| 865 | + /// <param name="input">查询参数</param> | ||
| 866 | + /// <returns>按品项统计数据</returns> | ||
| 867 | + /// <response code="200">成功返回统计数据</response> | ||
| 868 | + /// <response code="400">参数错误</response> | ||
| 869 | + /// <response code="500">服务器错误</response> | ||
| 870 | + [HttpPost("get-activity-statistics-by-item")] | ||
| 871 | + public async Task<object> GetActivityStatisticsByItem(ActivityStatisticsInput input) | ||
| 872 | + { | ||
| 873 | + try | ||
| 874 | + { | ||
| 875 | + // 1. 获取营销活动信息 | ||
| 876 | + var activity = await _db.Queryable<LqPackageInfoEntity>() | ||
| 877 | + .Where(x => x.Id == input.ActivityId && x.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 878 | + .FirstAsync(); | ||
| 879 | + | ||
| 880 | + if (activity == null) | ||
| 881 | + { | ||
| 882 | + throw NCCException.Oh("营销活动不存在或已失效"); | ||
| 883 | + } | ||
| 884 | + | ||
| 885 | + // 2. 设置时间范围(如果未提供,使用活动时间范围) | ||
| 886 | + var startTime = input.StartTime ?? activity.StartTime; | ||
| 887 | + var endTime = input.EndTime ?? activity.EndTime; | ||
| 888 | + | ||
| 889 | + // 3. 构建基础查询:品项明细 JOIN 开单记录(用于过滤活动ID和时间) | ||
| 890 | + var baseQuery = _db.Queryable<LqKdPxmxEntity, LqKdKdjlbEntity>( | ||
| 891 | + (px, kd) => px.Glkdbh == kd.Id) | ||
| 892 | + .Where((px, kd) => px.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 893 | + .Where((px, kd) => kd.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 894 | + .Where((px, kd) => kd.ActivityId == input.ActivityId) | ||
| 895 | + .Where((px, kd) => kd.Kdrq.HasValue && kd.Kdrq.Value >= startTime && kd.Kdrq.Value <= endTime); | ||
| 896 | + | ||
| 897 | + // 4. 门店筛选(如果提供) | ||
| 898 | + if (input.StoreIds != null && input.StoreIds.Any()) | ||
| 899 | + { | ||
| 900 | + baseQuery = baseQuery.Where((px, kd) => input.StoreIds.Contains(kd.Djmd)); | ||
| 901 | + } | ||
| 902 | + | ||
| 903 | + // 5. 按品项分组统计(先获取基础统计数据) | ||
| 904 | + var itemStatistics = await baseQuery | ||
| 905 | + .GroupBy((px, kd) => new { ItemId = px.Px, ItemName = px.Pxmc }) | ||
| 906 | + .Select((px, kd) => new | ||
| 907 | + { | ||
| 908 | + ItemId = px.Px ?? "", | ||
| 909 | + ItemName = px.Pxmc ?? "", | ||
| 910 | + SalesQuantity = SqlFunc.AggregateSum(px.ProjectNumber), | ||
| 911 | + SalesAmount = SqlFunc.AggregateSum(px.ActualPrice > 0 ? px.ActualPrice : px.TotalPrice), | ||
| 912 | + SalesCount = SqlFunc.AggregateCount(px.Id) | ||
| 913 | + }) | ||
| 914 | + .ToListAsync(); | ||
| 915 | + | ||
| 916 | + // 6. 单独统计每个品项的开单数量(去重开单ID) | ||
| 917 | + var itemList = new List<ItemStatisticsItem>(); | ||
| 918 | + foreach (var stat in itemStatistics) | ||
| 919 | + { | ||
| 920 | + var billingCountQuery = _db.Queryable<LqKdPxmxEntity, LqKdKdjlbEntity>( | ||
| 921 | + (px, kd) => px.Glkdbh == kd.Id) | ||
| 922 | + .Where((px, kd) => px.Px == stat.ItemId | ||
| 923 | + && px.IsEffective == StatusEnum.有效.GetHashCode() | ||
| 924 | + && kd.IsEffective == StatusEnum.有效.GetHashCode() | ||
| 925 | + && kd.ActivityId == input.ActivityId | ||
| 926 | + && kd.Kdrq.HasValue && kd.Kdrq.Value >= startTime && kd.Kdrq.Value <= endTime); | ||
| 927 | + | ||
| 928 | + if (input.StoreIds != null && input.StoreIds.Any()) | ||
| 929 | + { | ||
| 930 | + billingCountQuery = billingCountQuery.Where((px, kd) => input.StoreIds.Contains(kd.Djmd)); | ||
| 931 | + } | ||
| 932 | + | ||
| 933 | + var billingCount = await billingCountQuery | ||
| 934 | + .GroupBy((px, kd) => px.Glkdbh) | ||
| 935 | + .Select((px, kd) => px.Glkdbh) | ||
| 936 | + .CountAsync(); | ||
| 937 | + | ||
| 938 | + itemList.Add(new ItemStatisticsItem | ||
| 939 | + { | ||
| 940 | + ItemId = stat.ItemId ?? "", | ||
| 941 | + ItemName = stat.ItemName ?? "", | ||
| 942 | + SalesQuantity = stat.SalesQuantity, | ||
| 943 | + SalesAmount = stat.SalesAmount, | ||
| 944 | + BillingCount = billingCount, | ||
| 945 | + SalesCount = stat.SalesCount | ||
| 946 | + }); | ||
| 947 | + } | ||
| 948 | + | ||
| 949 | + // 7. 排序 | ||
| 950 | + itemList = itemList.OrderBy(x => x.ItemName).ToList(); | ||
| 951 | + | ||
| 952 | + // 7. 返回统计结果 | ||
| 953 | + return new ActivityStatisticsByItemOutput | ||
| 954 | + { | ||
| 955 | + ActivityId = input.ActivityId, | ||
| 956 | + ActivityName = activity.ActivityName, | ||
| 957 | + ItemList = itemList | ||
| 958 | + }; | ||
| 959 | + } | ||
| 960 | + catch (Exception ex) | ||
| 961 | + { | ||
| 962 | + throw NCCException.Oh($"获取营销活动按品项统计数据失败: {ex.Message}"); | ||
| 963 | + } | ||
| 964 | + } | ||
| 965 | + #endregion | ||
| 966 | + | ||
| 967 | + #region 营销活动按门店品项统计 | ||
| 968 | + /// <summary> | ||
| 969 | + /// 获取营销活动按门店品项统计数据 | ||
| 970 | + /// </summary> | ||
| 971 | + /// <remarks> | ||
| 972 | + /// 统计指定营销活动在各个门店的各个品项销售情况 | ||
| 973 | + /// 包括:销售数量、销售金额、开单数量、销售次数 | ||
| 974 | + /// | ||
| 975 | + /// 示例请求: | ||
| 976 | + /// ```json | ||
| 977 | + /// { | ||
| 978 | + /// "activityId": "营销活动ID", | ||
| 979 | + /// "startTime": "2025-10-01", | ||
| 980 | + /// "endTime": "2025-10-31", | ||
| 981 | + /// "storeIds": ["门店ID1", "门店ID2"] | ||
| 982 | + /// } | ||
| 983 | + /// ``` | ||
| 984 | + /// </remarks> | ||
| 985 | + /// <param name="input">查询参数</param> | ||
| 986 | + /// <returns>按门店品项统计数据</returns> | ||
| 987 | + /// <response code="200">成功返回统计数据</response> | ||
| 988 | + /// <response code="400">参数错误</response> | ||
| 989 | + /// <response code="500">服务器错误</response> | ||
| 990 | + [HttpPost("get-activity-statistics-by-store-item")] | ||
| 991 | + public async Task<object> GetActivityStatisticsByStoreItem(ActivityStatisticsInput input) | ||
| 992 | + { | ||
| 993 | + try | ||
| 994 | + { | ||
| 995 | + // 1. 获取营销活动信息 | ||
| 996 | + var activity = await _db.Queryable<LqPackageInfoEntity>() | ||
| 997 | + .Where(x => x.Id == input.ActivityId && x.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 998 | + .FirstAsync(); | ||
| 999 | + | ||
| 1000 | + if (activity == null) | ||
| 1001 | + { | ||
| 1002 | + throw NCCException.Oh("营销活动不存在或已失效"); | ||
| 1003 | + } | ||
| 1004 | + | ||
| 1005 | + // 2. 设置时间范围(如果未提供,使用活动时间范围) | ||
| 1006 | + var startTime = input.StartTime ?? activity.StartTime; | ||
| 1007 | + var endTime = input.EndTime ?? activity.EndTime; | ||
| 1008 | + | ||
| 1009 | + // 3. 构建基础查询:品项明细 JOIN 开单记录 JOIN 门店表 | ||
| 1010 | + var baseQuery = _db.Queryable<LqKdPxmxEntity, LqKdKdjlbEntity, LqMdxxEntity>( | ||
| 1011 | + (px, kd, md) => px.Glkdbh == kd.Id && kd.Djmd == md.Id) | ||
| 1012 | + .Where((px, kd, md) => px.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 1013 | + .Where((px, kd, md) => kd.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 1014 | + .Where((px, kd, md) => kd.ActivityId == input.ActivityId) | ||
| 1015 | + .Where((px, kd, md) => kd.Kdrq.HasValue && kd.Kdrq.Value >= startTime && kd.Kdrq.Value <= endTime); | ||
| 1016 | + | ||
| 1017 | + // 4. 门店筛选(如果提供) | ||
| 1018 | + if (input.StoreIds != null && input.StoreIds.Any()) | ||
| 1019 | + { | ||
| 1020 | + baseQuery = baseQuery.Where((px, kd, md) => input.StoreIds.Contains(kd.Djmd)); | ||
| 1021 | + } | ||
| 1022 | + | ||
| 1023 | + // 5. 按门店和品项分组统计(先获取基础统计数据) | ||
| 1024 | + var storeItemStatistics = await baseQuery | ||
| 1025 | + .GroupBy((px, kd, md) => new | ||
| 1026 | + { | ||
| 1027 | + StoreId = kd.Djmd, | ||
| 1028 | + StoreName = md.Dm, | ||
| 1029 | + ItemId = px.Px, | ||
| 1030 | + ItemName = px.Pxmc | ||
| 1031 | + }) | ||
| 1032 | + .Select((px, kd, md) => new | ||
| 1033 | + { | ||
| 1034 | + StoreId = kd.Djmd ?? "", | ||
| 1035 | + StoreName = md.Dm ?? "", | ||
| 1036 | + ItemId = px.Px ?? "", | ||
| 1037 | + ItemName = px.Pxmc ?? "", | ||
| 1038 | + SalesQuantity = SqlFunc.AggregateSum(px.ProjectNumber), | ||
| 1039 | + SalesAmount = SqlFunc.AggregateSum(px.ActualPrice > 0 ? px.ActualPrice : px.TotalPrice), | ||
| 1040 | + SalesCount = SqlFunc.AggregateCount(px.Id) | ||
| 1041 | + }) | ||
| 1042 | + .ToListAsync(); | ||
| 1043 | + | ||
| 1044 | + // 6. 单独统计每个门店品项的开单数量(去重开单ID) | ||
| 1045 | + var storeItemList = new List<StoreItemStatisticsItem>(); | ||
| 1046 | + foreach (var stat in storeItemStatistics) | ||
| 1047 | + { | ||
| 1048 | + var billingCountQuery = _db.Queryable<LqKdPxmxEntity, LqKdKdjlbEntity>( | ||
| 1049 | + (px, kd) => px.Glkdbh == kd.Id) | ||
| 1050 | + .Where((px, kd) => px.Px == stat.ItemId | ||
| 1051 | + && kd.Djmd == stat.StoreId | ||
| 1052 | + && px.IsEffective == StatusEnum.有效.GetHashCode() | ||
| 1053 | + && kd.IsEffective == StatusEnum.有效.GetHashCode() | ||
| 1054 | + && kd.ActivityId == input.ActivityId | ||
| 1055 | + && kd.Kdrq.HasValue && kd.Kdrq.Value >= startTime && kd.Kdrq.Value <= endTime); | ||
| 1056 | + | ||
| 1057 | + if (input.StoreIds != null && input.StoreIds.Any()) | ||
| 1058 | + { | ||
| 1059 | + billingCountQuery = billingCountQuery.Where((px, kd) => input.StoreIds.Contains(kd.Djmd)); | ||
| 1060 | + } | ||
| 1061 | + | ||
| 1062 | + var billingCount = await billingCountQuery | ||
| 1063 | + .GroupBy((px, kd) => px.Glkdbh) | ||
| 1064 | + .Select((px, kd) => px.Glkdbh) | ||
| 1065 | + .CountAsync(); | ||
| 1066 | + | ||
| 1067 | + storeItemList.Add(new StoreItemStatisticsItem | ||
| 1068 | + { | ||
| 1069 | + StoreId = stat.StoreId ?? "", | ||
| 1070 | + StoreName = stat.StoreName ?? "", | ||
| 1071 | + ItemId = stat.ItemId ?? "", | ||
| 1072 | + ItemName = stat.ItemName ?? "", | ||
| 1073 | + SalesQuantity = stat.SalesQuantity, | ||
| 1074 | + SalesAmount = stat.SalesAmount, | ||
| 1075 | + BillingCount = billingCount, | ||
| 1076 | + SalesCount = stat.SalesCount | ||
| 1077 | + }); | ||
| 1078 | + } | ||
| 1079 | + | ||
| 1080 | + // 7. 排序 | ||
| 1081 | + storeItemList = storeItemList.OrderBy(x => x.StoreName).ThenBy(x => x.ItemName).ToList(); | ||
| 1082 | + | ||
| 1083 | + // 7. 返回统计结果 | ||
| 1084 | + return new ActivityStatisticsByStoreItemOutput | ||
| 1085 | + { | ||
| 1086 | + ActivityId = input.ActivityId, | ||
| 1087 | + ActivityName = activity.ActivityName, | ||
| 1088 | + StoreItemList = storeItemList | ||
| 1089 | + }; | ||
| 1090 | + } | ||
| 1091 | + catch (Exception ex) | ||
| 1092 | + { | ||
| 1093 | + throw NCCException.Oh($"获取营销活动按门店品项统计数据失败: {ex.Message}"); | ||
| 1094 | + } | ||
| 1095 | + } | ||
| 1096 | + #endregion | ||
| 1097 | + | ||
| 696 | } | 1098 | } |
| 697 | } | 1099 | } |
netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
| @@ -28,8 +28,11 @@ using NCC.Extend.Entitys.lq_kd_kjbsyj; | @@ -28,8 +28,11 @@ using NCC.Extend.Entitys.lq_kd_kjbsyj; | ||
| 28 | using NCC.Extend.Entitys.lq_mdxx; | 28 | using NCC.Extend.Entitys.lq_mdxx; |
| 29 | using NCC.Extend.Entitys.lq_md_xdbhsj; | 29 | using NCC.Extend.Entitys.lq_md_xdbhsj; |
| 30 | using NCC.Extend.Entitys.lq_xh_kjbsyj; | 30 | using NCC.Extend.Entitys.lq_xh_kjbsyj; |
| 31 | +using NCC.Extend.Entitys.lq_xh_hyhk; | ||
| 32 | +using NCC.Extend.Entitys.lq_xh_pxmx; | ||
| 31 | using NCC.Extend.Entitys.lq_ycsd_jsj; | 33 | using NCC.Extend.Entitys.lq_ycsd_jsj; |
| 32 | using NCC.Extend.Entitys.lq_yjmxb; | 34 | using NCC.Extend.Entitys.lq_yjmxb; |
| 35 | +using NCC.Extend.Entitys.Enum; | ||
| 33 | using NCC.Extend.Entitys.lq_statistics_gold_triangle; | 36 | using NCC.Extend.Entitys.lq_statistics_gold_triangle; |
| 34 | using NCC.Extend.Entitys.lq_statistics_personal_performance; | 37 | using NCC.Extend.Entitys.lq_statistics_personal_performance; |
| 35 | using NCC.Extend.Entitys.lq_statistics_store_consume_performance; | 38 | using NCC.Extend.Entitys.lq_statistics_store_consume_performance; |
| @@ -831,120 +834,183 @@ namespace NCC.Extend.LqStatistics | @@ -831,120 +834,183 @@ namespace NCC.Extend.LqStatistics | ||
| 831 | /// <summary> | 834 | /// <summary> |
| 832 | /// 获取科技部老师业绩统计 | 835 | /// 获取科技部老师业绩统计 |
| 833 | /// </summary> | 836 | /// </summary> |
| 837 | + /// <remarks> | ||
| 838 | + /// 统计科技部老师的开单业绩、消耗业绩、手工费等相关数据 | ||
| 839 | + /// | ||
| 840 | + /// 示例请求: | ||
| 841 | + /// ```json | ||
| 842 | + /// { | ||
| 843 | + /// "startDate": "2025-01-01T00:00:00", | ||
| 844 | + /// "endDate": "2025-01-31T23:59:59", | ||
| 845 | + /// "teacherId": "科技部老师ID(可选)", | ||
| 846 | + /// "teacherName": "科技部老师姓名(可选)" | ||
| 847 | + /// } | ||
| 848 | + /// ``` | ||
| 849 | + /// | ||
| 850 | + /// 参数说明: | ||
| 851 | + /// - startDate: 开始日期(可选) | ||
| 852 | + /// - endDate: 结束日期(可选) | ||
| 853 | + /// - teacherId: 科技部老师ID(可选) | ||
| 854 | + /// - teacherName: 科技部老师姓名(可选) | ||
| 855 | + /// | ||
| 856 | + /// 返回数据说明: | ||
| 857 | + /// - DepartmentName: 部门名称(固定为"科技部") | ||
| 858 | + /// - TeacherName: 老师姓名 | ||
| 859 | + /// - ConsumeProjectCount: 消耗项目数 | ||
| 860 | + /// - ConsumeAchievement: 消耗业绩 | ||
| 861 | + /// - OrderAchievement: 开单业绩(开卡业绩) | ||
| 862 | + /// - OrderItemCount: 开单品项次数 | ||
| 863 | + /// - ConsumeItemCount: 耗卡品项次数 | ||
| 864 | + /// - ConsumeLaborCost: 消耗手工费(耗卡手工费) | ||
| 865 | + /// </remarks> | ||
| 834 | /// <param name="input">查询参数</param> | 866 | /// <param name="input">查询参数</param> |
| 835 | - /// <returns>科技部老师业绩统计结果</returns> | 867 | + /// <returns>科技部老师业绩统计结果列表,包含开单业绩、消耗业绩、手工费等数据</returns> |
| 868 | + /// <response code="200">成功返回统计数据</response> | ||
| 869 | + /// <response code="400">参数错误</response> | ||
| 870 | + /// <response code="500">服务器内部错误</response> | ||
| 836 | [HttpPost("GetTechTeacherStatistics")] | 871 | [HttpPost("GetTechTeacherStatistics")] |
| 837 | [AllowAnonymous] | 872 | [AllowAnonymous] |
| 838 | public async Task<List<TechTeacherSimpleStatisticsOutput>> GetTechTeacherStatistics(TechTeacherStatisticsInput input) | 873 | public async Task<List<TechTeacherSimpleStatisticsOutput>> GetTechTeacherStatistics(TechTeacherStatisticsInput input) |
| 839 | { | 874 | { |
| 840 | try | 875 | try |
| 841 | - { // 1. 从用户表获取所有科技部老师 | ||
| 842 | - var allTeachers = await _db.Queryable<UserEntity>() | ||
| 843 | - .Where(x => x.Gw == "科技老师") | 876 | + { |
| 877 | + // 1. 验证必须传入科技老师ID | ||
| 878 | + if (string.IsNullOrEmpty(input.TeacherId)) | ||
| 879 | + { | ||
| 880 | + return new List<TechTeacherSimpleStatisticsOutput> | ||
| 881 | + { | ||
| 882 | + new TechTeacherSimpleStatisticsOutput | ||
| 883 | + { | ||
| 884 | + DepartmentName = "科技部", | ||
| 885 | + TeacherName = "", | ||
| 886 | + OrderAchievement = 0m, | ||
| 887 | + OrderItemCount = 0, | ||
| 888 | + ConsumeAchievement = 0m, | ||
| 889 | + ConsumeItemCount = 0, | ||
| 890 | + ConsumeProjectCount = 0, | ||
| 891 | + ConsumeLaborCost = 0m, | ||
| 892 | + } | ||
| 893 | + }; | ||
| 894 | + } | ||
| 895 | + | ||
| 896 | + // 2. 获取科技老师信息 | ||
| 897 | + var teacher = await _db.Queryable<UserEntity>() | ||
| 898 | + .Where(x => x.Gw == "科技老师" && x.Id == input.TeacherId) | ||
| 844 | .Select(x => new | 899 | .Select(x => new |
| 845 | { | 900 | { |
| 846 | TeacherId = x.Id, | 901 | TeacherId = x.Id, |
| 847 | TeacherName = x.RealName, | 902 | TeacherName = x.RealName, |
| 848 | TeacherAccount = x.Account, | 903 | TeacherAccount = x.Account, |
| 849 | }) | 904 | }) |
| 850 | - .ToListAsync(); | ||
| 851 | - | ||
| 852 | - // 2. 获取业绩流水数据 | ||
| 853 | - var flowQuery = _db.Queryable<VTechTeacherFlowEntity>(); | 905 | + .FirstAsync(); |
| 854 | 906 | ||
| 855 | - // 老师过滤 | ||
| 856 | - if (!string.IsNullOrEmpty(input.TeacherId)) | 907 | + if (teacher == null) |
| 857 | { | 908 | { |
| 858 | - flowQuery = flowQuery.Where(x => x.TeacherId == input.TeacherId); | 909 | + return new List<TechTeacherSimpleStatisticsOutput> |
| 910 | + { | ||
| 911 | + new TechTeacherSimpleStatisticsOutput | ||
| 912 | + { | ||
| 913 | + DepartmentName = "科技部", | ||
| 914 | + TeacherName = "", | ||
| 915 | + OrderAchievement = 0m, | ||
| 916 | + OrderItemCount = 0, | ||
| 917 | + ConsumeAchievement = 0m, | ||
| 918 | + ConsumeItemCount = 0, | ||
| 919 | + ConsumeProjectCount = 0, | ||
| 920 | + ConsumeLaborCost = 0m, | ||
| 921 | + } | ||
| 922 | + }; | ||
| 859 | } | 923 | } |
| 860 | 924 | ||
| 861 | - if (!string.IsNullOrEmpty(input.TeacherName)) | ||
| 862 | - { | ||
| 863 | - flowQuery = flowQuery.Where(x => x.TeacherName.Contains(input.TeacherName)); | ||
| 864 | - } | 925 | + // 3. 查询开单业绩(从 lq_kd_kjbsyj 关联 lq_kd_kdjlb 和 lq_kd_pxmx) |
| 926 | + var orderQuery = _db.Queryable<LqKdKjbsyjEntity, LqKdKdjlbEntity, LqKdPxmxEntity>( | ||
| 927 | + (kjbsyj, kdjlb, pxmx) => kjbsyj.Glkdbh == kdjlb.Id && kjbsyj.Kdpxid == pxmx.Id) | ||
| 928 | + .Where((kjbsyj, kdjlb, pxmx) => kjbsyj.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 929 | + .Where((kjbsyj, kdjlb, pxmx) => kdjlb.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 930 | + .Where((kjbsyj, kdjlb, pxmx) => kjbsyj.Kjblszh == teacher.TeacherAccount); | ||
| 865 | 931 | ||
| 866 | // 日期过滤 | 932 | // 日期过滤 |
| 867 | if (input.StartDate.HasValue) | 933 | if (input.StartDate.HasValue) |
| 868 | { | 934 | { |
| 869 | - flowQuery = flowQuery.Where(x => x.BusinessDate >= input.StartDate.Value); | 935 | + orderQuery = orderQuery.Where((kjbsyj, kdjlb, pxmx) => kjbsyj.Yjsj >= input.StartDate.Value); |
| 870 | } | 936 | } |
| 871 | 937 | ||
| 872 | if (input.EndDate.HasValue) | 938 | if (input.EndDate.HasValue) |
| 873 | { | 939 | { |
| 874 | - flowQuery = flowQuery.Where(x => x.BusinessDate <= input.EndDate.Value); | 940 | + orderQuery = orderQuery.Where((kjbsyj, kdjlb, pxmx) => kjbsyj.Yjsj <= input.EndDate.Value); |
| 875 | } | 941 | } |
| 876 | 942 | ||
| 877 | - var flowRecords = await flowQuery.ToListAsync(); | ||
| 878 | - | ||
| 879 | - // 3. 按老师分组统计业绩数据 | ||
| 880 | - var teacherStatsDict = flowRecords | ||
| 881 | - .GroupBy(x => new | 943 | + var orderStats = await orderQuery |
| 944 | + .Select((kjbsyj, kdjlb, pxmx) => new | ||
| 882 | { | 945 | { |
| 883 | - x.TeacherId, | ||
| 884 | - x.TeacherName, | ||
| 885 | - x.TeacherAccount, | 946 | + OrderAchievement = SqlFunc.ToDecimal(kjbsyj.Kjblsyj), |
| 947 | + OrderItemCount = SqlFunc.ToInt32(pxmx.ProjectNumber), | ||
| 886 | }) | 948 | }) |
| 887 | - .ToDictionary( | ||
| 888 | - g => g.Key, | ||
| 889 | - g => new | ||
| 890 | - { | ||
| 891 | - ConsumeProjectCount = (int)g.Where(x => x.BusinessType == "耗卡").Sum(x => x.ProjectCount), | ||
| 892 | - ConsumeAchievement = g.Where(x => x.BusinessType == "耗卡").Sum(x => x.Achievement), | ||
| 893 | - OrderAchievement = g.Where(x => x.BusinessType == "开卡").Sum(x => x.Achievement), | ||
| 894 | - OrderItemCount = g.Where(x => x.BusinessType == "开卡").Sum(x => x.ItemCount), | ||
| 895 | - ConsumeItemCount = g.Where(x => x.BusinessType == "耗卡").Sum(x => x.ItemCount), | ||
| 896 | - } | ||
| 897 | - ); | 949 | + .ToListAsync(); |
| 898 | 950 | ||
| 899 | - // 4. 构建结果,包含所有老师 | ||
| 900 | - var result = new List<TechTeacherSimpleStatisticsOutput>(); | 951 | + // 4. 查询耗卡业绩(从 lq_xh_kjbsyj 关联 lq_xh_hyhk 和 lq_xh_pxmx) |
| 952 | + // 注意:lq_xh_kjbsyj.kjbls 字段存储的是健康师id,不是科技部老师id | ||
| 953 | + // 科技部老师信息在 kjblszh(账号)和 kjblsxm(姓名)字段 | ||
| 954 | + var consumeQuery = _db.Queryable<LqXhKjbsyjEntity, LqXhHyhkEntity, LqXhPxmxEntity>( | ||
| 955 | + (kjbsyj, hyhk, pxmx) => kjbsyj.Glkdbh == hyhk.Id && kjbsyj.Hkpxid == pxmx.Id) | ||
| 956 | + .Where((kjbsyj, hyhk, pxmx) => kjbsyj.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 957 | + .Where((kjbsyj, hyhk, pxmx) => hyhk.IsEffective == StatusEnum.有效.GetHashCode()) | ||
| 958 | + .Where((kjbsyj, hyhk, pxmx) => kjbsyj.Kjblszh == teacher.TeacherAccount); | ||
| 901 | 959 | ||
| 902 | - foreach (var teacher in allTeachers) | 960 | + // 日期过滤 |
| 961 | + if (input.StartDate.HasValue) | ||
| 903 | { | 962 | { |
| 904 | - // 应用过滤条件 | ||
| 905 | - if (!string.IsNullOrEmpty(input.TeacherId) && teacher.TeacherId != input.TeacherId) | ||
| 906 | - continue; | ||
| 907 | - | ||
| 908 | - if (!string.IsNullOrEmpty(input.TeacherName) && !teacher.TeacherName.Contains(input.TeacherName)) | ||
| 909 | - continue; | 963 | + consumeQuery = consumeQuery.Where((kjbsyj, hyhk, pxmx) => kjbsyj.Yjsj >= input.StartDate.Value); |
| 964 | + } | ||
| 910 | 965 | ||
| 911 | - var stats = teacherStatsDict.GetValueOrDefault( | ||
| 912 | - new | ||
| 913 | - { | ||
| 914 | - TeacherId = teacher.TeacherId, | ||
| 915 | - TeacherName = teacher.TeacherName, | ||
| 916 | - TeacherAccount = teacher.TeacherAccount, | ||
| 917 | - }, | ||
| 918 | - new | ||
| 919 | - { | ||
| 920 | - ConsumeProjectCount = 0, | ||
| 921 | - ConsumeAchievement = 0m, | ||
| 922 | - OrderAchievement = 0m, | ||
| 923 | - OrderItemCount = 0, | ||
| 924 | - ConsumeItemCount = 0, | ||
| 925 | - } | ||
| 926 | - ); | 966 | + if (input.EndDate.HasValue) |
| 967 | + { | ||
| 968 | + consumeQuery = consumeQuery.Where((kjbsyj, hyhk, pxmx) => kjbsyj.Yjsj <= input.EndDate.Value); | ||
| 969 | + } | ||
| 927 | 970 | ||
| 928 | - var teacherStats = new TechTeacherSimpleStatisticsOutput | 971 | + var consumeStats = await consumeQuery |
| 972 | + .Select((kjbsyj, hyhk, pxmx) => new | ||
| 929 | { | 973 | { |
| 930 | - DepartmentName = "科技部", // 固定为科技部 | ||
| 931 | - TeacherName = teacher.TeacherName, | ||
| 932 | - ConsumeProjectCount = stats.ConsumeProjectCount, | ||
| 933 | - ConsumeAchievement = stats.ConsumeAchievement, | ||
| 934 | - OrderAchievement = stats.OrderAchievement, | ||
| 935 | - OrderItemCount = stats.OrderItemCount, | ||
| 936 | - ConsumeItemCount = stats.ConsumeItemCount, | ||
| 937 | - }; | 974 | + ConsumeAchievement = kjbsyj.Kjblsyj, |
| 975 | + ConsumeItemCount = SqlFunc.ToInt32(pxmx.ProjectNumber), | ||
| 976 | + ConsumeProjectCount = SqlFunc.ToInt32(kjbsyj.HdpxNumber), | ||
| 977 | + ConsumeLaborCost = kjbsyj.LaborCost, | ||
| 978 | + }) | ||
| 979 | + .ToListAsync(); | ||
| 938 | 980 | ||
| 939 | - result.Add(teacherStats); | ||
| 940 | - } | 981 | + // 5. 统计并返回结果 |
| 982 | + var result = new TechTeacherSimpleStatisticsOutput | ||
| 983 | + { | ||
| 984 | + DepartmentName = "科技部", | ||
| 985 | + TeacherName = teacher.TeacherName, | ||
| 986 | + OrderAchievement = orderStats.Sum(x => x.OrderAchievement != null && decimal.TryParse(x.OrderAchievement.ToString(), out var val) ? val : 0m), | ||
| 987 | + OrderItemCount = orderStats.Sum(x => x.OrderItemCount), | ||
| 988 | + ConsumeAchievement = consumeStats.Sum(x => x.ConsumeAchievement ?? 0m), | ||
| 989 | + ConsumeItemCount = consumeStats.Sum(x => x.ConsumeItemCount), | ||
| 990 | + ConsumeProjectCount = consumeStats.Sum(x => x.ConsumeProjectCount), | ||
| 991 | + ConsumeLaborCost = consumeStats.Sum(x => x.ConsumeLaborCost ?? 0m), | ||
| 992 | + }; | ||
| 941 | 993 | ||
| 942 | - return result; | 994 | + return new List<TechTeacherSimpleStatisticsOutput> { result }; |
| 943 | } | 995 | } |
| 944 | catch (Exception ex) | 996 | catch (Exception ex) |
| 945 | { | 997 | { |
| 946 | _logger.LogError(ex, "获取科技部老师业绩统计时发生错误"); | 998 | _logger.LogError(ex, "获取科技部老师业绩统计时发生错误"); |
| 947 | - throw NCCException.Oh("获取科技部老师业绩统计失败", ex); | 999 | + // 发生错误时返回全0的结果,而不是抛出异常 |
| 1000 | + return new List<TechTeacherSimpleStatisticsOutput> | ||
| 1001 | + { | ||
| 1002 | + new TechTeacherSimpleStatisticsOutput | ||
| 1003 | + { | ||
| 1004 | + DepartmentName = "科技部", | ||
| 1005 | + TeacherName = "", | ||
| 1006 | + OrderAchievement = 0m, | ||
| 1007 | + OrderItemCount = 0, | ||
| 1008 | + ConsumeAchievement = 0m, | ||
| 1009 | + ConsumeItemCount = 0, | ||
| 1010 | + ConsumeProjectCount = 0, | ||
| 1011 | + ConsumeLaborCost = 0m, | ||
| 1012 | + } | ||
| 1013 | + }; | ||
| 948 | } | 1014 | } |
| 949 | } | 1015 | } |
| 950 | 1016 | ||
| @@ -3672,6 +3738,5 @@ namespace NCC.Extend.LqStatistics | @@ -3672,6 +3738,5 @@ namespace NCC.Extend.LqStatistics | ||
| 3672 | } | 3738 | } |
| 3673 | 3739 | ||
| 3674 | #endregion | 3740 | #endregion |
| 3675 | - | ||
| 3676 | } | 3741 | } |
| 3677 | } | 3742 | } |
netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
| @@ -1043,12 +1043,18 @@ namespace NCC.Extend.LqXhHyhk | @@ -1043,12 +1043,18 @@ namespace NCC.Extend.LqXhHyhk | ||
| 1043 | Kjblsyj = ikjbs_tem.kjblsyj, | 1043 | Kjblsyj = ikjbs_tem.kjblsyj, |
| 1044 | Yjsj = DateTime.Now, | 1044 | Yjsj = DateTime.Now, |
| 1045 | Hkpxid = lqXhPxmxEntity.Id, | 1045 | Hkpxid = lqXhPxmxEntity.Id, |
| 1046 | + // OriginalHdpxNumber = ikjbs_tem.hdpxNumber, | ||
| 1047 | + // OvertimeHdpxNumber = (decimal)(entity.OvertimeCoefficient * (ikjbs_tem.hdpxNumber ?? 0)), | ||
| 1048 | + // HdpxNumber = (decimal)((ikjbs_tem.hdpxNumber ?? 0) + (entity.OvertimeCoefficient * (ikjbs_tem.hdpxNumber ?? 0))), | ||
| 1046 | OriginalHdpxNumber = ikjbs_tem.hdpxNumber, | 1049 | OriginalHdpxNumber = ikjbs_tem.hdpxNumber, |
| 1047 | - OvertimeHdpxNumber = (decimal)(entity.OvertimeCoefficient * (ikjbs_tem.hdpxNumber ?? 0)), | ||
| 1048 | - HdpxNumber = (decimal)((ikjbs_tem.hdpxNumber ?? 0) + (entity.OvertimeCoefficient * (ikjbs_tem.hdpxNumber ?? 0))), | 1050 | + OvertimeHdpxNumber = 0, |
| 1051 | + HdpxNumber = ikjbs_tem.hdpxNumber, | ||
| 1052 | + // OriginalLaborCost = ikjbs_tem.laborCost, | ||
| 1053 | + // OvertimeLaborCost = (decimal)(entity.OvertimeCoefficient * (ikjbs_tem.laborCost ?? 0)), | ||
| 1054 | + // LaborCost = (decimal)((ikjbs_tem.laborCost ?? 0) + (entity.OvertimeCoefficient * (ikjbs_tem.laborCost ?? 0))), | ||
| 1049 | OriginalLaborCost = ikjbs_tem.laborCost, | 1055 | OriginalLaborCost = ikjbs_tem.laborCost, |
| 1050 | - OvertimeLaborCost = (decimal)(entity.OvertimeCoefficient * (ikjbs_tem.laborCost ?? 0)), | ||
| 1051 | - LaborCost = (decimal)((ikjbs_tem.laborCost ?? 0) + (entity.OvertimeCoefficient * (ikjbs_tem.laborCost ?? 0))), | 1056 | + OvertimeLaborCost = 0, |
| 1057 | + LaborCost = ikjbs_tem.laborCost, | ||
| 1052 | IsEffective = StatusEnum.有效.GetHashCode(), | 1058 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 1053 | } | 1059 | } |
| 1054 | ); | 1060 | ); |
| @@ -1328,12 +1334,18 @@ namespace NCC.Extend.LqXhHyhk | @@ -1328,12 +1334,18 @@ namespace NCC.Extend.LqXhHyhk | ||
| 1328 | Kjblsyj = ikjbs_tem.kjblsyj, | 1334 | Kjblsyj = ikjbs_tem.kjblsyj, |
| 1329 | Yjsj = DateTime.Now, | 1335 | Yjsj = DateTime.Now, |
| 1330 | Hkpxid = lqXhPxmxEntity.Id, | 1336 | Hkpxid = lqXhPxmxEntity.Id, |
| 1337 | + // OriginalHdpxNumber = ikjbs_tem.hdpxNumber, | ||
| 1338 | + // OvertimeHdpxNumber = (decimal)(entity.OvertimeCoefficient * (ikjbs_tem.hdpxNumber ?? 0)), | ||
| 1339 | + // HdpxNumber = (decimal)((ikjbs_tem.hdpxNumber ?? 0) + (entity.OvertimeCoefficient * (ikjbs_tem.hdpxNumber ?? 0))), | ||
| 1340 | + // OriginalLaborCost = ikjbs_tem.laborCost, | ||
| 1341 | + // OvertimeLaborCost = (decimal)(entity.OvertimeCoefficient * (ikjbs_tem.laborCost ?? 0)), | ||
| 1342 | + // LaborCost = (decimal)((ikjbs_tem.laborCost ?? 0) + (entity.OvertimeCoefficient * (ikjbs_tem.laborCost ?? 0))), | ||
| 1331 | OriginalHdpxNumber = ikjbs_tem.hdpxNumber, | 1343 | OriginalHdpxNumber = ikjbs_tem.hdpxNumber, |
| 1332 | - OvertimeHdpxNumber = (decimal)(entity.OvertimeCoefficient * (ikjbs_tem.hdpxNumber ?? 0)), | ||
| 1333 | - HdpxNumber = (decimal)((ikjbs_tem.hdpxNumber ?? 0) + (entity.OvertimeCoefficient * (ikjbs_tem.hdpxNumber ?? 0))), | 1344 | + OvertimeHdpxNumber = 0, |
| 1345 | + HdpxNumber = ikjbs_tem.hdpxNumber, | ||
| 1334 | OriginalLaborCost = ikjbs_tem.laborCost, | 1346 | OriginalLaborCost = ikjbs_tem.laborCost, |
| 1335 | - OvertimeLaborCost = (decimal)(entity.OvertimeCoefficient * (ikjbs_tem.laborCost ?? 0)), | ||
| 1336 | - LaborCost = (decimal)((ikjbs_tem.laborCost ?? 0) + (entity.OvertimeCoefficient * (ikjbs_tem.laborCost ?? 0))), | 1347 | + OvertimeLaborCost = 0, |
| 1348 | + LaborCost = ikjbs_tem.laborCost, | ||
| 1337 | IsEffective = StatusEnum.有效.GetHashCode(), | 1349 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 1338 | }); | 1350 | }); |
| 1339 | } | 1351 | } |
netcore/src/Modularity/Extend/NCC.Extend/LqYaoyjlService.cs
| @@ -93,6 +93,7 @@ namespace NCC.Extend.LqYaoyjl | @@ -93,6 +93,7 @@ namespace NCC.Extend.LqYaoyjl | ||
| 93 | .WhereIF(queryLxsj != null, p => p.Lxsj >= new DateTime(startLxsj.ToDate().Year, startLxsj.ToDate().Month, startLxsj.ToDate().Day, 0, 0, 0)) | 93 | .WhereIF(queryLxsj != null, p => p.Lxsj >= new DateTime(startLxsj.ToDate().Year, startLxsj.ToDate().Month, startLxsj.ToDate().Day, 0, 0, 0)) |
| 94 | .WhereIF(queryLxsj != null, p => p.Lxsj <= new DateTime(endLxsj.ToDate().Year, endLxsj.ToDate().Month, endLxsj.ToDate().Day, 23, 59, 59)) | 94 | .WhereIF(queryLxsj != null, p => p.Lxsj <= new DateTime(endLxsj.ToDate().Year, endLxsj.ToDate().Month, endLxsj.ToDate().Day, 23, 59, 59)) |
| 95 | .WhereIF(!string.IsNullOrEmpty(input.lxjl), p => p.Lxjl.Contains(input.lxjl)) | 95 | .WhereIF(!string.IsNullOrEmpty(input.lxjl), p => p.Lxjl.Contains(input.lxjl)) |
| 96 | + .WhereIF(!string.IsNullOrEmpty(input.storeId), p => p.StoreId.Equals(input.storeId)) | ||
| 96 | .Select(it => new LqYaoyjlListOutput | 97 | .Select(it => new LqYaoyjlListOutput |
| 97 | { | 98 | { |
| 98 | id = it.Id, | 99 | id = it.Id, |
| @@ -158,6 +159,7 @@ namespace NCC.Extend.LqYaoyjl | @@ -158,6 +159,7 @@ namespace NCC.Extend.LqYaoyjl | ||
| 158 | .WhereIF(queryLxsj != null, p => p.Lxsj >= new DateTime(startLxsj.ToDate().Year, startLxsj.ToDate().Month, startLxsj.ToDate().Day, 0, 0, 0)) | 159 | .WhereIF(queryLxsj != null, p => p.Lxsj >= new DateTime(startLxsj.ToDate().Year, startLxsj.ToDate().Month, startLxsj.ToDate().Day, 0, 0, 0)) |
| 159 | .WhereIF(queryLxsj != null, p => p.Lxsj <= new DateTime(endLxsj.ToDate().Year, endLxsj.ToDate().Month, endLxsj.ToDate().Day, 23, 59, 59)) | 160 | .WhereIF(queryLxsj != null, p => p.Lxsj <= new DateTime(endLxsj.ToDate().Year, endLxsj.ToDate().Month, endLxsj.ToDate().Day, 23, 59, 59)) |
| 160 | .WhereIF(!string.IsNullOrEmpty(input.lxjl), p => p.Lxjl.Contains(input.lxjl)) | 161 | .WhereIF(!string.IsNullOrEmpty(input.lxjl), p => p.Lxjl.Contains(input.lxjl)) |
| 162 | + .WhereIF(!string.IsNullOrEmpty(input.storeId), p => p.StoreId.Equals(input.storeId)) | ||
| 161 | .Select(it => new LqYaoyjlListOutput | 163 | .Select(it => new LqYaoyjlListOutput |
| 162 | { | 164 | { |
| 163 | id = it.Id, | 165 | id = it.Id, |
netcore/src/Modularity/Extend/NCC.Extend/Utils/WeChatBotService.cs
| @@ -3,6 +3,7 @@ using System.Net.Http; | @@ -3,6 +3,7 @@ using System.Net.Http; | ||
| 3 | using System.Text; | 3 | using System.Text; |
| 4 | using System.Threading.Tasks; | 4 | using System.Threading.Tasks; |
| 5 | using Newtonsoft.Json; | 5 | using Newtonsoft.Json; |
| 6 | +using NCC; | ||
| 6 | 7 | ||
| 7 | namespace NCC.Extend.Utils | 8 | namespace NCC.Extend.Utils |
| 8 | { | 9 | { |
| @@ -12,17 +13,28 @@ namespace NCC.Extend.Utils | @@ -12,17 +13,28 @@ namespace NCC.Extend.Utils | ||
| 12 | public class WeChatBotService | 13 | public class WeChatBotService |
| 13 | { | 14 | { |
| 14 | private readonly HttpClient _httpClient; | 15 | private readonly HttpClient _httpClient; |
| 15 | - private const string BOT_API_URL = "http://wx.lvqianmeiye.com/api/Bot/send-text"; | ||
| 16 | - //正式地址 | ||
| 17 | - //https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=581c22a6-cb67-42e5-8c76-b8e90052e188 | ||
| 18 | - //测试地址 | ||
| 19 | - //https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=6f8686ec-5011-4c1d-bae9-d82a2a2f4d83 | ||
| 20 | - private const string WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=496f1add-122b-43fc-9e38-0ca79c48b33f"; | ||
| 21 | - private const string WEBHOOK_URL_TEST = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=6f8686ec-5011-4c1d-bae9-d82a2a2f4d83"; | 16 | + private readonly string _botApiUrl; |
| 17 | + private readonly string _webhookUrl; | ||
| 22 | 18 | ||
| 19 | + /// <summary> | ||
| 20 | + /// 初始化企业微信机器人服务 | ||
| 21 | + /// </summary> | ||
| 22 | + /// <param name="httpClient">HTTP客户端</param> | ||
| 23 | public WeChatBotService(HttpClient httpClient) | 23 | public WeChatBotService(HttpClient httpClient) |
| 24 | { | 24 | { |
| 25 | _httpClient = httpClient; | 25 | _httpClient = httpClient; |
| 26 | + | ||
| 27 | + // 从配置文件中读取企业微信机器人配置 | ||
| 28 | + _botApiUrl = App.Configuration["WeChatBot:BotApiUrl"] ?? "http://wx.lvqianmeiye.com/api/Bot/send-text"; | ||
| 29 | + | ||
| 30 | + // 从配置文件中读取Webhook地址(正式或测试地址,通过配置文件切换) | ||
| 31 | + _webhookUrl = App.Configuration["WeChatBot:WebhookUrl"]; | ||
| 32 | + | ||
| 33 | + // 如果配置文件中没有配置,使用默认值 | ||
| 34 | + if (string.IsNullOrEmpty(_webhookUrl)) | ||
| 35 | + { | ||
| 36 | + _webhookUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=496f1add-122b-43fc-9e38-0ca79c48b33f"; | ||
| 37 | + } | ||
| 26 | } | 38 | } |
| 27 | 39 | ||
| 28 | /// <summary> | 40 | /// <summary> |
| @@ -36,8 +48,7 @@ namespace NCC.Extend.Utils | @@ -36,8 +48,7 @@ namespace NCC.Extend.Utils | ||
| 36 | { | 48 | { |
| 37 | var requestData = new | 49 | var requestData = new |
| 38 | { | 50 | { |
| 39 | - webhookUrl = WEBHOOK_URL, | ||
| 40 | - // webhookUrl = WEBHOOK_URL_TEST, | 51 | + webhookUrl = _webhookUrl, |
| 41 | content = content, | 52 | content = content, |
| 42 | mentionedList = (string)null, | 53 | mentionedList = (string)null, |
| 43 | mentionedMobileList = (string)null, | 54 | mentionedMobileList = (string)null, |
| @@ -46,7 +57,7 @@ namespace NCC.Extend.Utils | @@ -46,7 +57,7 @@ namespace NCC.Extend.Utils | ||
| 46 | var json = JsonConvert.SerializeObject(requestData); | 57 | var json = JsonConvert.SerializeObject(requestData); |
| 47 | var httpContent = new StringContent(json, Encoding.UTF8, "application/json"); | 58 | var httpContent = new StringContent(json, Encoding.UTF8, "application/json"); |
| 48 | 59 | ||
| 49 | - var response = await _httpClient.PostAsync(BOT_API_URL, httpContent); | 60 | + var response = await _httpClient.PostAsync(_botApiUrl, httpContent); |
| 50 | 61 | ||
| 51 | if (response.IsSuccessStatusCode) | 62 | if (response.IsSuccessStatusCode) |
| 52 | { | 63 | { |