Commit e96beca8aecd10686f265a2aa8c9d398e866b95f
1 parent
87aea27c
更新多个.DS_Store文件,删除不再使用的SQL视图文件,重构LqStatisticsService和WeChatBotService,新增门店开单业绩统计…
…和科技部老师业绩统计功能,优化查询逻辑和代码结构,确保代码整洁性和功能完整性。
Showing
17 changed files
with
1152 additions
and
303 deletions
.DS_Store
No preview for this file type
[已用]创建科技部老师业绩统计视图.sql
0 → 100644
| 1 | +-- 创建科技部老师业绩流水视图 | |
| 2 | +-- 包含所有业务类型的流水记录,并包含对应的信息表ID和品项次数 | |
| 3 | + | |
| 4 | +CREATE OR REPLACE VIEW v_tech_teacher_flow AS | |
| 5 | +SELECT | |
| 6 | + teacher_id, | |
| 7 | + teacher_name, | |
| 8 | + teacher_account, | |
| 9 | + business_type, | |
| 10 | + achievement, | |
| 11 | + labor_cost, | |
| 12 | + project_count, | |
| 13 | + customer_id, | |
| 14 | + customer_name, | |
| 15 | + business_date, | |
| 16 | + source_id, | |
| 17 | + source_table, | |
| 18 | + item_count | |
| 19 | +FROM ( | |
| 20 | + -- 开卡流水 | |
| 21 | + SELECT | |
| 22 | + k.kjbls as teacher_id, | |
| 23 | + k.kjblsxm as teacher_name, | |
| 24 | + k.kjblszh as teacher_account, | |
| 25 | + '开卡' as business_type, | |
| 26 | + CAST(COALESCE(k.kjblsyj, 0) AS DECIMAL(10,2)) as achievement, | |
| 27 | + CAST(COALESCE(k.F_LaborCost, 0) AS DECIMAL(10,2)) as labor_cost, | |
| 28 | + CAST(COALESCE(pm.F_ProjectNumber, 0) AS DECIMAL(10,2)) as project_count, | |
| 29 | + o.kdhy as customer_id, | |
| 30 | + o.kdhyc as customer_name, | |
| 31 | + k.yjsj as business_date, | |
| 32 | + k.F_kdpxid as source_id, | |
| 33 | + 'lq_kd_pxmx' as source_table, | |
| 34 | + COALESCE(pm.F_ProjectNumber, 0) as item_count | |
| 35 | + FROM lq_kd_kjbsyj k | |
| 36 | + LEFT JOIN lq_kd_kdjlb o ON k.glkdbh = o.F_Id | |
| 37 | + LEFT JOIN lq_kd_pxmx pm ON k.F_kdpxid = pm.F_Id | |
| 38 | + WHERE k.kjbls IS NOT NULL AND k.kjblsxm IS NOT NULL | |
| 39 | + | |
| 40 | + UNION ALL | |
| 41 | + | |
| 42 | + -- 耗卡流水 | |
| 43 | + SELECT | |
| 44 | + x.kjbls as teacher_id, | |
| 45 | + x.kjblsxm as teacher_name, | |
| 46 | + x.kjblszh as teacher_account, | |
| 47 | + '耗卡' as business_type, | |
| 48 | + CAST(COALESCE(x.kjblsyj, 0) AS DECIMAL(10,2)) as achievement, | |
| 49 | + CAST(COALESCE(x.F_LaborCost, 0) AS DECIMAL(10,2)) as labor_cost, | |
| 50 | + CAST(COALESCE(pm.F_ProjectNumber, 0) AS DECIMAL(10,2)) as project_count, | |
| 51 | + h.hy as customer_id, | |
| 52 | + h.hymc as customer_name, | |
| 53 | + x.yjsj as business_date, | |
| 54 | + x.F_hkpxid as source_id, | |
| 55 | + 'lq_xh_pxmx' as source_table, | |
| 56 | + COALESCE(pm.F_ProjectNumber, 0) as item_count | |
| 57 | + FROM lq_xh_kjbsyj x | |
| 58 | + LEFT JOIN lq_xh_hyhk h ON x.glkdbh = h.F_Id | |
| 59 | + LEFT JOIN lq_xh_pxmx pm ON x.F_hkpxid = pm.F_Id | |
| 60 | + WHERE x.kjbls IS NOT NULL AND x.kjblsxm IS NOT NULL | |
| 61 | + | |
| 62 | + UNION ALL | |
| 63 | + | |
| 64 | + -- 退卡流水 | |
| 65 | + SELECT | |
| 66 | + r.kjbls as teacher_id, | |
| 67 | + r.kjblsxm as teacher_name, | |
| 68 | + r.kjblszh as teacher_account, | |
| 69 | + '退卡' as business_type, | |
| 70 | + CAST(COALESCE(r.kjblsyj, 0) AS DECIMAL(10,2)) as achievement, | |
| 71 | + CAST(COALESCE(r.F_LaborCost, 0) AS DECIMAL(10,2)) as labor_cost, | |
| 72 | + CAST(COALESCE(r.F_tkpxNumber, 0) AS DECIMAL(10,2)) as project_count, | |
| 73 | + t.hy as customer_id, | |
| 74 | + t.hymc as customer_name, | |
| 75 | + r.tksj as business_date, | |
| 76 | + r.F_Id as source_id, | |
| 77 | + 'lq_hytk_kjbsyj' as source_table, | |
| 78 | + 0 as item_count | |
| 79 | + FROM lq_hytk_kjbsyj r | |
| 80 | + LEFT JOIN lq_hytk_hytk t ON r.gltkbh = t.F_Id | |
| 81 | + WHERE r.kjbls IS NOT NULL AND r.kjblsxm IS NOT NULL AND (r.F_DeleteMark IS NULL OR r.F_DeleteMark = 0) | |
| 82 | +) t; | |
| 83 | + | |
| 84 | + | ... | ... |
[已用]创建门店耗卡业绩统计视图.sql
0 → 100644
| 1 | +-- ============================================= | |
| 2 | +-- 门店耗卡业绩统计视图创建脚本 | |
| 3 | +-- 功能:统计所有门店的目标业绩、耗卡业绩、完成率等关键指标 | |
| 4 | +-- 作者:系统自动生成 | |
| 5 | +-- 创建时间:2025年 | |
| 6 | +-- ============================================= | |
| 7 | + | |
| 8 | +-- 先删除视图(如果存在) | |
| 9 | +DROP VIEW IF EXISTS v_store_consume_performance_simple; | |
| 10 | + | |
| 11 | +-- ============================================= | |
| 12 | +-- 创建门店耗卡业绩统计视图(当月数据) | |
| 13 | +-- ============================================= | |
| 14 | +CREATE VIEW v_store_consume_performance_simple AS | |
| 15 | +SELECT | |
| 16 | + `md`.`F_Id` AS `store_id`, | |
| 17 | + `md`.`djmd` AS `store_code`, | |
| 18 | + `md`.`dm` AS `store_name`, | |
| 19 | + COALESCE(`md`.`xsyj`, 0) AS `target_performance`, | |
| 20 | + COALESCE(`consume`.`consume_performance`, 0) AS `actual_performance`, | |
| 21 | + ( | |
| 22 | + CASE | |
| 23 | + WHEN (COALESCE(`md`.`xsyj`, 0) > 0) THEN | |
| 24 | + round( | |
| 25 | + ( | |
| 26 | + ( | |
| 27 | + COALESCE(`consume`.`consume_performance`, 0) / `md`.`xsyj` | |
| 28 | + ) * 100 | |
| 29 | + ), | |
| 30 | + 2 | |
| 31 | + ) ELSE 0 | |
| 32 | + END | |
| 33 | + ) AS `completion_rate`, | |
| 34 | + COALESCE(`consume`.`consume_count`, 0) AS `order_count` | |
| 35 | + FROM | |
| 36 | + ( | |
| 37 | + `lqerp`.`lq_mdxx` `md` | |
| 38 | + LEFT JOIN ( | |
| 39 | + SELECT | |
| 40 | + `hk`.`md` AS `md`, | |
| 41 | + sum(COALESCE(`px`.`F_TotalPrice`, 0)) AS `consume_performance`, | |
| 42 | + count(DISTINCT `hk`.`F_Id`) AS `consume_count` | |
| 43 | + FROM | |
| 44 | + ( | |
| 45 | + `lqerp`.`lq_xh_hyhk` `hk` | |
| 46 | + LEFT JOIN `lqerp`.`lq_xh_pxmx` `px` ON ((`hk`.`F_Id` = `px`.`glkdbh`)) | |
| 47 | + ) | |
| 48 | + WHERE | |
| 49 | + ( | |
| 50 | + ( | |
| 51 | + YEAR(`hk`.`hksj`) = YEAR(curdate()) | |
| 52 | + ) | |
| 53 | + AND ( | |
| 54 | + MONTH(`hk`.`hksj`) = MONTH(curdate()) | |
| 55 | + ) | |
| 56 | + AND ( | |
| 57 | + isnull(`px`.`F_CreateTIme`) | |
| 58 | + OR ( | |
| 59 | + ( | |
| 60 | + YEAR(`px`.`F_CreateTIme`) = YEAR(curdate()) | |
| 61 | + ) | |
| 62 | + AND ( | |
| 63 | + MONTH(`px`.`F_CreateTIme`) = MONTH(curdate()) | |
| 64 | + ) | |
| 65 | + ) | |
| 66 | + ) | |
| 67 | + ) | |
| 68 | + GROUP BY | |
| 69 | + `hk`.`md` | |
| 70 | + ) `consume` ON ((`md`.`F_Id` = `consume`.`md`)) | |
| 71 | + ) | |
| 72 | + ORDER BY | |
| 73 | + COALESCE(`consume`.`consume_performance`, 0) DESC; | |
| 74 | + | |
| 75 | +-- ============================================= | |
| 76 | +-- 添加视图注释 | |
| 77 | +-- ============================================= | |
| 78 | +ALTER VIEW v_store_consume_performance_simple COMMENT = '门店耗卡业绩统计视图(当月数据)- 统计所有门店的目标业绩、耗卡业绩、完成率等关键指标'; | |
| 79 | + | |
| 80 | +-- ============================================= | |
| 81 | +-- 视图字段说明 | |
| 82 | +-- ============================================= | |
| 83 | +/* | |
| 84 | +字段说明: | |
| 85 | +- store_id: 门店ID(来自lq_mdxx.F_Id) | |
| 86 | +- store_code: 门店编码(来自lq_mdxx.djmd) | |
| 87 | +- store_name: 店名(来自lq_mdxx.dm) | |
| 88 | +- target_performance: 目标业绩/生命线(来自lq_mdxx.xsyj) | |
| 89 | +- actual_performance: 耗卡业绩(来自lq_xh_pxmx.F_TotalPrice的汇总) | |
| 90 | +- completion_rate: 完成率百分比(actual_performance / target_performance * 100) | |
| 91 | +- order_count: 耗卡记录数(有效耗卡记录数) | |
| 92 | + | |
| 93 | +关联说明: | |
| 94 | +- 主表:lq_mdxx(门店信息表) | |
| 95 | +- 关联表:lq_xh_hyhk(耗卡记录表)+ lq_xh_pxmx(耗卡品项表) | |
| 96 | +- 关联条件:lq_mdxx.F_Id = lq_xh_hyhk.md, lq_xh_hyhk.F_Id = lq_xh_pxmx.glkdbh | |
| 97 | +- 关联方式:LEFT JOIN(确保所有门店都显示,包括没有耗卡记录的门店) | |
| 98 | + | |
| 99 | +数据来源: | |
| 100 | +- 目标业绩:lq_mdxx.xsyj(目标-门店生命线) | |
| 101 | +- 耗卡业绩:lq_xh_pxmx.F_TotalPrice(金额合计) | |
| 102 | +- 耗卡记录数:lq_xh_hyhk表记录数统计 | |
| 103 | + | |
| 104 | +时间过滤: | |
| 105 | +- 耗卡日期:lq_xh_hyhk.hksj(当月) | |
| 106 | +- 品项创建时间:lq_xh_pxmx.F_CreateTIme(当月) | |
| 107 | + | |
| 108 | +注意事项: | |
| 109 | +1. 使用金额合计(F_TotalPrice)而不是品项价格(pxjg) | |
| 110 | +2. 只统计当月的数据(耗卡日期和品项创建时间都是当月) | |
| 111 | +3. 即使目标业绩、耗卡业绩为0的门店也会显示 | |
| 112 | +4. 完成率计算时,目标业绩为0的门店显示0%完成率 | |
| 113 | +5. 按耗卡业绩降序排列,便于查看业绩排名 | |
| 114 | +6. 确保耗卡品项也是当月创建的,避免历史数据干扰 | |
| 115 | +*/ | |
| 116 | + | |
| 117 | +-- ============================================= | |
| 118 | +-- 使用示例 | |
| 119 | +-- ============================================= | |
| 120 | +/* | |
| 121 | +-- 查看所有门店当月耗卡业绩 | |
| 122 | +SELECT * FROM v_store_consume_performance_simple; | |
| 123 | + | |
| 124 | +-- 查看华润店当月耗卡业绩 | |
| 125 | +SELECT * FROM v_store_consume_performance_simple WHERE store_name LIKE '%华润%'; | |
| 126 | + | |
| 127 | +-- 查看已完成目标的门店(当月耗卡) | |
| 128 | +SELECT * FROM v_store_consume_performance_simple WHERE completion_rate >= 100; | |
| 129 | + | |
| 130 | +-- 查看零耗卡业绩的门店(当月) | |
| 131 | +SELECT * FROM v_store_consume_performance_simple WHERE actual_performance = 0; | |
| 132 | + | |
| 133 | +-- 按完成率排名(当月耗卡) | |
| 134 | +SELECT * FROM v_store_consume_performance_simple WHERE target_performance > 0 ORDER BY completion_rate DESC; | |
| 135 | + | |
| 136 | +-- 查看当月耗卡业绩前10名门店 | |
| 137 | +SELECT * FROM v_store_consume_performance_simple ORDER BY actual_performance DESC LIMIT 10; | |
| 138 | + | |
| 139 | +-- 查看当月完成率低于50%的门店 | |
| 140 | +SELECT * FROM v_store_consume_performance_simple WHERE completion_rate < 50 AND target_performance > 0; | |
| 141 | +*/ | ... | ... |
netcore/src/.DS_Store
No preview for this file type
netcore/src/Application/.DS_Store
No preview for this file type
netcore/src/Application/NCC.API/.DS_Store
No preview for this file type
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/TechTeacherSimpleStatisticsOutput.cs
0 → 100644
| 1 | +using System; | |
| 2 | + | |
| 3 | +namespace NCC.Extend.Entitys.Dto.LqStatistics | |
| 4 | +{ | |
| 5 | + /// <summary> | |
| 6 | + /// 科技部老师简化统计输出 | |
| 7 | + /// </summary> | |
| 8 | + public class TechTeacherSimpleStatisticsOutput | |
| 9 | + { | |
| 10 | + /// <summary> | |
| 11 | + /// 部门名称 | |
| 12 | + /// </summary> | |
| 13 | + public string DepartmentName { get; set; } | |
| 14 | + | |
| 15 | + /// <summary> | |
| 16 | + /// 老师姓名 | |
| 17 | + /// </summary> | |
| 18 | + public string TeacherName { get; set; } | |
| 19 | + | |
| 20 | + /// <summary> | |
| 21 | + /// 消耗项目数 | |
| 22 | + /// </summary> | |
| 23 | + public int ConsumeProjectCount { get; set; } | |
| 24 | + | |
| 25 | + /// <summary> | |
| 26 | + /// 消耗业绩 | |
| 27 | + /// </summary> | |
| 28 | + public decimal ConsumeAchievement { get; set; } | |
| 29 | + | |
| 30 | + /// <summary> | |
| 31 | + /// 开卡业绩 | |
| 32 | + /// </summary> | |
| 33 | + public decimal OrderAchievement { get; set; } | |
| 34 | + | |
| 35 | + /// <summary> | |
| 36 | + /// 开卡品项次数 | |
| 37 | + /// </summary> | |
| 38 | + public int OrderItemCount { get; set; } | |
| 39 | + | |
| 40 | + /// <summary> | |
| 41 | + /// 耗卡品项次数 | |
| 42 | + /// </summary> | |
| 43 | + public int ConsumeItemCount { get; set; } | |
| 44 | + } | |
| 45 | +} | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/TechTeacherStatisticsInput.cs
0 → 100644
| 1 | +using System; | |
| 2 | + | |
| 3 | +namespace NCC.Extend.Entitys.Dto.LqStatistics | |
| 4 | +{ | |
| 5 | + /// <summary> | |
| 6 | + /// 科技部老师统计查询参数 | |
| 7 | + /// </summary> | |
| 8 | + public class TechTeacherStatisticsInput | |
| 9 | + { | |
| 10 | + /// <summary> | |
| 11 | + /// 开始日期 | |
| 12 | + /// </summary> | |
| 13 | + public DateTime? StartDate { get; set; } | |
| 14 | + | |
| 15 | + /// <summary> | |
| 16 | + /// 结束日期 | |
| 17 | + /// </summary> | |
| 18 | + public DateTime? EndDate { get; set; } | |
| 19 | + | |
| 20 | + /// <summary> | |
| 21 | + /// 科技部老师ID | |
| 22 | + /// </summary> | |
| 23 | + public string TeacherId { get; set; } | |
| 24 | + | |
| 25 | + /// <summary> | |
| 26 | + /// 科技部老师姓名 | |
| 27 | + /// </summary> | |
| 28 | + public string TeacherName { get; set; } | |
| 29 | + | |
| 30 | + /// <summary> | |
| 31 | + /// 部门ID | |
| 32 | + /// </summary> | |
| 33 | + public string DepartmentId { get; set; } | |
| 34 | + } | |
| 35 | +} | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/TechTeacherStatisticsOutput.cs
0 → 100644
| 1 | +using System; | |
| 2 | +using System.Collections.Generic; | |
| 3 | + | |
| 4 | +namespace NCC.Extend.Entitys.Dto.LqStatistics | |
| 5 | +{ | |
| 6 | + /// <summary> | |
| 7 | + /// 科技部老师统计输出结果 | |
| 8 | + /// </summary> | |
| 9 | + public class TechTeacherStatisticsOutput | |
| 10 | + { | |
| 11 | + /// <summary> | |
| 12 | + /// 科技部老师ID | |
| 13 | + /// </summary> | |
| 14 | + public string TeacherId { get; set; } | |
| 15 | + | |
| 16 | + /// <summary> | |
| 17 | + /// 科技部老师姓名 | |
| 18 | + /// </summary> | |
| 19 | + public string TeacherName { get; set; } | |
| 20 | + | |
| 21 | + /// <summary> | |
| 22 | + /// 科技部老师账号 | |
| 23 | + /// </summary> | |
| 24 | + public string TeacherAccount { get; set; } | |
| 25 | + | |
| 26 | + /// <summary> | |
| 27 | + /// 开卡业绩 | |
| 28 | + /// </summary> | |
| 29 | + public decimal OrderAchievement { get; set; } | |
| 30 | + | |
| 31 | + /// <summary> | |
| 32 | + /// 消耗业绩 | |
| 33 | + /// </summary> | |
| 34 | + public decimal ConsumeAchievement { get; set; } | |
| 35 | + | |
| 36 | + /// <summary> | |
| 37 | + /// 退卡业绩 | |
| 38 | + /// </summary> | |
| 39 | + public decimal RefundAchievement { get; set; } | |
| 40 | + | |
| 41 | + /// <summary> | |
| 42 | + /// 总业绩 | |
| 43 | + /// </summary> | |
| 44 | + public decimal TotalAchievement { get; set; } | |
| 45 | + | |
| 46 | + /// <summary> | |
| 47 | + /// 见客数 | |
| 48 | + /// </summary> | |
| 49 | + public int CustomerCount { get; set; } | |
| 50 | + | |
| 51 | + /// <summary> | |
| 52 | + /// 项目数 | |
| 53 | + /// </summary> | |
| 54 | + public int ProjectCount { get; set; } | |
| 55 | + | |
| 56 | + /// <summary> | |
| 57 | + /// 手工费 | |
| 58 | + /// </summary> | |
| 59 | + public decimal LaborCost { get; set; } | |
| 60 | + | |
| 61 | + /// <summary> | |
| 62 | + /// 统计时间 | |
| 63 | + /// </summary> | |
| 64 | + public DateTime StatisticsTime { get; set; } | |
| 65 | + } | |
| 66 | + | |
| 67 | + /// <summary> | |
| 68 | + /// 科技部老师统计列表输出结果 | |
| 69 | + /// </summary> | |
| 70 | + public class TechTeacherStatisticsListOutput | |
| 71 | + { | |
| 72 | + /// <summary> | |
| 73 | + /// 科技部老师统计列表 | |
| 74 | + /// </summary> | |
| 75 | + public List<TechTeacherStatisticsOutput> Teachers { get; set; } = new List<TechTeacherStatisticsOutput>(); | |
| 76 | + | |
| 77 | + /// <summary> | |
| 78 | + /// 总记录数 | |
| 79 | + /// </summary> | |
| 80 | + public int TotalCount { get; set; } | |
| 81 | + | |
| 82 | + /// <summary> | |
| 83 | + /// 总开卡业绩 | |
| 84 | + /// </summary> | |
| 85 | + public decimal TotalOrderAchievement { get; set; } | |
| 86 | + | |
| 87 | + /// <summary> | |
| 88 | + /// 总消耗业绩 | |
| 89 | + /// </summary> | |
| 90 | + public decimal TotalConsumeAchievement { get; set; } | |
| 91 | + | |
| 92 | + /// <summary> | |
| 93 | + /// 总退卡业绩 | |
| 94 | + /// </summary> | |
| 95 | + public decimal TotalRefundAchievement { get; set; } | |
| 96 | + | |
| 97 | + /// <summary> | |
| 98 | + /// 总业绩 | |
| 99 | + /// </summary> | |
| 100 | + public decimal TotalAchievement { get; set; } | |
| 101 | + | |
| 102 | + /// <summary> | |
| 103 | + /// 总见客数 | |
| 104 | + /// </summary> | |
| 105 | + public int TotalCustomerCount { get; set; } | |
| 106 | + | |
| 107 | + /// <summary> | |
| 108 | + /// 总项目数 | |
| 109 | + /// </summary> | |
| 110 | + public int TotalProjectCount { get; set; } | |
| 111 | + | |
| 112 | + /// <summary> | |
| 113 | + /// 总手工费 | |
| 114 | + /// </summary> | |
| 115 | + public decimal TotalLaborCost { get; set; } | |
| 116 | + } | |
| 117 | +} | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_kjbsyj/LqKdKjbsyjEntity.cs
| 1 | -using NCC.Common.Const; | |
| 1 | +using System; | |
| 2 | +using NCC.Common.Const; | |
| 2 | 3 | using SqlSugar; |
| 3 | -using System; | |
| 4 | 4 | |
| 5 | 5 | namespace NCC.Extend.Entitys.lq_kd_kjbsyj |
| 6 | 6 | { |
| ... | ... | @@ -59,5 +59,10 @@ namespace NCC.Extend.Entitys.lq_kd_kjbsyj |
| 59 | 59 | [SugarColumn(ColumnName = "F_kdpxid")] |
| 60 | 60 | public string Kdpxid { get; set; } |
| 61 | 61 | |
| 62 | + /// <summary> | |
| 63 | + /// 手工费 | |
| 64 | + /// </summary> | |
| 65 | + [SugarColumn(ColumnName = "F_LaborCost")] | |
| 66 | + public decimal? LaborCost { get; set; } | |
| 62 | 67 | } |
| 63 | -} | |
| 64 | 68 | \ No newline at end of file |
| 69 | +} | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/v_tech_teacher_flow/VTechTeacherFlowEntity.cs
0 → 100644
| 1 | +using System; | |
| 2 | +using NCC.Common.Const; | |
| 3 | +using SqlSugar; | |
| 4 | + | |
| 5 | +namespace NCC.Extend.Entitys.v_tech_teacher_flow | |
| 6 | +{ | |
| 7 | + /// <summary> | |
| 8 | + /// 科技部老师业绩流水视图 | |
| 9 | + /// </summary> | |
| 10 | + [SugarTable("v_tech_teacher_flow")] | |
| 11 | + [Tenant(ClaimConst.TENANT_ID)] | |
| 12 | + public class VTechTeacherFlowEntity | |
| 13 | + { | |
| 14 | + /// <summary> | |
| 15 | + /// 老师ID | |
| 16 | + /// </summary> | |
| 17 | + [SugarColumn(ColumnName = "teacher_id")] | |
| 18 | + public string TeacherId { get; set; } | |
| 19 | + | |
| 20 | + /// <summary> | |
| 21 | + /// 老师姓名 | |
| 22 | + /// </summary> | |
| 23 | + [SugarColumn(ColumnName = "teacher_name")] | |
| 24 | + public string TeacherName { get; set; } | |
| 25 | + | |
| 26 | + /// <summary> | |
| 27 | + /// 老师账号 | |
| 28 | + /// </summary> | |
| 29 | + [SugarColumn(ColumnName = "teacher_account")] | |
| 30 | + public string TeacherAccount { get; set; } | |
| 31 | + | |
| 32 | + /// <summary> | |
| 33 | + /// 业务类型(开卡、耗卡、退卡) | |
| 34 | + /// </summary> | |
| 35 | + [SugarColumn(ColumnName = "business_type")] | |
| 36 | + public string BusinessType { get; set; } | |
| 37 | + | |
| 38 | + /// <summary> | |
| 39 | + /// 业绩金额 | |
| 40 | + /// </summary> | |
| 41 | + [SugarColumn(ColumnName = "achievement")] | |
| 42 | + public decimal Achievement { get; set; } | |
| 43 | + | |
| 44 | + /// <summary> | |
| 45 | + /// 手工费 | |
| 46 | + /// </summary> | |
| 47 | + [SugarColumn(ColumnName = "labor_cost")] | |
| 48 | + public decimal LaborCost { get; set; } | |
| 49 | + | |
| 50 | + /// <summary> | |
| 51 | + /// 项目数 | |
| 52 | + /// </summary> | |
| 53 | + [SugarColumn(ColumnName = "project_count")] | |
| 54 | + public decimal ProjectCount { get; set; } | |
| 55 | + | |
| 56 | + /// <summary> | |
| 57 | + /// 客户ID | |
| 58 | + /// </summary> | |
| 59 | + [SugarColumn(ColumnName = "customer_id")] | |
| 60 | + public string CustomerId { get; set; } | |
| 61 | + | |
| 62 | + /// <summary> | |
| 63 | + /// 客户姓名 | |
| 64 | + /// </summary> | |
| 65 | + [SugarColumn(ColumnName = "customer_name")] | |
| 66 | + public string CustomerName { get; set; } | |
| 67 | + | |
| 68 | + /// <summary> | |
| 69 | + /// 业务日期 | |
| 70 | + /// </summary> | |
| 71 | + [SugarColumn(ColumnName = "business_date")] | |
| 72 | + public DateTime? BusinessDate { get; set; } | |
| 73 | + | |
| 74 | + /// <summary> | |
| 75 | + /// 源记录ID | |
| 76 | + /// </summary> | |
| 77 | + [SugarColumn(ColumnName = "source_id")] | |
| 78 | + public string SourceId { get; set; } | |
| 79 | + | |
| 80 | + /// <summary> | |
| 81 | + /// 源表名 | |
| 82 | + /// </summary> | |
| 83 | + [SugarColumn(ColumnName = "source_table")] | |
| 84 | + public string SourceTable { get; set; } | |
| 85 | + | |
| 86 | + /// <summary> | |
| 87 | + /// 品项次数 | |
| 88 | + /// </summary> | |
| 89 | + [SugarColumn(ColumnName = "item_count")] | |
| 90 | + public int ItemCount { get; set; } | |
| 91 | + } | |
| 92 | +} | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/v_tech_teacher_summary/VTechTeacherSummaryEntity.cs
0 → 100644
| 1 | +using NCC.Common.Const; | |
| 2 | +using SqlSugar; | |
| 3 | + | |
| 4 | +namespace NCC.Extend.Entitys.v_tech_teacher_summary | |
| 5 | +{ | |
| 6 | + /// <summary> | |
| 7 | + /// 科技部老师业绩汇总视图(简化版) | |
| 8 | + /// </summary> | |
| 9 | + [SugarTable("v_tech_teacher_summary")] | |
| 10 | + [Tenant(ClaimConst.TENANT_ID)] | |
| 11 | + public class VTechTeacherSummaryEntity | |
| 12 | + { | |
| 13 | + /// <summary> | |
| 14 | + /// 老师ID | |
| 15 | + /// </summary> | |
| 16 | + [SugarColumn(ColumnName = "teacher_id")] | |
| 17 | + public string TeacherId { get; set; } | |
| 18 | + | |
| 19 | + /// <summary> | |
| 20 | + /// 老师姓名 | |
| 21 | + /// </summary> | |
| 22 | + [SugarColumn(ColumnName = "teacher_name")] | |
| 23 | + public string TeacherName { get; set; } | |
| 24 | + | |
| 25 | + /// <summary> | |
| 26 | + /// 老师账号 | |
| 27 | + /// </summary> | |
| 28 | + [SugarColumn(ColumnName = "teacher_account")] | |
| 29 | + public string TeacherAccount { get; set; } | |
| 30 | + | |
| 31 | + /// <summary> | |
| 32 | + /// 开卡业绩 | |
| 33 | + /// </summary> | |
| 34 | + [SugarColumn(ColumnName = "order_achievement")] | |
| 35 | + public decimal OrderAchievement { get; set; } | |
| 36 | + | |
| 37 | + /// <summary> | |
| 38 | + /// 消耗业绩 | |
| 39 | + /// </summary> | |
| 40 | + [SugarColumn(ColumnName = "consume_achievement")] | |
| 41 | + public decimal ConsumeAchievement { get; set; } | |
| 42 | + | |
| 43 | + /// <summary> | |
| 44 | + /// 退卡业绩 | |
| 45 | + /// </summary> | |
| 46 | + [SugarColumn(ColumnName = "refund_achievement")] | |
| 47 | + public decimal RefundAchievement { get; set; } | |
| 48 | + | |
| 49 | + /// <summary> | |
| 50 | + /// 总业绩 | |
| 51 | + /// </summary> | |
| 52 | + [SugarColumn(ColumnName = "total_achievement")] | |
| 53 | + public decimal TotalAchievement { get; set; } | |
| 54 | + | |
| 55 | + /// <summary> | |
| 56 | + /// 手工费 | |
| 57 | + /// </summary> | |
| 58 | + [SugarColumn(ColumnName = "labor_cost")] | |
| 59 | + public decimal LaborCost { get; set; } | |
| 60 | + | |
| 61 | + /// <summary> | |
| 62 | + /// 项目数 | |
| 63 | + /// </summary> | |
| 64 | + [SugarColumn(ColumnName = "project_count")] | |
| 65 | + public decimal ProjectCount { get; set; } | |
| 66 | + | |
| 67 | + /// <summary> | |
| 68 | + /// 见客数 | |
| 69 | + /// </summary> | |
| 70 | + [SugarColumn(ColumnName = "customer_count")] | |
| 71 | + public int CustomerCount { get; set; } | |
| 72 | + } | |
| 73 | +} | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqStatistics/ILqStatisticsService.cs
| ... | ... | @@ -2,6 +2,7 @@ using System.Collections.Generic; |
| 2 | 2 | using System.Threading.Tasks; |
| 3 | 3 | using NCC.Extend.Entitys.Dto.LqMdxx; |
| 4 | 4 | using NCC.Extend.Entitys.Dto.LqStatistics; |
| 5 | +using NCC.Extend.Entitys.v_tech_teacher_flow; | |
| 5 | 6 | |
| 6 | 7 | namespace NCC.Extend.Interfaces.LqStatistics |
| 7 | 8 | { |
| ... | ... | @@ -17,6 +18,12 @@ namespace NCC.Extend.Interfaces.LqStatistics |
| 17 | 18 | Task<List<StorePerformanceOutput>> GetStorePerformanceList(); |
| 18 | 19 | |
| 19 | 20 | /// <summary> |
| 21 | + /// 获取门店开单业绩统计列表 | |
| 22 | + /// </summary> | |
| 23 | + /// <returns>门店开单业绩统计列表</returns> | |
| 24 | + Task<List<StorePerformanceOutput>> GetStoreOrderPerformanceList(); | |
| 25 | + | |
| 26 | + /// <summary> | |
| 20 | 27 | /// 获取门店统计信息 |
| 21 | 28 | /// </summary> |
| 22 | 29 | /// <param name="input">查询参数</param> |
| ... | ... | @@ -50,5 +57,12 @@ namespace NCC.Extend.Interfaces.LqStatistics |
| 50 | 57 | /// <param name="input">查询参数</param> |
| 51 | 58 | /// <returns>经理业绩汇总统计结果</returns> |
| 52 | 59 | Task<ManagerSummaryStatisticsOutput> GetManagerSummaryStatistics(ManagerStatisticsInput input); |
| 60 | + | |
| 61 | + /// <summary> | |
| 62 | + /// 获取科技部老师业绩统计 | |
| 63 | + /// </summary> | |
| 64 | + /// <param name="input">查询参数</param> | |
| 65 | + /// <returns>科技部老师业绩统计结果</returns> | |
| 66 | + Task<List<TechTeacherSimpleStatisticsOutput>> GetTechTeacherStatistics(TechTeacherStatisticsInput input); | |
| 53 | 67 | } |
| 54 | 68 | } | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
| ... | ... | @@ -2,6 +2,7 @@ using System; |
| 2 | 2 | using System.Collections.Generic; |
| 3 | 3 | using System.Linq; |
| 4 | 4 | using System.Threading.Tasks; |
| 5 | +using Microsoft.AspNetCore.Authorization; | |
| 5 | 6 | using Microsoft.AspNetCore.Mvc; |
| 6 | 7 | using Microsoft.Extensions.Logging; |
| 7 | 8 | using NCC.Common.Core.Manager; |
| ... | ... | @@ -12,9 +13,15 @@ using NCC.Dependency; |
| 12 | 13 | using NCC.DynamicApiController; |
| 13 | 14 | using NCC.Extend.Entitys.Dto.LqMdxx; |
| 14 | 15 | using NCC.Extend.Entitys.Dto.LqStatistics; |
| 16 | +using NCC.Extend.Entitys.lq_hytk_kjbsyj; | |
| 17 | +using NCC.Extend.Entitys.lq_kd_kdjlb; | |
| 18 | +using NCC.Extend.Entitys.lq_kd_kjbsyj; | |
| 15 | 19 | using NCC.Extend.Entitys.lq_mdxx; |
| 20 | +using NCC.Extend.Entitys.lq_xh_kjbsyj; | |
| 16 | 21 | using NCC.Extend.Entitys.lq_yjmxb; |
| 22 | +using NCC.Extend.Entitys.v_tech_teacher_flow; | |
| 17 | 23 | using NCC.Extend.Interfaces.LqStatistics; |
| 24 | +using NCC.Extend.Utils; | |
| 18 | 25 | using NCC.FriendlyException; |
| 19 | 26 | using NCC.System.Entitys.Permission; |
| 20 | 27 | using SqlSugar; |
| ... | ... | @@ -32,45 +39,65 @@ namespace NCC.Extend.LqStatistics |
| 32 | 39 | private readonly SqlSugarScope _db; |
| 33 | 40 | private readonly IUserManager _userManager; |
| 34 | 41 | private readonly ILogger<LqStatisticsService> _logger; |
| 42 | + private readonly WeChatBotService _weChatBotService; | |
| 35 | 43 | |
| 36 | 44 | /// <summary> |
| 37 | 45 | /// 初始化一个<see cref="LqStatisticsService"/>类型的新实例 |
| 38 | 46 | /// </summary> |
| 39 | - public LqStatisticsService(ISqlSugarRepository<LqMdxxEntity> lqMdxxRepository, IUserManager userManager, ILogger<LqStatisticsService> logger) | |
| 47 | + public LqStatisticsService(ISqlSugarRepository<LqMdxxEntity> lqMdxxRepository, IUserManager userManager, ILogger<LqStatisticsService> logger, WeChatBotService weChatBotService) | |
| 40 | 48 | { |
| 41 | 49 | _lqMdxxRepository = lqMdxxRepository; |
| 42 | 50 | _db = _lqMdxxRepository.Context; |
| 43 | 51 | _userManager = userManager; |
| 44 | 52 | _logger = logger; |
| 53 | + _weChatBotService = weChatBotService; | |
| 45 | 54 | } |
| 46 | 55 | |
| 47 | - #region 获取门店业绩统计列表 | |
| 56 | + #region 获取门店耗卡业绩统计列表 | |
| 48 | 57 | /// <summary> |
| 49 | 58 | /// 获取门店业绩统计列表 |
| 50 | 59 | /// </summary> |
| 60 | + /// <remarks> | |
| 61 | + /// 获取所有门店的耗卡业绩统计信息,包括门店ID、名称、编码、目标业绩、耗卡业绩、完成率等关键指标 | |
| 62 | + /// | |
| 63 | + /// 返回数据说明: | |
| 64 | + /// - StoreId: 门店ID | |
| 65 | + /// - StoreName: 门店名称 | |
| 66 | + /// - StoreCode: 门店编码 | |
| 67 | + /// - BusinessUnitId: 事业部ID(暂未关联) | |
| 68 | + /// - BusinessUnitName: 事业部名称(暂未关联) | |
| 69 | + /// - TargetPerformance: 目标业绩(门店生命线) | |
| 70 | + /// - ActualPerformance: 耗卡业绩(当月耗卡金额汇总) | |
| 71 | + /// - CompletionRate: 完成率(耗卡业绩/目标业绩*100) | |
| 72 | + /// - OrderCount: 耗卡记录数(当月耗卡记录数) | |
| 73 | + /// | |
| 74 | + /// 数据来源:v_store_consume_performance_simple 视图 | |
| 75 | + /// </remarks> | |
| 51 | 76 | /// <returns>门店业绩统计列表</returns> |
| 52 | - [HttpGet] | |
| 77 | + /// <response code="200">成功返回门店业绩统计列表</response> | |
| 78 | + /// <response code="500">服务器内部错误</response> | |
| 79 | + [HttpGet("GetStorePerformanceList")] | |
| 53 | 80 | public async Task<List<StorePerformanceOutput>> GetStorePerformanceList() |
| 54 | 81 | { |
| 55 | 82 | try |
| 56 | 83 | { |
| 57 | 84 | _logger.LogInformation("开始查询门店业绩统计列表"); |
| 58 | 85 | |
| 59 | - var storeList = await _lqMdxxRepository | |
| 60 | - .AsQueryable() | |
| 61 | - .Where(x => x.Status == 1) | |
| 62 | - .Select(x => new StorePerformanceOutput | |
| 63 | - { | |
| 64 | - StoreId = x.Id, | |
| 65 | - StoreName = x.Dm, | |
| 66 | - StoreCode = x.Mdbm, | |
| 67 | - BusinessUnitId = x.Syb, | |
| 68 | - BusinessUnitName = x.Syb, | |
| 69 | - TargetPerformance = x.Xsyj ?? 0, | |
| 70 | - ActualPerformance = 0, | |
| 71 | - CompletionRate = 0, | |
| 72 | - }) | |
| 73 | - .ToListAsync(); | |
| 86 | + // 使用耗卡业绩统计视图 | |
| 87 | + var storeList = await _db.Ado.SqlQueryAsync<StorePerformanceOutput>( | |
| 88 | + "SELECT " | |
| 89 | + + "store_id AS StoreId, " | |
| 90 | + + "store_code AS StoreCode, " | |
| 91 | + + "store_name AS StoreName, " | |
| 92 | + + "'' AS BusinessUnitId, " | |
| 93 | + + "'' AS BusinessUnitName, " | |
| 94 | + + "target_performance AS TargetPerformance, " | |
| 95 | + + "actual_performance AS ActualPerformance, " | |
| 96 | + + "completion_rate AS CompletionRate, " | |
| 97 | + + "order_count AS OrderCount " | |
| 98 | + + "FROM v_store_consume_performance_simple " | |
| 99 | + + "ORDER BY actual_performance DESC" | |
| 100 | + ); | |
| 74 | 101 | |
| 75 | 102 | _logger.LogInformation("门店业绩统计列表查询完成,返回{Count}条记录", storeList.Count); |
| 76 | 103 | |
| ... | ... | @@ -84,12 +111,101 @@ namespace NCC.Extend.LqStatistics |
| 84 | 111 | } |
| 85 | 112 | #endregion |
| 86 | 113 | |
| 114 | + #region 获取门店开单业绩统计列表 | |
| 115 | + /// <summary> | |
| 116 | + /// 获取门店开单业绩统计列表 | |
| 117 | + /// </summary> | |
| 118 | + /// <remarks> | |
| 119 | + /// 获取所有门店的开单业绩统计信息,包括门店ID、名称、编码、目标业绩、开单业绩、完成率等关键指标 | |
| 120 | + /// | |
| 121 | + /// 返回数据说明: | |
| 122 | + /// - StoreId: 门店ID | |
| 123 | + /// - StoreName: 门店名称 | |
| 124 | + /// - StoreCode: 门店编码 | |
| 125 | + /// - BusinessUnitId: 事业部ID(暂未关联) | |
| 126 | + /// - BusinessUnitName: 事业部名称(暂未关联) | |
| 127 | + /// - TargetPerformance: 目标业绩(门店生命线) | |
| 128 | + /// - ActualPerformance: 开单业绩(当月开单金额汇总) | |
| 129 | + /// - CompletionRate: 完成率(开单业绩/目标业绩*100) | |
| 130 | + /// - OrderCount: 开单记录数(当月开单记录数) | |
| 131 | + /// | |
| 132 | + /// 数据来源:v_store_performance_simple 视图 | |
| 133 | + /// </remarks> | |
| 134 | + /// <returns>门店开单业绩统计列表</returns> | |
| 135 | + /// <response code="200">成功返回门店开单业绩统计列表</response> | |
| 136 | + /// <response code="500">服务器内部错误</response> | |
| 137 | + [HttpGet("GetStoreOrderPerformanceList")] | |
| 138 | + public async Task<List<StorePerformanceOutput>> GetStoreOrderPerformanceList() | |
| 139 | + { | |
| 140 | + try | |
| 141 | + { | |
| 142 | + _logger.LogInformation("开始查询门店开单业绩统计列表"); | |
| 143 | + | |
| 144 | + // 使用开单业绩统计视图 | |
| 145 | + var storeList = await _db.Ado.SqlQueryAsync<StorePerformanceOutput>( | |
| 146 | + "SELECT " | |
| 147 | + + "store_id AS StoreId, " | |
| 148 | + + "store_code AS StoreCode, " | |
| 149 | + + "store_name AS StoreName, " | |
| 150 | + + "'' AS BusinessUnitId, " | |
| 151 | + + "'' AS BusinessUnitName, " | |
| 152 | + + "target_performance AS TargetPerformance, " | |
| 153 | + + "actual_performance AS ActualPerformance, " | |
| 154 | + + "completion_rate AS CompletionRate, " | |
| 155 | + + "order_count AS OrderCount " | |
| 156 | + + "FROM v_store_performance_simple " | |
| 157 | + + "ORDER BY actual_performance DESC" | |
| 158 | + ); | |
| 159 | + | |
| 160 | + _logger.LogInformation("门店开单业绩统计列表查询完成,返回{Count}条记录", storeList.Count); | |
| 161 | + | |
| 162 | + return storeList ?? new List<StorePerformanceOutput>(); | |
| 163 | + } | |
| 164 | + catch (Exception ex) | |
| 165 | + { | |
| 166 | + _logger.LogError(ex, "查询门店开单业绩统计列表时发生错误"); | |
| 167 | + throw NCCException.Oh("查询门店开单业绩统计列表失败", ex); | |
| 168 | + } | |
| 169 | + } | |
| 170 | + #endregion | |
| 171 | + | |
| 87 | 172 | #region 获取门店统计信息 |
| 88 | 173 | /// <summary> |
| 89 | 174 | /// 获取门店统计信息 |
| 90 | 175 | /// </summary> |
| 176 | + /// <remarks> | |
| 177 | + /// 根据指定日期范围和门店ID查询门店的详细业绩统计信息,包括目标业绩、完成业绩、完成率等 | |
| 178 | + /// | |
| 179 | + /// 示例请求: | |
| 180 | + /// ```json | |
| 181 | + /// { | |
| 182 | + /// "startDate": "2025-01-01T00:00:00", | |
| 183 | + /// "endDate": "2025-01-31T23:59:59", | |
| 184 | + /// "storeId": "门店ID(可选)" | |
| 185 | + /// } | |
| 186 | + /// ``` | |
| 187 | + /// | |
| 188 | + /// 参数说明: | |
| 189 | + /// - startDate: 开始日期,格式:yyyy-MM-ddTHH:mm:ss | |
| 190 | + /// - endDate: 结束日期,格式:yyyy-MM-ddTHH:mm:ss | |
| 191 | + /// - storeId: 门店ID,可选参数,不传则查询所有门店 | |
| 192 | + /// | |
| 193 | + /// 返回数据说明: | |
| 194 | + /// - StoreId: 门店ID | |
| 195 | + /// - StoreName: 门店名称 | |
| 196 | + /// - StoreCode: 门店编码 | |
| 197 | + /// - BusinessUnitId: 事业部ID | |
| 198 | + /// - BusinessUnitName: 事业部名称 | |
| 199 | + /// - TargetPerformance: 目标业绩 | |
| 200 | + /// - ActualPerformance: 完成业绩 | |
| 201 | + /// - OrderCount: 开单数量 | |
| 202 | + /// - CompletionRate: 完成率(%) | |
| 203 | + /// </remarks> | |
| 91 | 204 | /// <param name="input">查询参数</param> |
| 92 | 205 | /// <returns>门店统计结果</returns> |
| 206 | + /// <response code="200">成功返回门店统计数据</response> | |
| 207 | + /// <response code="400">请求参数错误</response> | |
| 208 | + /// <response code="500">服务器内部错误</response> | |
| 93 | 209 | [HttpPost("StoreStatistics")] |
| 94 | 210 | public async Task<StoreStatisticsOutput> GetStoreStatistics(StoreStatisticsInput input) |
| 95 | 211 | { |
| ... | ... | @@ -101,41 +217,29 @@ namespace NCC.Extend.LqStatistics |
| 101 | 217 | var parameters = new Dictionary<string, object> { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } }; |
| 102 | 218 | |
| 103 | 219 | // 构建WHERE条件 |
| 104 | - var whereClause = "WHERE (order_date >= @startDate AND order_date <= @endDate OR order_date IS NULL)"; | |
| 105 | - | |
| 220 | + var whereClause = "WHERE 1=1"; | |
| 106 | 221 | if (!string.IsNullOrEmpty(input.StoreId)) |
| 107 | 222 | { |
| 108 | 223 | whereClause += " AND store_id = @storeId"; |
| 109 | 224 | parameters.Add("@storeId", input.StoreId); |
| 110 | 225 | } |
| 111 | 226 | |
| 112 | - // 构建SQL查询 | |
| 227 | + // 使用SQL查询门店统计信息,包含日期范围过滤 | |
| 113 | 228 | var sql = |
| 114 | 229 | $@" |
| 115 | 230 | SELECT |
| 116 | 231 | store_id AS StoreId, |
| 117 | - store_name AS StoreName, | |
| 118 | 232 | store_code AS StoreCode, |
| 119 | - business_unit_id AS BusinessUnitId, | |
| 120 | - business_unit_name AS BusinessUnitName, | |
| 233 | + store_name AS StoreName, | |
| 234 | + '' AS BusinessUnitId, | |
| 235 | + '' AS BusinessUnitName, | |
| 121 | 236 | target_performance AS TargetPerformance, |
| 122 | - SUM(COALESCE(actual_amount, 0)) AS ActualPerformance, | |
| 123 | - COUNT(order_id) AS OrderCount, | |
| 124 | - CASE | |
| 125 | - WHEN target_performance > 0 | |
| 126 | - THEN ROUND((SUM(COALESCE(actual_amount, 0)) / target_performance) * 100, 2) | |
| 127 | - ELSE 0 | |
| 128 | - END AS CompletionRate | |
| 129 | - FROM v_store_daily_consume_stats | |
| 237 | + actual_performance AS ActualPerformance, | |
| 238 | + completion_rate AS CompletionRate, | |
| 239 | + order_count AS OrderCount | |
| 240 | + FROM v_store_performance_simple | |
| 130 | 241 | {whereClause} |
| 131 | - GROUP BY | |
| 132 | - store_id, | |
| 133 | - store_name, | |
| 134 | - store_code, | |
| 135 | - business_unit_id, | |
| 136 | - business_unit_name, | |
| 137 | - target_performance | |
| 138 | - ORDER BY ActualPerformance DESC"; | |
| 242 | + ORDER BY actual_performance DESC"; | |
| 139 | 243 | |
| 140 | 244 | _logger.LogInformation("执行SQL查询:{Sql}", sql); |
| 141 | 245 | _logger.LogInformation("查询参数:{Parameters}", string.Join(", ", parameters.Select(p => $"{p.Key}={p.Value}"))); |
| ... | ... | @@ -176,8 +280,38 @@ namespace NCC.Extend.LqStatistics |
| 176 | 280 | /// <summary> |
| 177 | 281 | /// 获取事业部业绩统计 |
| 178 | 282 | /// </summary> |
| 283 | + /// <remarks> | |
| 284 | + /// 根据指定日期范围和事业部ID查询事业部的业绩统计信息,包括目标业绩总和、完成业绩总和、完成率等 | |
| 285 | + /// | |
| 286 | + /// 示例请求: | |
| 287 | + /// ```json | |
| 288 | + /// { | |
| 289 | + /// "startDate": "2025-01-01T00:00:00", | |
| 290 | + /// "endDate": "2025-01-31T23:59:59", | |
| 291 | + /// "businessUnitId": "事业部ID(可选)" | |
| 292 | + /// } | |
| 293 | + /// ``` | |
| 294 | + /// | |
| 295 | + /// 参数说明: | |
| 296 | + /// - startDate: 开始日期,格式:yyyy-MM-ddTHH:mm:ss | |
| 297 | + /// - endDate: 结束日期,格式:yyyy-MM-ddTHH:mm:ss | |
| 298 | + /// - businessUnitId: 事业部ID,可选参数,不传则查询所有事业部 | |
| 299 | + /// | |
| 300 | + /// 返回数据说明: | |
| 301 | + /// - DepartmentId: 部门ID | |
| 302 | + /// - DepartmentName: 部门名称 | |
| 303 | + /// - ParentId: 父部门ID | |
| 304 | + /// - ParentName: 父部门名称 | |
| 305 | + /// - TotalTargetAmount: 目标业绩总和 | |
| 306 | + /// - TotalActualAmount: 完成业绩总和 | |
| 307 | + /// - TotalOrderCount: 开单总数量 | |
| 308 | + /// - CompletionRate: 完成率(%) | |
| 309 | + /// </remarks> | |
| 179 | 310 | /// <param name="input">查询参数</param> |
| 180 | 311 | /// <returns>事业部业绩统计结果</returns> |
| 312 | + /// <response code="200">成功返回事业部业绩统计数据</response> | |
| 313 | + /// <response code="400">请求参数错误</response> | |
| 314 | + /// <response code="500">服务器内部错误</response> | |
| 181 | 315 | [HttpPost("BusinessUnitStatistics")] |
| 182 | 316 | public async Task<BusinessUnitStatisticsOutput> GetBusinessUnitStatistics(BusinessUnitStatisticsInput input) |
| 183 | 317 | { |
| ... | ... | @@ -189,37 +323,41 @@ namespace NCC.Extend.LqStatistics |
| 189 | 323 | var parameters = new Dictionary<string, object> { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } }; |
| 190 | 324 | |
| 191 | 325 | // 构建WHERE条件 |
| 192 | - var whereClause = "WHERE (order_date >= @startDate AND order_date <= @endDate OR order_date IS NULL)"; | |
| 193 | - | |
| 326 | + var whereClause = "WHERE 1=1"; | |
| 194 | 327 | if (!string.IsNullOrEmpty(input.BusinessUnitId)) |
| 195 | 328 | { |
| 196 | - whereClause += " AND department_id = @businessUnitId"; | |
| 329 | + whereClause += " AND dept.F_Id = @businessUnitId"; | |
| 197 | 330 | parameters.Add("@businessUnitId", input.BusinessUnitId); |
| 198 | 331 | } |
| 199 | 332 | |
| 200 | - // 构建SQL查询 | |
| 333 | + // 构建SQL查询 - 先查询所有事业部,然后左连接业绩数据 | |
| 201 | 334 | var sql = |
| 202 | 335 | $@" |
| 203 | 336 | SELECT |
| 204 | - department_id AS DepartmentId, | |
| 205 | - department_name AS DepartmentName, | |
| 206 | - parent_id AS ParentId, | |
| 207 | - parent_name AS ParentName, | |
| 208 | - SUM(COALESCE(target_amount, 0)) AS TotalTargetAmount, | |
| 209 | - SUM(COALESCE(actual_amount, 0)) AS TotalActualAmount, | |
| 210 | - COUNT(order_id) AS TotalOrderCount, | |
| 337 | + dept.F_Id AS DepartmentId, | |
| 338 | + dept.F_FullName AS DepartmentName, | |
| 339 | + dept.F_ParentId AS ParentId, | |
| 340 | + parent.F_FullName AS ParentName, | |
| 341 | + COALESCE(SUM(flow.actual_amount), 0) AS TotalActualAmount, | |
| 342 | + COALESCE(COUNT(flow.order_id), 0) AS TotalOrderCount, | |
| 211 | 343 | CASE |
| 212 | - WHEN SUM(COALESCE(target_amount, 0)) > 0 | |
| 213 | - THEN ROUND((SUM(COALESCE(actual_amount, 0)) / SUM(COALESCE(target_amount, 0))) * 100, 2) | |
| 344 | + WHEN COALESCE(SUM(flow.actual_amount), 0) > 0 | |
| 345 | + THEN ROUND((COALESCE(SUM(flow.actual_amount), 0) / 100000) * 100, 2) | |
| 214 | 346 | ELSE 0 |
| 215 | 347 | END AS CompletionRate |
| 216 | - FROM v_department_performance_flow | |
| 217 | - {whereClause} | |
| 348 | + FROM base_organize dept | |
| 349 | + LEFT JOIN base_organize parent ON dept.F_ParentId = parent.F_Id | |
| 350 | + LEFT JOIN v_department_performance_flow flow ON dept.F_Id = flow.department_id | |
| 351 | + AND (flow.order_date >= @startDate AND flow.order_date <= @endDate OR flow.order_date IS NULL) | |
| 352 | + WHERE dept.F_ParentId = (SELECT F_Id FROM base_organize WHERE F_FullName = '事业部') | |
| 353 | + AND dept.F_EnabledMark = 1 | |
| 354 | + AND dept.F_DeleteMark IS NULL | |
| 355 | + {whereClause.Replace("WHERE 1=1", "")} | |
| 218 | 356 | GROUP BY |
| 219 | - department_id, | |
| 220 | - department_name, | |
| 221 | - parent_id, | |
| 222 | - parent_name | |
| 357 | + dept.F_Id, | |
| 358 | + dept.F_FullName, | |
| 359 | + dept.F_ParentId, | |
| 360 | + parent.F_FullName | |
| 223 | 361 | ORDER BY TotalActualAmount DESC"; |
| 224 | 362 | |
| 225 | 363 | _logger.LogInformation("执行SQL查询:{Sql}", sql); |
| ... | ... | @@ -237,7 +375,7 @@ namespace NCC.Extend.LqStatistics |
| 237 | 375 | DepartmentName = r.DepartmentName?.ToString() ?? "", |
| 238 | 376 | ParentId = r.ParentId?.ToString() ?? "", |
| 239 | 377 | ParentName = r.ParentName?.ToString() ?? "", |
| 240 | - TotalTargetAmount = Convert.ToDecimal(r.TotalTargetAmount ?? 0), | |
| 378 | + TotalTargetAmount = 100000, // 默认目标业绩10万 | |
| 241 | 379 | TotalActualAmount = Convert.ToDecimal(r.TotalActualAmount ?? 0), |
| 242 | 380 | TotalOrderCount = Convert.ToInt32(r.TotalOrderCount ?? 0), |
| 243 | 381 | CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0), |
| ... | ... | @@ -260,8 +398,38 @@ namespace NCC.Extend.LqStatistics |
| 260 | 398 | /// <summary> |
| 261 | 399 | /// 获取其他部门业绩统计 |
| 262 | 400 | /// </summary> |
| 401 | + /// <remarks> | |
| 402 | + /// 根据指定日期范围和部门ID查询其他部门(教育部、科技部、大项目部)的业绩统计信息 | |
| 403 | + /// | |
| 404 | + /// 示例请求: | |
| 405 | + /// ```json | |
| 406 | + /// { | |
| 407 | + /// "startDate": "2025-01-01T00:00:00", | |
| 408 | + /// "endDate": "2025-01-31T23:59:59", | |
| 409 | + /// "departmentId": "部门ID(可选)" | |
| 410 | + /// } | |
| 411 | + /// ``` | |
| 412 | + /// | |
| 413 | + /// 参数说明: | |
| 414 | + /// - startDate: 开始日期,格式:yyyy-MM-ddTHH:mm:ss | |
| 415 | + /// - endDate: 结束日期,格式:yyyy-MM-ddTHH:mm:ss | |
| 416 | + /// - departmentId: 部门ID,可选参数,不传则查询所有其他部门 | |
| 417 | + /// | |
| 418 | + /// 返回数据说明: | |
| 419 | + /// - DepartmentId: 部门ID | |
| 420 | + /// - DepartmentName: 部门名称 | |
| 421 | + /// - ParentId: 父部门ID | |
| 422 | + /// - ParentName: 父部门名称 | |
| 423 | + /// - TotalTargetAmount: 目标业绩总和 | |
| 424 | + /// - TotalActualAmount: 完成业绩总和 | |
| 425 | + /// - TotalOrderCount: 开单总数量 | |
| 426 | + /// - CompletionRate: 完成率(%) | |
| 427 | + /// </remarks> | |
| 263 | 428 | /// <param name="input">查询参数</param> |
| 264 | 429 | /// <returns>其他部门业绩统计结果</returns> |
| 430 | + /// <response code="200">成功返回其他部门业绩统计数据</response> | |
| 431 | + /// <response code="400">请求参数错误</response> | |
| 432 | + /// <response code="500">服务器内部错误</response> | |
| 265 | 433 | [HttpPost("OtherDepartmentStatistics")] |
| 266 | 434 | public async Task<OtherDepartmentStatisticsOutput> GetOtherDepartmentStatistics(OtherDepartmentStatisticsInput input) |
| 267 | 435 | { |
| ... | ... | @@ -273,37 +441,41 @@ namespace NCC.Extend.LqStatistics |
| 273 | 441 | var parameters = new Dictionary<string, object> { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } }; |
| 274 | 442 | |
| 275 | 443 | // 构建WHERE条件 |
| 276 | - var whereClause = "WHERE (order_date >= @startDate AND order_date <= @endDate OR order_date IS NULL)"; | |
| 277 | - | |
| 444 | + var whereClause = "WHERE 1=1"; | |
| 278 | 445 | if (!string.IsNullOrEmpty(input.DepartmentId)) |
| 279 | 446 | { |
| 280 | - whereClause += " AND department_id = @departmentId"; | |
| 447 | + whereClause += " AND dept.F_Id = @departmentId"; | |
| 281 | 448 | parameters.Add("@departmentId", input.DepartmentId); |
| 282 | 449 | } |
| 283 | 450 | |
| 284 | - // 构建SQL查询 | |
| 451 | + // 构建SQL查询 - 先查询所有其他部门的子部门,然后左连接业绩数据 | |
| 285 | 452 | var sql = |
| 286 | 453 | $@" |
| 287 | 454 | SELECT |
| 288 | - department_id AS DepartmentId, | |
| 289 | - department_name AS DepartmentName, | |
| 290 | - parent_id AS ParentId, | |
| 291 | - parent_name AS ParentName, | |
| 292 | - SUM(COALESCE(target_amount, 0)) AS TotalTargetAmount, | |
| 293 | - SUM(COALESCE(actual_amount, 0)) AS TotalActualAmount, | |
| 294 | - COUNT(order_id) AS TotalOrderCount, | |
| 455 | + dept.F_Id AS DepartmentId, | |
| 456 | + dept.F_FullName AS DepartmentName, | |
| 457 | + dept.F_ParentId AS ParentId, | |
| 458 | + parent.F_FullName AS ParentName, | |
| 459 | + COALESCE(SUM(flow.actual_amount), 0) AS TotalActualAmount, | |
| 460 | + COALESCE(COUNT(flow.order_id), 0) AS TotalOrderCount, | |
| 295 | 461 | CASE |
| 296 | - WHEN SUM(COALESCE(target_amount, 0)) > 0 | |
| 297 | - THEN ROUND((SUM(COALESCE(actual_amount, 0)) / SUM(COALESCE(target_amount, 0))) * 100, 2) | |
| 462 | + WHEN COALESCE(SUM(flow.actual_amount), 0) > 0 | |
| 463 | + THEN ROUND((COALESCE(SUM(flow.actual_amount), 0) / 50000) * 100, 2) | |
| 298 | 464 | ELSE 0 |
| 299 | 465 | END AS CompletionRate |
| 300 | - FROM v_other_department_performance_flow | |
| 301 | - {whereClause} | |
| 466 | + FROM base_organize dept | |
| 467 | + LEFT JOIN base_organize parent ON dept.F_ParentId = parent.F_Id | |
| 468 | + LEFT JOIN v_other_department_performance_flow flow ON dept.F_Id = flow.department_id | |
| 469 | + AND (flow.order_date >= @startDate AND flow.order_date <= @endDate OR flow.order_date IS NULL) | |
| 470 | + WHERE dept.F_ParentId IN (SELECT F_Id FROM base_organize WHERE F_FullName IN ('教育部', '科技部', '大项目部')) | |
| 471 | + AND dept.F_EnabledMark = 1 | |
| 472 | + AND dept.F_DeleteMark IS NULL | |
| 473 | + {whereClause.Replace("WHERE 1=1", "")} | |
| 302 | 474 | GROUP BY |
| 303 | - department_id, | |
| 304 | - department_name, | |
| 305 | - parent_id, | |
| 306 | - parent_name | |
| 475 | + dept.F_Id, | |
| 476 | + dept.F_FullName, | |
| 477 | + dept.F_ParentId, | |
| 478 | + parent.F_FullName | |
| 307 | 479 | ORDER BY TotalActualAmount DESC"; |
| 308 | 480 | |
| 309 | 481 | _logger.LogInformation("执行SQL查询:{Sql}", sql); |
| ... | ... | @@ -321,7 +493,7 @@ namespace NCC.Extend.LqStatistics |
| 321 | 493 | DepartmentName = r.DepartmentName?.ToString() ?? "", |
| 322 | 494 | ParentId = r.ParentId?.ToString() ?? "", |
| 323 | 495 | ParentName = r.ParentName?.ToString() ?? "", |
| 324 | - TotalTargetAmount = Convert.ToDecimal(r.TotalTargetAmount ?? 0), | |
| 496 | + TotalTargetAmount = 50000, // 默认目标业绩5万 | |
| 325 | 497 | TotalActualAmount = Convert.ToDecimal(r.TotalActualAmount ?? 0), |
| 326 | 498 | TotalOrderCount = Convert.ToInt32(r.TotalOrderCount ?? 0), |
| 327 | 499 | CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0), |
| ... | ... | @@ -344,8 +516,40 @@ namespace NCC.Extend.LqStatistics |
| 344 | 516 | /// <summary> |
| 345 | 517 | /// 获取经理业绩统计 |
| 346 | 518 | /// </summary> |
| 519 | + /// <remarks> | |
| 520 | + /// 根据指定日期范围和事业部ID查询经理的业绩统计信息,按经理和门店维度进行统计 | |
| 521 | + /// | |
| 522 | + /// 示例请求: | |
| 523 | + /// ```json | |
| 524 | + /// { | |
| 525 | + /// "startDate": "2025-01-01T00:00:00", | |
| 526 | + /// "endDate": "2025-01-31T23:59:59", | |
| 527 | + /// "businessUnitId": "事业部ID(可选)" | |
| 528 | + /// } | |
| 529 | + /// ``` | |
| 530 | + /// | |
| 531 | + /// 参数说明: | |
| 532 | + /// - startDate: 开始日期,格式:yyyy-MM-ddTHH:mm:ss | |
| 533 | + /// - endDate: 结束日期,格式:yyyy-MM-ddTHH:mm:ss | |
| 534 | + /// - businessUnitId: 事业部ID,可选参数,不传则查询所有事业部 | |
| 535 | + /// | |
| 536 | + /// 返回数据说明: | |
| 537 | + /// - ManagerName: 经理姓名 | |
| 538 | + /// - ManagerUserId: 经理用户ID | |
| 539 | + /// - BusinessUnitName: 事业部名称 | |
| 540 | + /// - BusinessUnitId: 事业部ID | |
| 541 | + /// - StoreName: 门店名称 | |
| 542 | + /// - StoreId: 门店ID | |
| 543 | + /// - TargetPerformance: 目标业绩 | |
| 544 | + /// - ActualPerformance: 完成业绩 | |
| 545 | + /// - OrderCount: 开单数量 | |
| 546 | + /// - CompletionRate: 完成率(%) | |
| 547 | + /// </remarks> | |
| 347 | 548 | /// <param name="input">查询参数</param> |
| 348 | 549 | /// <returns>经理业绩统计结果</returns> |
| 550 | + /// <response code="200">成功返回经理业绩统计数据</response> | |
| 551 | + /// <response code="400">请求参数错误</response> | |
| 552 | + /// <response code="500">服务器内部错误</response> | |
| 349 | 553 | [HttpPost("ManagerStatistics")] |
| 350 | 554 | public async Task<ManagerStatisticsOutput> GetManagerStatistics(ManagerStatisticsInput input) |
| 351 | 555 | { |
| ... | ... | @@ -593,6 +797,242 @@ namespace NCC.Extend.LqStatistics |
| 593 | 797 | } |
| 594 | 798 | } |
| 595 | 799 | #endregion |
| 800 | + | |
| 801 | + #region 科技部老师业绩统计 | |
| 802 | + /// <summary> | |
| 803 | + /// 获取科技部老师业绩统计 | |
| 804 | + /// </summary> | |
| 805 | + /// <param name="input">查询参数</param> | |
| 806 | + /// <returns>科技部老师业绩统计结果</returns> | |
| 807 | + [HttpPost("GetTechTeacherStatistics")] | |
| 808 | + public async Task<List<TechTeacherSimpleStatisticsOutput>> GetTechTeacherStatistics(TechTeacherStatisticsInput input) | |
| 809 | + { | |
| 810 | + try | |
| 811 | + { // 1. 从用户表获取所有科技部老师 | |
| 812 | + var allTeachers = await _db.Queryable<UserEntity>() | |
| 813 | + .Where(x => x.Gw == "科技老师") | |
| 814 | + .Select(x => new | |
| 815 | + { | |
| 816 | + TeacherId = x.Id, | |
| 817 | + TeacherName = x.RealName, | |
| 818 | + TeacherAccount = x.Account, | |
| 819 | + }) | |
| 820 | + .ToListAsync(); | |
| 821 | + | |
| 822 | + // 2. 获取业绩流水数据 | |
| 823 | + var flowQuery = _db.Queryable<VTechTeacherFlowEntity>(); | |
| 824 | + | |
| 825 | + // 老师过滤 | |
| 826 | + if (!string.IsNullOrEmpty(input.TeacherId)) | |
| 827 | + { | |
| 828 | + flowQuery = flowQuery.Where(x => x.TeacherId == input.TeacherId); | |
| 829 | + } | |
| 830 | + | |
| 831 | + if (!string.IsNullOrEmpty(input.TeacherName)) | |
| 832 | + { | |
| 833 | + flowQuery = flowQuery.Where(x => x.TeacherName.Contains(input.TeacherName)); | |
| 834 | + } | |
| 835 | + | |
| 836 | + // 日期过滤 | |
| 837 | + if (input.StartDate.HasValue) | |
| 838 | + { | |
| 839 | + flowQuery = flowQuery.Where(x => x.BusinessDate >= input.StartDate.Value); | |
| 840 | + } | |
| 841 | + | |
| 842 | + if (input.EndDate.HasValue) | |
| 843 | + { | |
| 844 | + flowQuery = flowQuery.Where(x => x.BusinessDate <= input.EndDate.Value); | |
| 845 | + } | |
| 846 | + | |
| 847 | + var flowRecords = await flowQuery.ToListAsync(); | |
| 848 | + | |
| 849 | + // 3. 按老师分组统计业绩数据 | |
| 850 | + var teacherStatsDict = flowRecords | |
| 851 | + .GroupBy(x => new | |
| 852 | + { | |
| 853 | + x.TeacherId, | |
| 854 | + x.TeacherName, | |
| 855 | + x.TeacherAccount, | |
| 856 | + }) | |
| 857 | + .ToDictionary( | |
| 858 | + g => g.Key, | |
| 859 | + g => new | |
| 860 | + { | |
| 861 | + ConsumeProjectCount = (int)g.Where(x => x.BusinessType == "耗卡").Sum(x => x.ProjectCount), | |
| 862 | + ConsumeAchievement = g.Where(x => x.BusinessType == "耗卡").Sum(x => x.Achievement), | |
| 863 | + OrderAchievement = g.Where(x => x.BusinessType == "开卡").Sum(x => x.Achievement), | |
| 864 | + OrderItemCount = g.Where(x => x.BusinessType == "开卡").Sum(x => x.ItemCount), | |
| 865 | + ConsumeItemCount = g.Where(x => x.BusinessType == "耗卡").Sum(x => x.ItemCount), | |
| 866 | + } | |
| 867 | + ); | |
| 868 | + | |
| 869 | + // 4. 构建结果,包含所有老师 | |
| 870 | + var result = new List<TechTeacherSimpleStatisticsOutput>(); | |
| 871 | + | |
| 872 | + foreach (var teacher in allTeachers) | |
| 873 | + { | |
| 874 | + // 应用过滤条件 | |
| 875 | + if (!string.IsNullOrEmpty(input.TeacherId) && teacher.TeacherId != input.TeacherId) | |
| 876 | + continue; | |
| 877 | + | |
| 878 | + if (!string.IsNullOrEmpty(input.TeacherName) && !teacher.TeacherName.Contains(input.TeacherName)) | |
| 879 | + continue; | |
| 880 | + | |
| 881 | + var stats = teacherStatsDict.GetValueOrDefault( | |
| 882 | + new | |
| 883 | + { | |
| 884 | + TeacherId = teacher.TeacherId, | |
| 885 | + TeacherName = teacher.TeacherName, | |
| 886 | + TeacherAccount = teacher.TeacherAccount, | |
| 887 | + }, | |
| 888 | + new | |
| 889 | + { | |
| 890 | + ConsumeProjectCount = 0, | |
| 891 | + ConsumeAchievement = 0m, | |
| 892 | + OrderAchievement = 0m, | |
| 893 | + OrderItemCount = 0, | |
| 894 | + ConsumeItemCount = 0, | |
| 895 | + } | |
| 896 | + ); | |
| 897 | + | |
| 898 | + var teacherStats = new TechTeacherSimpleStatisticsOutput | |
| 899 | + { | |
| 900 | + DepartmentName = "科技部", // 固定为科技部 | |
| 901 | + TeacherName = teacher.TeacherName, | |
| 902 | + ConsumeProjectCount = stats.ConsumeProjectCount, | |
| 903 | + ConsumeAchievement = stats.ConsumeAchievement, | |
| 904 | + OrderAchievement = stats.OrderAchievement, | |
| 905 | + OrderItemCount = stats.OrderItemCount, | |
| 906 | + ConsumeItemCount = stats.ConsumeItemCount, | |
| 907 | + }; | |
| 908 | + | |
| 909 | + result.Add(teacherStats); | |
| 910 | + } | |
| 911 | + | |
| 912 | + return result; | |
| 913 | + } | |
| 914 | + catch (Exception ex) | |
| 915 | + { | |
| 916 | + _logger.LogError(ex, "获取科技部老师业绩统计时发生错误"); | |
| 917 | + throw NCCException.Oh("获取科技部老师业绩统计失败", ex); | |
| 918 | + } | |
| 919 | + } | |
| 920 | + | |
| 921 | + #endregion | |
| 922 | + | |
| 923 | + #region 匿名接口 | |
| 924 | + | |
| 925 | + /// <summary> | |
| 926 | + /// 发送每日统计消息(匿名接口) | |
| 927 | + /// </summary> | |
| 928 | + /// <returns>发送结果</returns> | |
| 929 | + [HttpPost("SendDailyReportMessage")] | |
| 930 | + [AllowAnonymous] | |
| 931 | + public async Task<object> SendDailyReportMessage() | |
| 932 | + { | |
| 933 | + try | |
| 934 | + { | |
| 935 | + // 获取本月全门店统计数据 | |
| 936 | + var monthlyStats = await GetMonthlyStoreStatistics(); | |
| 937 | + | |
| 938 | + // 构建包含统计数据的消息 | |
| 939 | + var messageContent = | |
| 940 | + $"📊 今日日报已生成,点击链接查看\n\n" | |
| 941 | + + $"本月全门店目标业绩:{monthlyStats.TargetPerformance:N0}元\n" | |
| 942 | + + $"本月已完成业绩:{monthlyStats.ActualPerformance:N0}元\n" | |
| 943 | + + $"完成率:{monthlyStats.CompletionRate:F2}%\n\n" | |
| 944 | + + $"http://lvqian.antissoft.com/html/dailyReportnew.html"; | |
| 945 | + | |
| 946 | + var result = await _weChatBotService.SendTextMessage(messageContent); | |
| 947 | + return new | |
| 948 | + { | |
| 949 | + success = result, | |
| 950 | + message = result ? "每日统计消息发送成功" : "每日统计消息发送失败", | |
| 951 | + timestamp = DateTime.Now, | |
| 952 | + statistics = monthlyStats, | |
| 953 | + }; | |
| 954 | + } | |
| 955 | + catch (Exception ex) | |
| 956 | + { | |
| 957 | + _logger.LogError(ex, "发送每日统计消息时发生错误"); | |
| 958 | + return new | |
| 959 | + { | |
| 960 | + success = false, | |
| 961 | + message = "发送每日统计消息时发生错误: " + ex.Message, | |
| 962 | + timestamp = DateTime.Now, | |
| 963 | + }; | |
| 964 | + } | |
| 965 | + } | |
| 966 | + | |
| 967 | + /// <summary> | |
| 968 | + /// 获取本月全门店统计数据 | |
| 969 | + /// </summary> | |
| 970 | + /// <returns>本月统计数据</returns> | |
| 971 | + private async Task<dynamic> GetMonthlyStoreStatistics() | |
| 972 | + { | |
| 973 | + try | |
| 974 | + { | |
| 975 | + // 获取本月开始和结束日期 | |
| 976 | + var now = DateTime.Now; | |
| 977 | + var startDate = new DateTime(now.Year, now.Month, 1); | |
| 978 | + var endDate = startDate.AddMonths(1).AddDays(-1); | |
| 979 | + | |
| 980 | + // 构建查询参数 | |
| 981 | + var parameters = new Dictionary<string, object> { { "@startDate", startDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", endDate.ToString("yyyy-MM-dd 23:59:59") } }; | |
| 982 | + | |
| 983 | + // 查询本月全门店统计数据 | |
| 984 | + var sql = | |
| 985 | + @" | |
| 986 | + SELECT | |
| 987 | + SUM(target_performance) AS TotalTargetPerformance, | |
| 988 | + SUM(actual_performance) AS TotalActualPerformance, | |
| 989 | + CASE | |
| 990 | + WHEN SUM(target_performance) > 0 | |
| 991 | + THEN (SUM(actual_performance) / SUM(target_performance)) * 100 | |
| 992 | + ELSE 0 | |
| 993 | + END AS TotalCompletionRate | |
| 994 | + FROM v_store_performance_simple"; | |
| 995 | + | |
| 996 | + var result = await _db.Ado.SqlQueryAsync<dynamic>(sql, parameters); | |
| 997 | + var stats = result.FirstOrDefault(); | |
| 998 | + | |
| 999 | + if (stats != null) | |
| 1000 | + { | |
| 1001 | + var targetPerformance = Convert.ToDecimal(stats.TotalTargetPerformance ?? 0); | |
| 1002 | + var actualPerformance = Convert.ToDecimal(stats.TotalActualPerformance ?? 0); | |
| 1003 | + var completionRate = Convert.ToDecimal(stats.TotalCompletionRate ?? 0); | |
| 1004 | + | |
| 1005 | + return new | |
| 1006 | + { | |
| 1007 | + TargetPerformance = targetPerformance, | |
| 1008 | + ActualPerformance = actualPerformance, | |
| 1009 | + CompletionRate = completionRate, | |
| 1010 | + Month = now.ToString("yyyy年MM月"), | |
| 1011 | + }; | |
| 1012 | + } | |
| 1013 | + | |
| 1014 | + return new | |
| 1015 | + { | |
| 1016 | + TargetPerformance = 0m, | |
| 1017 | + ActualPerformance = 0m, | |
| 1018 | + CompletionRate = 0m, | |
| 1019 | + Month = now.ToString("yyyy年MM月"), | |
| 1020 | + }; | |
| 1021 | + } | |
| 1022 | + catch (Exception ex) | |
| 1023 | + { | |
| 1024 | + _logger.LogError(ex, "获取本月全门店统计数据时发生错误"); | |
| 1025 | + return new | |
| 1026 | + { | |
| 1027 | + TargetPerformance = 0m, | |
| 1028 | + ActualPerformance = 0m, | |
| 1029 | + CompletionRate = 0m, | |
| 1030 | + Month = DateTime.Now.ToString("yyyy年MM月"), | |
| 1031 | + }; | |
| 1032 | + } | |
| 1033 | + } | |
| 1034 | + | |
| 1035 | + #endregion | |
| 596 | 1036 | } |
| 597 | 1037 | |
| 598 | 1038 | /// <summary> | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/Utils/WeChatBotService.cs
| ... | ... | @@ -34,14 +34,14 @@ namespace NCC.Extend.Utils |
| 34 | 34 | webhookUrl = WEBHOOK_URL, |
| 35 | 35 | content = content, |
| 36 | 36 | mentionedList = (string)null, |
| 37 | - mentionedMobileList = (string)null | |
| 37 | + mentionedMobileList = (string)null, | |
| 38 | 38 | }; |
| 39 | 39 | |
| 40 | 40 | var json = JsonConvert.SerializeObject(requestData); |
| 41 | 41 | var httpContent = new StringContent(json, Encoding.UTF8, "application/json"); |
| 42 | 42 | |
| 43 | 43 | var response = await _httpClient.PostAsync(BOT_API_URL, httpContent); |
| 44 | - | |
| 44 | + | |
| 45 | 45 | if (response.IsSuccessStatusCode) |
| 46 | 46 | { |
| 47 | 47 | var responseContent = await response.Content.ReadAsStringAsync(); |
| ... | ... | @@ -77,8 +77,28 @@ namespace NCC.Extend.Utils |
| 77 | 77 | |
| 78 | 78 | // 添加标题和格式化 |
| 79 | 79 | var messageContent = $"🎉 新开单记录\n\n{orderRecordString}"; |
| 80 | - | |
| 81 | 80 | return await SendTextMessage(messageContent); |
| 82 | 81 | } |
| 82 | + | |
| 83 | + /// <summary> | |
| 84 | + /// 发送每日统计消息 | |
| 85 | + /// </summary> | |
| 86 | + /// <returns>发送结果</returns> | |
| 87 | + public async Task<bool> SendDailyReportMessage() | |
| 88 | + { | |
| 89 | + try | |
| 90 | + { | |
| 91 | + var reportUrl = "http://lvqian.antissoft.com/html/dailyReportnew.html"; | |
| 92 | + var messageContent = $"📊 今日日报已生成,点击链接查看\n\n{reportUrl}"; | |
| 93 | + | |
| 94 | + Console.WriteLine("发送每日统计消息..."); | |
| 95 | + return await SendTextMessage(messageContent); | |
| 96 | + } | |
| 97 | + catch (Exception ex) | |
| 98 | + { | |
| 99 | + Console.WriteLine($"发送每日统计消息异常: {ex.Message}"); | |
| 100 | + return false; | |
| 101 | + } | |
| 102 | + } | |
| 83 | 103 | } |
| 84 | 104 | } | ... | ... |
创建经理门店业绩统计视图.sql deleted
| 1 | --- 创建经理门店业绩统计视图 | |
| 2 | --- 融合经理信息、管理门店、生命线设置、业绩流水数据 | |
| 3 | - | |
| 4 | -DROP VIEW IF EXISTS `v_manager_store_performance`; | |
| 5 | - | |
| 6 | -CREATE VIEW `v_manager_store_performance` AS | |
| 7 | -SELECT | |
| 8 | - -- 经理基础信息 | |
| 9 | - u.F_Id AS manager_user_id, -- 经理用户ID | |
| 10 | - u.F_REALNAME AS manager_name, -- 经理姓名 | |
| 11 | - u.F_GW AS manager_position, -- 经理岗位 | |
| 12 | - u.F_ORGANIZEID AS manager_organize_id, -- 经理组织ID | |
| 13 | - | |
| 14 | - -- 事业部信息 | |
| 15 | - o.F_Id AS business_unit_id, -- 事业部ID | |
| 16 | - o.F_FullName AS business_unit_name, -- 事业部名称 | |
| 17 | - o.F_ParentId AS parent_organize_id, -- 上级组织ID | |
| 18 | - parent.F_FullName AS parent_organize_name, -- 上级组织名称 | |
| 19 | - | |
| 20 | - -- 门店信息 | |
| 21 | - md.F_Id AS store_id, -- 门店ID | |
| 22 | - md.mdbm AS store_code, -- 门店编号 | |
| 23 | - md.dm AS store_name, -- 门店名称 | |
| 24 | - md.syb AS store_business_unit_id, -- 门店所属事业部ID | |
| 25 | - | |
| 26 | - -- 生命线设置信息 | |
| 27 | - COALESCE(zjl.smx1, 0) AS target_performance, -- 目标业绩(生命线1) | |
| 28 | - zjl.tcbl1 AS commission_rate1, -- 生命线1提成比例 | |
| 29 | - zjl.smx2 AS target_performance2, -- 目标业绩2(生命线2) | |
| 30 | - zjl.tcbl2 AS commission_rate2, -- 生命线2提成比例 | |
| 31 | - zjl.smx3 AS target_performance3, -- 目标业绩3(生命线3) | |
| 32 | - zjl.tcbl3 AS commission_rate3, -- 生命线3提成比例 | |
| 33 | - | |
| 34 | - -- 业绩流水信息(从现有视图获取) | |
| 35 | - flow.order_id, -- 开单ID | |
| 36 | - flow.order_date, -- 开单时间 | |
| 37 | - flow.completed_amount, -- 完成业绩(整单业绩) | |
| 38 | - flow.actual_amount, -- 实付业绩 | |
| 39 | - flow.debt_amount, -- 欠款 | |
| 40 | - flow.completion_rate, -- 完成率 | |
| 41 | - flow.golden_triangle, -- 金三角 | |
| 42 | - flow.member_id, -- 开单会员ID | |
| 43 | - flow.member_name, -- 开单会员名称 | |
| 44 | - flow.member_phone, -- 开单会员手机号 | |
| 45 | - flow.customer_type, -- 顾客类型 | |
| 46 | - flow.payment_method, -- 付款方式 | |
| 47 | - flow.customer_source, -- 客户来源 | |
| 48 | - | |
| 49 | - -- 时间维度 | |
| 50 | - flow.order_year, -- 开单年份 | |
| 51 | - flow.order_month, -- 开单月份 | |
| 52 | - flow.order_quarter, -- 开单季度 | |
| 53 | - flow.order_date_only, -- 开单日期(不含时间) | |
| 54 | - | |
| 55 | - -- 统计标识 | |
| 56 | - CASE | |
| 57 | - WHEN flow.order_id IS NOT NULL THEN 1 | |
| 58 | - ELSE 0 | |
| 59 | - END AS has_performance, -- 是否有业绩记录 | |
| 60 | - | |
| 61 | - -- 创建时间 | |
| 62 | - COALESCE(flow.create_time, NOW()) AS create_time, | |
| 63 | - COALESCE(flow.modify_time, NOW()) AS modify_time | |
| 64 | - | |
| 65 | -FROM base_user u | |
| 66 | --- 关联组织信息 | |
| 67 | -LEFT JOIN base_organize o ON u.F_ORGANIZEID = o.F_Id | |
| 68 | -LEFT JOIN base_organize parent ON o.F_ParentId = parent.F_Id | |
| 69 | --- 关联门店信息(通过事业部关联) | |
| 70 | -LEFT JOIN lq_mdxx md ON md.syb = o.F_Id | |
| 71 | --- 关联生命线设置 | |
| 72 | -LEFT JOIN lq_zjl_mdsmxsz zjl ON zjl.zjl_userid = u.F_Id | |
| 73 | - AND zjl.md_id = md.F_Id | |
| 74 | - AND zjl.deletemark = 0 | |
| 75 | --- 关联业绩流水(从现有视图) | |
| 76 | -LEFT JOIN v_department_performance_flow flow ON flow.store_id = md.F_Id | |
| 77 | - AND flow.department_id = o.F_Id | |
| 78 | - | |
| 79 | -WHERE u.F_DELETEMARK IS NULL -- 用户未删除 | |
| 80 | - AND u.F_GW IS NOT NULL -- 有岗位信息 | |
| 81 | - AND (u.F_GW LIKE '%经理%' OR u.F_GW LIKE '%总经理%' OR u.F_GW LIKE '%主管%') -- 经理岗位 | |
| 82 | - AND o.F_Category = 'department' -- 部门类型 | |
| 83 | - AND (o.F_DeleteMark IS NULL OR o.F_DeleteMark != 1) -- 组织未删除 | |
| 84 | - AND md.F_Id IS NOT NULL; -- 有门店信息 | |
| 85 | - | |
| 86 | --- 添加视图注释 | |
| 87 | ---ALTER VIEW `v_manager_store_performance` COMMENT = '经理门店业绩统计视图 - 融合经理信息、管理门店、生命线设置、业绩流水数据'; |
创建退卡相关表.sql deleted
| 1 | --- ============================================= | |
| 2 | --- 绿纤美业ERP系统 - 退卡相关表创建脚本 | |
| 3 | --- 创建时间: 2025-01-27 | |
| 4 | --- 说明: 创建会员退卡主表、明细表、业绩表 | |
| 5 | --- ============================================= | |
| 6 | - | |
| 7 | --- 1. 创建会员退卡主表 | |
| 8 | -DROP TABLE IF EXISTS `lq_hytk_hytk`; | |
| 9 | -CREATE TABLE `lq_hytk_hytk` ( | |
| 10 | - `F_Id` varchar(50) NOT NULL COMMENT '退卡编号', | |
| 11 | - `md` varchar(50) DEFAULT NULL COMMENT '门店', | |
| 12 | - `mdbh` varchar(50) DEFAULT NULL COMMENT '门店编号', | |
| 13 | - `mdmc` varchar(50) DEFAULT NULL COMMENT '门店名称', | |
| 14 | - `hy` varchar(50) DEFAULT NULL COMMENT '会员', | |
| 15 | - `hyzh` varchar(50) DEFAULT NULL COMMENT '会员账号', | |
| 16 | - `hymc` varchar(50) DEFAULT NULL COMMENT '会员名称', | |
| 17 | - `gklx` varchar(50) DEFAULT NULL COMMENT '顾客类型', | |
| 18 | - `tkje` decimal(15,2) DEFAULT NULL COMMENT '退卡总金额', | |
| 19 | - `sgfy` decimal(15,2) DEFAULT NULL COMMENT '手工费用', | |
| 20 | - `bz` text COMMENT '备注', | |
| 21 | - `tksj` datetime DEFAULT NULL COMMENT '退卡时间', | |
| 22 | - `czry` varchar(50) DEFAULT NULL COMMENT '操作人员', | |
| 23 | - `tkzt` varchar(20) DEFAULT NULL COMMENT '退卡状态', | |
| 24 | - `tkyy` varchar(200) DEFAULT NULL COMMENT '退卡原因', | |
| 25 | - `F_CreateTime` datetime DEFAULT NULL COMMENT '创建时间', | |
| 26 | - `F_CreateUser` varchar(50) DEFAULT NULL COMMENT '创建用户', | |
| 27 | - `F_ModifyTime` datetime DEFAULT NULL COMMENT '修改时间', | |
| 28 | - `F_ModifyUser` varchar(50) DEFAULT NULL COMMENT '修改用户', | |
| 29 | - `F_DeleteMark` int(1) DEFAULT NULL COMMENT '删除标记', | |
| 30 | - PRIMARY KEY (`F_Id`), | |
| 31 | - KEY `idx_md` (`md`), | |
| 32 | - KEY `idx_hy` (`hy`), | |
| 33 | - KEY `idx_tksj` (`tksj`), | |
| 34 | - KEY `idx_tkzt` (`tkzt`) | |
| 35 | -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='退卡_信息表'; | |
| 36 | - | |
| 37 | --- 2. 创建会员退卡明细表 | |
| 38 | -DROP TABLE IF EXISTS `lq_hytk_mx`; | |
| 39 | -CREATE TABLE `lq_hytk_mx` ( | |
| 40 | - `F_Id` varchar(50) NOT NULL COMMENT '明细编号', | |
| 41 | - `gltkbh` varchar(50) DEFAULT NULL COMMENT '关联退卡编号', | |
| 42 | - `px` varchar(50) DEFAULT NULL COMMENT '品项', | |
| 43 | - `pxmc` varchar(100) DEFAULT NULL COMMENT '品项名称', | |
| 44 | - `pxjg` decimal(15,2) DEFAULT NULL COMMENT '品项价格', | |
| 45 | - `tkje` decimal(15,2) DEFAULT NULL COMMENT '退款金额', | |
| 46 | - `F_ProjectNumber` int DEFAULT NULL COMMENT '项目次数', | |
| 47 | - `F_IsEnabled` int(1) DEFAULT NULL COMMENT '是否有效', | |
| 48 | - `F_SourceType` varchar(20) DEFAULT NULL COMMENT '来源类型', | |
| 49 | - `F_TotalPrice` decimal(15,2) DEFAULT NULL COMMENT '合计金额', | |
| 50 | - `F_CreateTime` datetime DEFAULT NULL COMMENT '创建时间', | |
| 51 | - `F_CreateUser` varchar(50) DEFAULT NULL COMMENT '创建用户', | |
| 52 | - `F_ModifyTime` datetime DEFAULT NULL COMMENT '修改时间', | |
| 53 | - `F_ModifyUser` varchar(50) DEFAULT NULL COMMENT '修改用户', | |
| 54 | - `F_DeleteMark` int(1) DEFAULT NULL COMMENT '删除标记', | |
| 55 | - PRIMARY KEY (`F_Id`), | |
| 56 | - KEY `idx_gltkbh` (`gltkbh`), | |
| 57 | - KEY `idx_px` (`px`), | |
| 58 | - KEY `idx_F_SourceType` (`F_SourceType`) | |
| 59 | -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='退卡_品项明细表'; | |
| 60 | - | |
| 61 | --- 3. 创建退卡健康师业绩表 | |
| 62 | -DROP TABLE IF EXISTS `lq_hytk_jksyj`; | |
| 63 | -CREATE TABLE `lq_hytk_jksyj` ( | |
| 64 | - `F_Id` varchar(50) NOT NULL COMMENT '业绩编号', | |
| 65 | - `gltkbh` varchar(50) DEFAULT NULL COMMENT '关联退卡编号', | |
| 66 | - `jks` varchar(50) DEFAULT NULL COMMENT '健康师', | |
| 67 | - `jksxm` varchar(50) DEFAULT NULL COMMENT '健康师姓名', | |
| 68 | - `jkszh` varchar(50) DEFAULT NULL COMMENT '健康师账号', | |
| 69 | - `jksyj` decimal(15,2) DEFAULT NULL COMMENT '健康师业绩', | |
| 70 | - `tksj` datetime DEFAULT NULL COMMENT '退卡时间', | |
| 71 | - `F_jsjid` varchar(50) DEFAULT NULL COMMENT '金三角id', | |
| 72 | - `F_tkpxid` varchar(50) DEFAULT NULL COMMENT '关联项目资料表ID', | |
| 73 | - `F_LaborCost` decimal(15,2) DEFAULT NULL COMMENT '手工费', | |
| 74 | - `F_tkpxNumber` decimal(15,2) DEFAULT NULL COMMENT '退卡品项次数', | |
| 75 | - `F_CreateTime` datetime DEFAULT NULL COMMENT '创建时间', | |
| 76 | - `F_CreateUser` varchar(50) DEFAULT NULL COMMENT '创建用户', | |
| 77 | - `F_ModifyTime` datetime DEFAULT NULL COMMENT '修改时间', | |
| 78 | - `F_ModifyUser` varchar(50) DEFAULT NULL COMMENT '修改用户', | |
| 79 | - `F_DeleteMark` int(1) DEFAULT NULL COMMENT '删除标记', | |
| 80 | - PRIMARY KEY (`F_Id`), | |
| 81 | - KEY `idx_gltkbh` (`gltkbh`), | |
| 82 | - KEY `idx_jks` (`jks`), | |
| 83 | - KEY `idx_F_tkpxid` (`F_tkpxid`), | |
| 84 | - KEY `idx_tksj` (`tksj`) | |
| 85 | -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='退卡_健康师业绩表'; | |
| 86 | - | |
| 87 | --- 4. 创建退卡科技部老师业绩表 | |
| 88 | -DROP TABLE IF EXISTS `lq_hytk_kjbsyj`; | |
| 89 | -CREATE TABLE `lq_hytk_kjbsyj` ( | |
| 90 | - `F_Id` varchar(50) NOT NULL COMMENT '业绩编号', | |
| 91 | - `gltkbh` varchar(50) DEFAULT NULL COMMENT '关联退卡编号', | |
| 92 | - `kjbls` varchar(50) DEFAULT NULL COMMENT '科技部老师', | |
| 93 | - `kjblsxm` varchar(50) DEFAULT NULL COMMENT '科技部老师姓名', | |
| 94 | - `kjblszh` varchar(50) DEFAULT NULL COMMENT '科技部老师账号', | |
| 95 | - `kjblsyj` decimal(15,2) DEFAULT NULL COMMENT '科技部老师业绩', | |
| 96 | - `tksj` datetime DEFAULT NULL COMMENT '退卡时间', | |
| 97 | - `F_tkpxid` varchar(50) DEFAULT NULL COMMENT '关联项目资料表ID', | |
| 98 | - `F_LaborCost` decimal(15,2) DEFAULT NULL COMMENT '手工费', | |
| 99 | - `F_tkpxNumber` decimal(15,2) DEFAULT NULL COMMENT '退卡品项次数', | |
| 100 | - `F_CreateTime` datetime DEFAULT NULL COMMENT '创建时间', | |
| 101 | - `F_CreateUser` varchar(50) DEFAULT NULL COMMENT '创建用户', | |
| 102 | - `F_ModifyTime` datetime DEFAULT NULL COMMENT '修改时间', | |
| 103 | - `F_ModifyUser` varchar(50) DEFAULT NULL COMMENT '修改用户', | |
| 104 | - `F_DeleteMark` int(1) DEFAULT NULL COMMENT '删除标记', | |
| 105 | - PRIMARY KEY (`F_Id`), | |
| 106 | - KEY `idx_gltkbh` (`gltkbh`), | |
| 107 | - KEY `idx_kjbls` (`kjbls`), | |
| 108 | - KEY `idx_F_tkpxid` (`F_tkpxid`), | |
| 109 | - KEY `idx_tksj` (`tksj`) | |
| 110 | -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='退卡_科技部老师业绩表'; | |
| 111 | - | |
| 112 | --- ============================================= | |
| 113 | --- 添加外键约束(可选) | |
| 114 | --- ============================================= | |
| 115 | - | |
| 116 | --- 退卡明细表外键约束 | |
| 117 | --- ALTER TABLE `lq_hytk_mx` ADD CONSTRAINT `fk_hytk_mx_gltkbh` FOREIGN KEY (`gltkbh`) REFERENCES `lq_hytk_hytk` (`F_Id`) ON DELETE CASCADE ON UPDATE CASCADE; | |
| 118 | - | |
| 119 | --- 退卡健康师业绩表外键约束 | |
| 120 | --- ALTER TABLE `lq_hytk_jksyj` ADD CONSTRAINT `fk_hytk_jksyj_gltkbh` FOREIGN KEY (`gltkbh`) REFERENCES `lq_hytk_hytk` (`F_Id`) ON DELETE CASCADE ON UPDATE CASCADE; | |
| 121 | --- ALTER TABLE `lq_hytk_jksyj` ADD CONSTRAINT `fk_hytk_jksyj_tkpxid` FOREIGN KEY (`F_tkpxid`) REFERENCES `lq_xmzl` (`F_Id`) ON DELETE CASCADE ON UPDATE CASCADE; | |
| 122 | - | |
| 123 | --- 退卡科技部老师业绩表外键约束 | |
| 124 | --- ALTER TABLE `lq_hytk_kjbsyj` ADD CONSTRAINT `fk_hytk_kjbsyj_gltkbh` FOREIGN KEY (`gltkbh`) REFERENCES `lq_hytk_hytk` (`F_Id`) ON DELETE CASCADE ON UPDATE CASCADE; | |
| 125 | --- ALTER TABLE `lq_hytk_kjbsyj` ADD CONSTRAINT `fk_hytk_kjbsyj_tkpxid` FOREIGN KEY (`F_tkpxid`) REFERENCES `lq_xmzl` (`F_Id`) ON DELETE CASCADE ON UPDATE CASCADE; | |
| 126 | - | |
| 127 | --- ============================================= | |
| 128 | --- 创建完成提示 | |
| 129 | --- ============================================= | |
| 130 | -SELECT '退卡相关表创建完成!' AS '创建结果'; |