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 | 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 | 189 | "NCC_App": { |
| 185 | 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 | 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 | 7 | namespace NCC.Extend.Entitys.Dto.LqHytkHytk |
| 4 | 8 | { |
| ... | ... | @@ -102,5 +106,19 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk |
| 102 | 106 | /// </summary> |
| 103 | 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 | 93 | /// </summary> |
| 94 | 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 | 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 | 170 | /// 开单品项明细列表 |
| 171 | 171 | /// </summary> |
| 172 | 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 | 139 | /// </summary> |
| 140 | 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
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/MemberRemainingItemsOutput.cs
| ... | ... | @@ -25,6 +25,7 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk |
| 25 | 25 | public string MemberName { get; set; } |
| 26 | 26 | |
| 27 | 27 | /// <summary> |
| 28 | + /// <summary> | |
| 28 | 29 | /// 剩余品项列表 |
| 29 | 30 | /// </summary> |
| 30 | 31 | /// <remarks>按剩余数量降序排列的品项列表</remarks> |
| ... | ... | @@ -71,6 +72,12 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk |
| 71 | 72 | public string SourceType { get; set; } |
| 72 | 73 | |
| 73 | 74 | /// <summary> |
| 75 | + /// 备注 | |
| 76 | + /// </summary> | |
| 77 | + /// <example>备注</example> | |
| 78 | + public string Remark { get; set; } | |
| 79 | + | |
| 80 | + /// <summary> | |
| 74 | 81 | /// 总购买数量 |
| 75 | 82 | /// </summary> |
| 76 | 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 | 17 | /// |
| 18 | 18 | /// </summary> |
| 19 | 19 | public int dataType { get; set; } |
| 20 | - | |
| 21 | - | |
| 22 | 20 | /// <summary> |
| 23 | 21 | /// 邀约编号 |
| 24 | 22 | /// </summary> |
| 25 | 23 | public string id { get; set; } |
| 26 | - | |
| 24 | + | |
| 27 | 25 | /// <summary> |
| 28 | 26 | /// 邀约人 |
| 29 | 27 | /// </summary> |
| 30 | 28 | public string yyr { get; set; } |
| 31 | - | |
| 29 | + | |
| 32 | 30 | /// <summary> |
| 33 | 31 | /// 邀约时间 |
| 34 | 32 | /// </summary> |
| 35 | 33 | public string yysj { get; set; } |
| 36 | - | |
| 34 | + | |
| 37 | 35 | /// <summary> |
| 38 | 36 | /// 邀约客户 |
| 39 | 37 | /// </summary> |
| 40 | 38 | public string yykh { get; set; } |
| 41 | - | |
| 39 | + | |
| 42 | 40 | /// <summary> |
| 43 | 41 | /// 邀约客户姓名 |
| 44 | 42 | /// </summary> |
| 45 | 43 | public string yykhxm { get; set; } |
| 46 | - | |
| 44 | + | |
| 47 | 45 | /// <summary> |
| 48 | 46 | /// 电话是否有效 |
| 49 | 47 | /// </summary> |
| 50 | 48 | public string dhsfyx { get; set; } |
| 51 | - | |
| 49 | + | |
| 52 | 50 | /// <summary> |
| 53 | 51 | /// 联系时间 |
| 54 | 52 | /// </summary> |
| 55 | 53 | public string lxsj { get; set; } |
| 56 | - | |
| 54 | + | |
| 57 | 55 | /// <summary> |
| 58 | 56 | /// 联系记录 |
| 59 | 57 | /// </summary> |
| 60 | 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 | 28 | public string generalManagerId { get; set; } |
| 29 | 29 | |
| 30 | 30 | /// <summary> |
| 31 | + /// 经理类型(0=经理,1=总经理) | |
| 32 | + /// </summary> | |
| 33 | + [Required(ErrorMessage = "经理类型不能为空")] | |
| 34 | + public int managerType { get; set; } = 1; | |
| 35 | + | |
| 36 | + /// <summary> | |
| 31 | 37 | /// 生命线1 |
| 32 | 38 | /// </summary> |
| 33 | 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 | 28 | public string generalManagerId { get; set; } |
| 29 | 29 | |
| 30 | 30 | /// <summary> |
| 31 | + /// 经理类型(0=经理,1=总经理) | |
| 32 | + /// </summary> | |
| 33 | + public int managerType { get; set; } | |
| 34 | + | |
| 35 | + /// <summary> | |
| 31 | 36 | /// 生命线1 |
| 32 | 37 | /// </summary> |
| 33 | 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 | 28 | public string generalManagerId { get; set; } |
| 29 | 29 | |
| 30 | 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 | 41 | /// 生命线1 |
| 32 | 42 | /// </summary> |
| 33 | 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 | 28 | public string generalManagerId { get; set; } |
| 29 | 29 | |
| 30 | 30 | /// <summary> |
| 31 | + /// 经理类型(0=经理,1=总经理) | |
| 32 | + /// </summary> | |
| 33 | + [Required(ErrorMessage = "经理类型不能为空")] | |
| 34 | + public int managerType { get; set; } = 1; | |
| 35 | + | |
| 36 | + /// <summary> | |
| 31 | 37 | /// 生命线1 |
| 32 | 38 | /// </summary> |
| 33 | 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 | 36 | public string GeneralManagerId { get; set; } |
| 37 | 37 | |
| 38 | 38 | /// <summary> |
| 39 | + /// 经理类型(0=经理,1=总经理) | |
| 40 | + /// </summary> | |
| 41 | + [SugarColumn(ColumnName = "F_ManagerType")] | |
| 42 | + public int ManagerType { get; set; } = 1; | |
| 43 | + | |
| 44 | + /// <summary> | |
| 39 | 45 | /// 生命线1 |
| 40 | 46 | /// </summary> |
| 41 | 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 | 12 | using System; |
| 13 | 13 | using System.Collections.Generic; |
| 14 | 14 | using System.Linq; |
| 15 | +using System.Text; | |
| 15 | 16 | using System.Threading.Tasks; |
| 16 | 17 | using Yitter.IdGenerator; |
| 17 | 18 | using NCC.Common.Helper; |
| ... | ... | @@ -22,6 +23,10 @@ using NCC.DataEncryption; |
| 22 | 23 | using NCC.ClayObject; |
| 23 | 24 | using NCC.Extend.Entitys.Dto.LqDailyReport; |
| 24 | 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 | 30 | using Microsoft.AspNetCore.Authorization; |
| 26 | 31 | |
| 27 | 32 | namespace NCC.Extend |
| ... | ... | @@ -752,7 +757,7 @@ namespace NCC.Extend |
| 752 | 757 | managerFilter = $"AND target.F_GeneralManagerId = '{input.ManagerId}'"; |
| 753 | 758 | } |
| 754 | 759 | |
| 755 | - // SQL查询:获取经理汇总业绩 | |
| 760 | + // SQL查询:获取经理汇总业绩(基于lq_md_general_manager_lifeline表中的经理和门店关系) | |
| 756 | 761 | var sql = $@" |
| 757 | 762 | SELECT |
| 758 | 763 | target.F_GeneralManagerId as ManagerId, |
| ... | ... | @@ -761,7 +766,7 @@ namespace NCC.Extend |
| 761 | 766 | COALESCE(SUM(target.F_Lifeline2), 0) as TotalTarget2, |
| 762 | 767 | COALESCE(SUM(target.F_Lifeline3), 0) as TotalTarget3, |
| 763 | 768 | COUNT(DISTINCT target.F_StoreId) as StoreCount, |
| 764 | - -- 总完成业绩 | |
| 769 | + -- 总完成业绩(基于lq_md_general_manager_lifeline表中的门店关系计算) | |
| 765 | 770 | SUM(COALESCE(( |
| 766 | 771 | SELECT SUM(billing.sfyj) |
| 767 | 772 | FROM lq_kd_kdjlb billing |
| ... | ... | @@ -957,7 +962,267 @@ namespace NCC.Extend |
| 957 | 962 | |
| 958 | 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 | 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 | 70 | /// <summary> |
| 71 | 71 | /// 获取退卡信息列表 |
| 72 | 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 | 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 | 102 | [HttpGet("")] |
| 76 | 103 | public async Task<dynamic> GetList([FromQuery] LqHytkHytkListQueryInput input) |
| 77 | 104 | { |
| ... | ... | @@ -79,7 +106,48 @@ namespace NCC.Extend.LqHytkHytk |
| 79 | 106 | List<string> queryTksj = input.tksj != null ? input.tksj.Split(',').ToObeject<List<string>>() : null; |
| 80 | 107 | DateTime? startTksj = queryTksj != null ? Ext.GetDateTime(queryTksj.First()) : null; |
| 81 | 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 | 151 | .WhereIF(!string.IsNullOrEmpty(input.id), p => p.Id.Contains(input.id)) |
| 84 | 152 | .WhereIF(!string.IsNullOrEmpty(input.md), p => p.Md.Equals(input.md)) |
| 85 | 153 | .WhereIF(!string.IsNullOrEmpty(input.mdbh), p => p.Mdbh.Contains(input.mdbh)) |
| ... | ... | @@ -123,6 +191,104 @@ namespace NCC.Extend.LqHytkHytk |
| 123 | 191 | .MergeTable() |
| 124 | 192 | .OrderBy(sidx + " " + input.sort) |
| 125 | 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 | 292 | return PageResult<LqHytkHytkListOutput>.SqlSugarPageResult(data); |
| 127 | 293 | } |
| 128 | 294 | #endregion | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
| ... | ... | @@ -45,6 +45,7 @@ using Yitter.IdGenerator; |
| 45 | 45 | using NCC.Extend.Entitys.lq_package_info; |
| 46 | 46 | using NCC.Extend.Entitys.lq_mdxx; |
| 47 | 47 | using NCC.Extend.Entitys.lq_card_transfer_log; |
| 48 | +using NCC.Extend.Entitys.Dto.LqDailyReport; | |
| 48 | 49 | |
| 49 | 50 | namespace NCC.Extend.LqKdKdjlb |
| 50 | 51 | { |
| ... | ... | @@ -64,6 +65,7 @@ namespace NCC.Extend.LqKdKdjlb |
| 64 | 65 | private readonly WeChatBotService _weChatBotService; |
| 65 | 66 | private readonly LqKdKdjlbStringGenerator _stringGenerator; |
| 66 | 67 | private readonly ILogger<LqKdKdjlbService> _logger; |
| 68 | + private readonly LqDailyReportService _dailyReportService; | |
| 67 | 69 | |
| 68 | 70 | /// <summary> |
| 69 | 71 | /// 初始化一个<see cref="LqKdKdjlbService"/>类型的新实例 |
| ... | ... | @@ -76,7 +78,8 @@ namespace NCC.Extend.LqKdKdjlb |
| 76 | 78 | IUserManager userManager, |
| 77 | 79 | WeChatBotService weChatBotService, |
| 78 | 80 | LqKdKdjlbStringGenerator stringGenerator, |
| 79 | - ILogger<LqKdKdjlbService> logger | |
| 81 | + ILogger<LqKdKdjlbService> logger, | |
| 82 | + LqDailyReportService dailyReportService | |
| 80 | 83 | ) |
| 81 | 84 | { |
| 82 | 85 | _lqKdKdjlbRepository = lqKdKdjlbRepository; |
| ... | ... | @@ -88,6 +91,7 @@ namespace NCC.Extend.LqKdKdjlb |
| 88 | 91 | _weChatBotService = weChatBotService; |
| 89 | 92 | _stringGenerator = stringGenerator; |
| 90 | 93 | _logger = logger; |
| 94 | + _dailyReportService = dailyReportService; | |
| 91 | 95 | } |
| 92 | 96 | |
| 93 | 97 | #region 获取开单记录表 |
| ... | ... | @@ -214,8 +218,49 @@ namespace NCC.Extend.LqKdKdjlb |
| 214 | 218 | List<string> queryKdrq = input.kdrq != null ? input.kdrq.Split(',').ToObeject<List<string>>() : null; |
| 215 | 219 | DateTime? startKdrq = queryKdrq != null ? Ext.GetDateTime(queryKdrq.First()) : null; |
| 216 | 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 | 264 | .WhereIF(!string.IsNullOrEmpty(input.id), p => p.Id.Contains(input.id)) |
| 220 | 265 | .WhereIF(!string.IsNullOrEmpty(input.djmd), p => p.Djmd.Equals(input.djmd)) |
| 221 | 266 | .WhereIF(!string.IsNullOrEmpty(input.jsj), p => p.Jsj.Equals(input.jsj)) |
| ... | ... | @@ -308,18 +353,380 @@ namespace NCC.Extend.LqKdKdjlb |
| 308 | 353 | var itemDetailsGrouped = itemDetails.GroupBy(x => x.glkdbh) |
| 309 | 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 | 408 | foreach (var item in data.list) |
| 313 | 409 | { |
| 314 | 410 | item.ItemDetails = itemDetailsGrouped.ContainsKey(item.id) |
| 315 | 411 | ? itemDetailsGrouped[item.id] |
| 316 | 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 | 421 | return PageResult<LqKdKdjlbListOutput>.SqlSugarPageResult(data); |
| 320 | 422 | } |
| 321 | 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 | 730 | #region 新建开单记录表 |
| 324 | 731 | /// <summary> |
| 325 | 732 | /// 新建开单记录表 |
| ... | ... | @@ -563,6 +970,47 @@ namespace NCC.Extend.LqKdKdjlb |
| 563 | 970 | // 字符串生成失败不影响主流程,只记录日志 |
| 564 | 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 | 1015 | catch (Exception ex) |
| 568 | 1016 | { | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
| ... | ... | @@ -551,7 +551,8 @@ namespace NCC.Extend.LqKhxx |
| 551 | 551 | x.Pxmc, |
| 552 | 552 | x.Pxjg, |
| 553 | 553 | x.SourceType, |
| 554 | - x.ProjectNumber | |
| 554 | + x.ProjectNumber, | |
| 555 | + x.Remark | |
| 555 | 556 | }) |
| 556 | 557 | .ToListAsync(); |
| 557 | 558 | |
| ... | ... | @@ -600,6 +601,7 @@ namespace NCC.Extend.LqKhxx |
| 600 | 601 | ItemPrice = item.Pxjg, |
| 601 | 602 | SourceType = item.SourceType, |
| 602 | 603 | TotalPurchased = item.ProjectNumber, |
| 604 | + Remark = item.Remark, | |
| 603 | 605 | ConsumedCount = consumedData.FirstOrDefault(c => c.BillingItemId == item.Id)?.TotalConsumed ?? 0, |
| 604 | 606 | RefundedCount = refundedData.FirstOrDefault(r => r.BillingItemId == item.Id)?.TotalRefunded ?? 0, |
| 605 | 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 | 7 | using Microsoft.AspNetCore.Mvc; |
| 8 | 8 | using NCC.Common.Core.Manager; |
| 9 | 9 | using NCC.Common.Enum; |
| 10 | +using NCC.Common.Extension; | |
| 10 | 11 | using NCC.Common.Filter; |
| 11 | 12 | using NCC.Dependency; |
| 12 | 13 | using NCC.DynamicApiController; |
| 13 | 14 | using NCC.Extend.Entitys.Dto.LqMdGeneralManagerLifeline; |
| 15 | +using NCC.Extend.Entitys.Enum; | |
| 14 | 16 | using NCC.Extend.Entitys.lq_md_general_manager_lifeline; |
| 15 | 17 | using NCC.Extend.Entitys.lq_md_target; |
| 16 | 18 | using NCC.Extend.Interfaces.LqMdGeneralManagerLifeline; |
| ... | ... | @@ -77,6 +79,7 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline |
| 77 | 79 | storeId = it.StoreId, |
| 78 | 80 | month = it.Month, |
| 79 | 81 | generalManagerId = it.GeneralManagerId, |
| 82 | + managerType = it.ManagerType, | |
| 80 | 83 | lifeline1 = it.Lifeline1, |
| 81 | 84 | commissionRate1 = it.CommissionRate1, |
| 82 | 85 | lifeline2 = it.Lifeline2, |
| ... | ... | @@ -92,6 +95,21 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline |
| 92 | 95 | .MergeTable() |
| 93 | 96 | .OrderBy(sidx + " " + input.sort) |
| 94 | 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 | 113 | return PageResult<LqMdGeneralManagerLifelineListOutput>.SqlSugarPageResult(data); |
| 96 | 114 | } |
| 97 | 115 | #endregion |
| ... | ... | @@ -273,6 +291,7 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline |
| 273 | 291 | Id = YitIdHelper.NextId().ToString(), |
| 274 | 292 | StoreId = target.StoreId, |
| 275 | 293 | Month = target.Month, |
| 294 | + ManagerType = ManagerTypeEnum.总经理.GetHashCode(), | |
| 276 | 295 | GeneralManagerId = target.BusinessUnitGeneralManager, |
| 277 | 296 | Lifeline1 = 0, |
| 278 | 297 | CommissionRate1 = 0, |
| ... | ... | @@ -299,14 +318,15 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline |
| 299 | 318 | Id = YitIdHelper.NextId().ToString(), |
| 300 | 319 | StoreId = target.StoreId, |
| 301 | 320 | Month = target.Month, |
| 321 | + ManagerType = ManagerTypeEnum.经理.GetHashCode(), | |
| 302 | 322 | GeneralManagerId = target.BusinessUnitManager, |
| 303 | 323 | Lifeline1 = 0, |
| 304 | 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 | 330 | CreateTime = DateTime.Now, |
| 311 | 331 | CreateUserId = userInfo.userId, |
| 312 | 332 | }); |
| ... | ... | @@ -405,6 +425,7 @@ namespace NCC.Extend.LqMdGeneralManagerLifeline |
| 405 | 425 | Id = YitIdHelper.NextId().ToString(), |
| 406 | 426 | StoreId = p.StoreId, |
| 407 | 427 | Month = targetMonthStr, |
| 428 | + ManagerType = p.ManagerType, | |
| 408 | 429 | GeneralManagerId = p.GeneralManagerId, |
| 409 | 430 | Lifeline1 = p.Lifeline1, |
| 410 | 431 | CommissionRate1 = p.CommissionRate1, | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqPackageInfoService.cs
| ... | ... | @@ -14,6 +14,9 @@ using NCC.Extend.Entitys.Enum; |
| 14 | 14 | using NCC.Extend.Entitys.lq_package_info; |
| 15 | 15 | using NCC.Extend.Entitys.lq_package_item_detail; |
| 16 | 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 | 20 | using NCC.Extend.Interfaces.LqPackageInfo; |
| 18 | 21 | using NCC.FriendlyException; |
| 19 | 22 | using SqlSugar; |
| ... | ... | @@ -693,5 +696,404 @@ namespace NCC.Extend.LqPackageInfo |
| 693 | 696 | } |
| 694 | 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 | 28 | using NCC.Extend.Entitys.lq_mdxx; |
| 29 | 29 | using NCC.Extend.Entitys.lq_md_xdbhsj; |
| 30 | 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 | 33 | using NCC.Extend.Entitys.lq_ycsd_jsj; |
| 32 | 34 | using NCC.Extend.Entitys.lq_yjmxb; |
| 35 | +using NCC.Extend.Entitys.Enum; | |
| 33 | 36 | using NCC.Extend.Entitys.lq_statistics_gold_triangle; |
| 34 | 37 | using NCC.Extend.Entitys.lq_statistics_personal_performance; |
| 35 | 38 | using NCC.Extend.Entitys.lq_statistics_store_consume_performance; |
| ... | ... | @@ -831,120 +834,183 @@ namespace NCC.Extend.LqStatistics |
| 831 | 834 | /// <summary> |
| 832 | 835 | /// 获取科技部老师业绩统计 |
| 833 | 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 | 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 | 871 | [HttpPost("GetTechTeacherStatistics")] |
| 837 | 872 | [AllowAnonymous] |
| 838 | 873 | public async Task<List<TechTeacherSimpleStatisticsOutput>> GetTechTeacherStatistics(TechTeacherStatisticsInput input) |
| 839 | 874 | { |
| 840 | 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 | 899 | .Select(x => new |
| 845 | 900 | { |
| 846 | 901 | TeacherId = x.Id, |
| 847 | 902 | TeacherName = x.RealName, |
| 848 | 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 | 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 | 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 | 996 | catch (Exception ex) |
| 945 | 997 | { |
| 946 | 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 | 3738 | } |
| 3673 | 3739 | |
| 3674 | 3740 | #endregion |
| 3675 | - | |
| 3676 | 3741 | } |
| 3677 | 3742 | } | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
| ... | ... | @@ -1043,12 +1043,18 @@ namespace NCC.Extend.LqXhHyhk |
| 1043 | 1043 | Kjblsyj = ikjbs_tem.kjblsyj, |
| 1044 | 1044 | Yjsj = DateTime.Now, |
| 1045 | 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 | 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 | 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 | 1058 | IsEffective = StatusEnum.有效.GetHashCode(), |
| 1053 | 1059 | } |
| 1054 | 1060 | ); |
| ... | ... | @@ -1328,12 +1334,18 @@ namespace NCC.Extend.LqXhHyhk |
| 1328 | 1334 | Kjblsyj = ikjbs_tem.kjblsyj, |
| 1329 | 1335 | Yjsj = DateTime.Now, |
| 1330 | 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 | 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 | 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 | 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 | 93 | .WhereIF(queryLxsj != null, p => p.Lxsj >= new DateTime(startLxsj.ToDate().Year, startLxsj.ToDate().Month, startLxsj.ToDate().Day, 0, 0, 0)) |
| 94 | 94 | .WhereIF(queryLxsj != null, p => p.Lxsj <= new DateTime(endLxsj.ToDate().Year, endLxsj.ToDate().Month, endLxsj.ToDate().Day, 23, 59, 59)) |
| 95 | 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 | 97 | .Select(it => new LqYaoyjlListOutput |
| 97 | 98 | { |
| 98 | 99 | id = it.Id, |
| ... | ... | @@ -158,6 +159,7 @@ namespace NCC.Extend.LqYaoyjl |
| 158 | 159 | .WhereIF(queryLxsj != null, p => p.Lxsj >= new DateTime(startLxsj.ToDate().Year, startLxsj.ToDate().Month, startLxsj.ToDate().Day, 0, 0, 0)) |
| 159 | 160 | .WhereIF(queryLxsj != null, p => p.Lxsj <= new DateTime(endLxsj.ToDate().Year, endLxsj.ToDate().Month, endLxsj.ToDate().Day, 23, 59, 59)) |
| 160 | 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 | 163 | .Select(it => new LqYaoyjlListOutput |
| 162 | 164 | { |
| 163 | 165 | id = it.Id, | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/Utils/WeChatBotService.cs
| ... | ... | @@ -3,6 +3,7 @@ using System.Net.Http; |
| 3 | 3 | using System.Text; |
| 4 | 4 | using System.Threading.Tasks; |
| 5 | 5 | using Newtonsoft.Json; |
| 6 | +using NCC; | |
| 6 | 7 | |
| 7 | 8 | namespace NCC.Extend.Utils |
| 8 | 9 | { |
| ... | ... | @@ -12,17 +13,28 @@ namespace NCC.Extend.Utils |
| 12 | 13 | public class WeChatBotService |
| 13 | 14 | { |
| 14 | 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 | 23 | public WeChatBotService(HttpClient httpClient) |
| 24 | 24 | { |
| 25 | 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 | 40 | /// <summary> |
| ... | ... | @@ -36,8 +48,7 @@ namespace NCC.Extend.Utils |
| 36 | 48 | { |
| 37 | 49 | var requestData = new |
| 38 | 50 | { |
| 39 | - webhookUrl = WEBHOOK_URL, | |
| 40 | - // webhookUrl = WEBHOOK_URL_TEST, | |
| 51 | + webhookUrl = _webhookUrl, | |
| 41 | 52 | content = content, |
| 42 | 53 | mentionedList = (string)null, |
| 43 | 54 | mentionedMobileList = (string)null, |
| ... | ... | @@ -46,7 +57,7 @@ namespace NCC.Extend.Utils |
| 46 | 57 | var json = JsonConvert.SerializeObject(requestData); |
| 47 | 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 | 62 | if (response.IsSuccessStatusCode) |
| 52 | 63 | { | ... | ... |