Commit e96beca8aecd10686f265a2aa8c9d398e866b95f

Authored by “wangming”
1 parent 87aea27c

更新多个.DS_Store文件,删除不再使用的SQL视图文件,重构LqStatisticsService和WeChatBotService,新增门店开单业绩统计…

…和科技部老师业绩统计功能,优化查询逻辑和代码结构,确保代码整洁性和功能完整性。
.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 '创建结果';