using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using NCC.Common.Core.Manager;
using NCC.Common.Enum;
using NCC.Common.Extension;
using NCC.Common.Filter;
using NCC.Dependency;
using NCC.DynamicApiController;
using NCC.Extend.Entitys.Dto.LqMdxx;
using NCC.Extend.Entitys.Dto.LqStatistics;
using NCC.Extend.Entitys.Dto.LqStatistics.DepartmentInfo;
using NCC.Extend.Entitys.Dto.LqStatisticsStoreConsumePerformance;
using NCC.Extend.Entitys.Dto.LqStatisticsStoreTotalPerformance;
using NCC.Extend.Entitys.Dto.LqStatisticsTechPerformance;
using NCC.Extend.Entitys.Dto.LqSalaryStatistics;
using NCC.Extend.Entitys.Dto.LqStatisticsDepartmentConsumePerformance;
using NCC.Extend.Entitys.Dto.LqYcsdJsj;
using NCC.Extend.Entitys.lq_hytk_kjbsyj;
using NCC.Extend.Entitys.lq_jinsanjiao_user;
using NCC.Extend.Entitys.lq_kd_jksyj;
using NCC.Extend.Entitys.lq_kd_kdjlb;
using NCC.Extend.Entitys.lq_kd_kjbsyj;
using NCC.Extend.Entitys.lq_mdxx;
using NCC.Extend.Entitys.lq_md_target;
using NCC.Extend.Entitys.lq_hytk_hytk;
using NCC.Extend.Entitys.lq_md_xdbhsj;
using NCC.Extend.Entitys.lq_xh_kjbsyj;
using NCC.Extend.Entitys.lq_xh_hyhk;
using NCC.Extend.Entitys.lq_xh_pxmx;
using NCC.Extend.Entitys.lq_ycsd_jsj;
using NCC.Extend.Entitys.lq_yjmxb;
using NCC.Extend.Entitys.Enum;
using NCC.Extend.Entitys.lq_statistics_gold_triangle;
using NCC.Extend.Entitys.lq_statistics_personal_performance;
using NCC.Extend.Entitys.lq_statistics_store_consume_performance;
using NCC.Extend.Entitys.lq_statistics_store_total_performance;
using NCC.Extend.Entitys.lq_statistics_tech_performance;
using NCC.Extend.Entitys.lq_salary_statistics;
using NCC.Extend.Entitys.lq_statistics_department_consume_performance;
using NCC.Extend.Entitys.lq_xmzl;
using NCC.Extend.Entitys.Dto.LqStatisticsPersonalPerformance;
using NCC.Extend.Entitys.v_tech_teacher_flow;
using NCC.Extend.Interfaces.LqStatistics;
using NCC.Extend.Utils;
using NCC.FriendlyException;
using NCC.System.Entitys.Permission;
using SqlSugar;
using Yitter.IdGenerator;
using NCC.Extend.Entitys.lq_kd_pxmx;
using NCC.Extend.Entitys.lq_khxx;
using NCC.Extend.Entitys.lq_tkjlb;
using NCC.Extend.Entitys.lq_yaoyjl;
using NCC.Extend.Entitys.lq_yyjl;
using NCC.Extend.Entitys.lq_store_manager_salary_statistics;
using NCC.System.Entitys.System;
namespace NCC.Extend.LqStatistics
{
///
/// 绿纤统计服务
///
[ApiDescriptionSettings(Tag = "绿纤统计服务", Name = "LqStatistics", Order = 200, Groups = new[] { "Default" })]
[Route("api/Extend/[controller]")]
public class LqStatisticsService : ILqStatisticsService, IDynamicApiController, ITransient
{
private readonly ISqlSugarRepository _lqMdxxRepository;
private readonly SqlSugarScope _db;
private readonly IUserManager _userManager;
private readonly ILogger _logger;
private readonly WeChatBotService _weChatBotService;
///
/// 初始化一个类型的新实例
///
public LqStatisticsService(ISqlSugarRepository lqMdxxRepository, IUserManager userManager, ILogger logger, WeChatBotService weChatBotService)
{
_lqMdxxRepository = lqMdxxRepository;
_db = _lqMdxxRepository.Context;
_userManager = userManager;
_logger = logger;
_weChatBotService = weChatBotService;
}
#region 获取门店耗卡业绩统计列表
///
/// 获取门店业绩统计列表
///
///
/// 获取所有门店的耗卡业绩统计信息,包括门店ID、名称、编码、目标业绩、耗卡业绩、完成率等关键指标
///
/// 返回数据说明:
/// - StoreId: 门店ID
/// - StoreName: 门店名称
/// - StoreCode: 门店编码
/// - BusinessUnitId: 事业部ID(暂未关联)
/// - BusinessUnitName: 事业部名称(暂未关联)
/// - TargetPerformance: 目标业绩(门店生命线)
/// - ActualPerformance: 耗卡业绩(当月耗卡金额汇总)
/// - CompletionRate: 完成率(耗卡业绩/目标业绩*100)
/// - OrderCount: 耗卡记录数(当月耗卡记录数)
///
/// 数据来源:v_store_consume_performance_simple 视图
///
/// 门店业绩统计列表
/// 成功返回门店业绩统计列表
/// 服务器内部错误
[HttpGet("GetStorePerformanceList")]
[AllowAnonymous]
public async Task> GetStorePerformanceList()
{
try
{
_logger.LogInformation("开始查询门店业绩统计列表");
// 使用耗卡业绩统计视图
var storeList = await _db.Ado.SqlQueryAsync(
"SELECT "
+ "store_id AS StoreId, "
+ "store_code AS StoreCode, "
+ "store_name AS StoreName, "
+ "'' AS BusinessUnitId, "
+ "'' AS BusinessUnitName, "
+ "target_performance AS TargetPerformance, "
+ "actual_performance AS ActualPerformance, "
+ "completion_rate AS CompletionRate, "
+ "order_count AS OrderCount "
+ "FROM v_store_consume_performance_simple "
+ "ORDER BY actual_performance DESC"
);
_logger.LogInformation("门店业绩统计列表查询完成,返回{Count}条记录", storeList.Count);
return storeList;
}
catch (Exception ex)
{
_logger.LogError(ex, "查询门店业绩统计列表时发生错误");
throw NCCException.Oh("查询门店业绩统计列表失败", ex);
}
}
#endregion
#region 获取门店开单业绩统计列表
///
/// 获取门店开单业绩统计列表
///
///
/// 获取所有门店的开单业绩统计信息,包括门店ID、名称、编码、目标业绩、开单业绩、完成率等关键指标
///
/// 返回数据说明:
/// - StoreId: 门店ID
/// - StoreName: 门店名称
/// - StoreCode: 门店编码
/// - BusinessUnitId: 事业部ID(暂未关联)
/// - BusinessUnitName: 事业部名称(暂未关联)
/// - TargetPerformance: 目标业绩(门店生命线)
/// - ActualPerformance: 开单业绩(当月开单金额汇总)
/// - CompletionRate: 完成率(开单业绩/目标业绩*100)
/// - OrderCount: 开单记录数(当月开单记录数)
///
/// 数据来源:v_store_performance_simple 视图
///
/// 门店开单业绩统计列表
/// 成功返回门店开单业绩统计列表
/// 服务器内部错误
[HttpGet("GetStoreOrderPerformanceList")]
[AllowAnonymous]
public async Task> GetStoreOrderPerformanceList()
{
try
{
_logger.LogInformation("开始查询门店开单业绩统计列表");
// 使用开单业绩统计视图
var storeList = await _db.Ado.SqlQueryAsync(
"SELECT "
+ "store_id AS StoreId, "
+ "store_code AS StoreCode, "
+ "store_name AS StoreName, "
+ "'' AS BusinessUnitId, "
+ "'' AS BusinessUnitName, "
+ "target_performance AS TargetPerformance, "
+ "actual_performance AS ActualPerformance, "
+ "completion_rate AS CompletionRate, "
+ "order_count AS OrderCount "
+ "FROM v_store_performance_simple "
+ "ORDER BY actual_performance DESC"
);
_logger.LogInformation("门店开单业绩统计列表查询完成,返回{Count}条记录", storeList.Count);
return storeList ?? new List();
}
catch (Exception ex)
{
_logger.LogError(ex, "查询门店开单业绩统计列表时发生错误");
throw NCCException.Oh("查询门店开单业绩统计列表失败", ex);
}
}
#endregion
#region 获取门店统计信息
///
/// 获取门店统计信息
///
///
/// 根据指定日期范围和门店ID查询门店的详细业绩统计信息,包括目标业绩、完成业绩、完成率等
///
/// 示例请求:
/// ```json
/// {
/// "startDate": "2025-01-01T00:00:00",
/// "endDate": "2025-01-31T23:59:59",
/// "storeId": "门店ID(可选)"
/// }
/// ```
///
/// 参数说明:
/// - startDate: 开始日期,格式:yyyy-MM-ddTHH:mm:ss
/// - endDate: 结束日期,格式:yyyy-MM-ddTHH:mm:ss
/// - storeId: 门店ID,可选参数,不传则查询所有门店
///
/// 返回数据说明:
/// - StoreId: 门店ID
/// - StoreName: 门店名称
/// - StoreCode: 门店编码
/// - BusinessUnitId: 事业部ID
/// - BusinessUnitName: 事业部名称
/// - TargetPerformance: 目标业绩
/// - ActualPerformance: 完成业绩
/// - OrderCount: 开单数量
/// - CompletionRate: 完成率(%)
///
/// 查询参数
/// 门店统计结果
/// 成功返回门店统计数据
/// 请求参数错误
/// 服务器内部错误
[HttpPost("StoreStatistics")]
[AllowAnonymous]
public async Task GetStoreStatistics(StoreStatisticsInput input)
{
try
{
_logger.LogInformation("开始查询门店统计信息,查询日期:{StartDate} - {EndDate},门店ID:{StoreId}", input.StartDate, input.EndDate, input.StoreId);
// 构建查询参数
var parameters = new Dictionary { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } };
// 构建WHERE条件
var whereClause = "WHERE 1=1";
if (!string.IsNullOrEmpty(input.StoreId))
{
whereClause += " AND store_id = @storeId";
parameters.Add("@storeId", input.StoreId);
}
// 使用SQL查询门店统计信息,包含日期范围过滤
var sql =
$@"
SELECT
store_id AS StoreId,
store_code AS StoreCode,
store_name AS StoreName,
'' AS BusinessUnitId,
'' AS BusinessUnitName,
target_performance AS TargetPerformance,
actual_performance AS ActualPerformance,
completion_rate AS CompletionRate,
order_count AS OrderCount
FROM v_store_performance_simple
{whereClause}
ORDER BY actual_performance DESC";
_logger.LogInformation("执行SQL查询:{Sql}", sql);
_logger.LogInformation("查询参数:{Parameters}", string.Join(", ", parameters.Select(p => $"{p.Key}={p.Value}")));
var results = await _db.Ado.SqlQueryAsync(sql, parameters);
_logger.LogInformation("查询到门店统计数据数量:{Count}", results.Count);
// 转换为输出格式
var storeList = results
.Select(r => new StoreStatisticsInfo
{
StoreId = r.StoreId?.ToString() ?? "",
StoreName = r.StoreName?.ToString() ?? "",
StoreCode = r.StoreCode?.ToString() ?? "",
BusinessUnitId = r.BusinessUnitId?.ToString() ?? "",
BusinessUnitName = r.BusinessUnitName?.ToString() ?? "",
TargetPerformance = Convert.ToDecimal(r.TargetPerformance ?? 0),
ActualPerformance = Convert.ToDecimal(r.ActualPerformance ?? 0),
OrderCount = Convert.ToInt32(r.OrderCount ?? 0),
CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0),
})
.ToList();
_logger.LogInformation("门店统计信息查询完成,返回{Count}条记录", storeList.Count);
return new StoreStatisticsOutput { StoreList = storeList, TotalCount = storeList.Count };
}
catch (Exception ex)
{
_logger.LogError(ex, "查询门店统计信息时发生错误,查询日期:{StartDate} - {EndDate},门店ID:{StoreId}", input.StartDate, input.EndDate, input.StoreId);
throw NCCException.Oh("查询门店统计信息失败", ex);
}
}
#endregion
#region 获取事业部业绩统计
///
/// 获取事业部业绩统计
///
///
/// 根据指定日期范围和事业部ID查询事业部的业绩统计信息,包括目标业绩总和、完成业绩总和、完成率等
///
/// 示例请求:
/// ```json
/// {
/// "startDate": "2025-01-01T00:00:00",
/// "endDate": "2025-01-31T23:59:59",
/// "businessUnitId": "事业部ID(可选)"
/// }
/// ```
///
/// 参数说明:
/// - startDate: 开始日期,格式:yyyy-MM-ddTHH:mm:ss
/// - endDate: 结束日期,格式:yyyy-MM-ddTHH:mm:ss
/// - businessUnitId: 事业部ID,可选参数,不传则查询所有事业部
///
/// 返回数据说明:
/// - DepartmentId: 部门ID
/// - DepartmentName: 部门名称
/// - ParentId: 父部门ID
/// - ParentName: 父部门名称
/// - TotalTargetAmount: 目标业绩总和
/// - TotalActualAmount: 完成业绩总和
/// - TotalOrderCount: 开单总数量
/// - CompletionRate: 完成率(%)
///
/// 查询参数
/// 事业部业绩统计结果
/// 成功返回事业部业绩统计数据
/// 请求参数错误
/// 服务器内部错误
[HttpPost("BusinessUnitStatistics")]
[AllowAnonymous]
public async Task GetBusinessUnitStatistics(BusinessUnitStatisticsInput input)
{
try
{
_logger.LogInformation("开始查询事业部业绩统计,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
// 构建查询参数
var parameters = new Dictionary { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } };
// 构建WHERE条件
var whereClause = "WHERE 1=1";
if (!string.IsNullOrEmpty(input.BusinessUnitId))
{
whereClause += " AND dept.F_Id = @businessUnitId";
parameters.Add("@businessUnitId", input.BusinessUnitId);
}
// 构建SQL查询 - 先查询所有事业部,然后左连接业绩数据
var sql =
$@"
SELECT
dept.F_Id AS DepartmentId,
dept.F_FullName AS DepartmentName,
dept.F_ParentId AS ParentId,
parent.F_FullName AS ParentName,
COALESCE(SUM(flow.actual_amount), 0) AS TotalActualAmount,
COALESCE(COUNT(flow.order_id), 0) AS TotalOrderCount,
CASE
WHEN COALESCE(SUM(flow.actual_amount), 0) > 0
THEN ROUND((COALESCE(SUM(flow.actual_amount), 0) / 100000) * 100, 2)
ELSE 0
END AS CompletionRate
FROM base_organize dept
LEFT JOIN base_organize parent ON dept.F_ParentId = parent.F_Id
LEFT JOIN v_department_performance_flow flow ON dept.F_Id = flow.department_id
AND (flow.order_date >= @startDate AND flow.order_date <= @endDate OR flow.order_date IS NULL)
WHERE dept.F_ParentId = (SELECT F_Id FROM base_organize WHERE F_FullName = '事业部')
AND dept.F_EnabledMark = 1
AND dept.F_DeleteMark IS NULL
{whereClause.Replace("WHERE 1=1", "")}
GROUP BY
dept.F_Id,
dept.F_FullName,
dept.F_ParentId,
parent.F_FullName
ORDER BY TotalActualAmount DESC";
_logger.LogInformation("执行SQL查询:{Sql}", sql);
_logger.LogInformation("查询参数:{Parameters}", string.Join(", ", parameters.Select(p => $"{p.Key}={p.Value}")));
var results = await _db.Ado.SqlQueryAsync(sql, parameters);
_logger.LogInformation("查询到事业部业绩数据数量:{Count}", results.Count);
// 转换为输出格式
var businessUnitList = results
.Select(r => new BusinessUnitStatisticsInfo
{
DepartmentId = r.DepartmentId?.ToString() ?? "",
DepartmentName = r.DepartmentName?.ToString() ?? "",
ParentId = r.ParentId?.ToString() ?? "",
ParentName = r.ParentName?.ToString() ?? "",
TotalTargetAmount = 100000, // 默认目标业绩10万
TotalActualAmount = Convert.ToDecimal(r.TotalActualAmount ?? 0),
TotalOrderCount = Convert.ToInt32(r.TotalOrderCount ?? 0),
CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0),
})
.ToList();
_logger.LogInformation("事业部业绩统计查询完成,返回{Count}条记录", businessUnitList.Count);
return new BusinessUnitStatisticsOutput { BusinessUnitList = businessUnitList, TotalCount = businessUnitList.Count };
}
catch (Exception ex)
{
_logger.LogError(ex, "查询事业部业绩统计时发生错误,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
throw NCCException.Oh("查询事业部业绩统计失败", ex);
}
}
#endregion
#region 获取其他部门业绩统计
///
/// 获取其他部门业绩统计
///
///
/// 根据指定日期范围和部门ID查询其他部门(教育部、科技部、大项目部)的业绩统计信息
///
/// 示例请求:
/// ```json
/// {
/// "startDate": "2025-01-01T00:00:00",
/// "endDate": "2025-01-31T23:59:59",
/// "departmentId": "部门ID(可选)"
/// }
/// ```
///
/// 参数说明:
/// - startDate: 开始日期,格式:yyyy-MM-ddTHH:mm:ss
/// - endDate: 结束日期,格式:yyyy-MM-ddTHH:mm:ss
/// - departmentId: 部门ID,可选参数,不传则查询所有其他部门
///
/// 返回数据说明:
/// - DepartmentId: 部门ID
/// - DepartmentName: 部门名称
/// - ParentId: 父部门ID
/// - ParentName: 父部门名称
/// - TotalTargetAmount: 目标业绩总和
/// - TotalActualAmount: 完成业绩总和
/// - TotalOrderCount: 开单总数量
/// - CompletionRate: 完成率(%)
///
/// 查询参数
/// 其他部门业绩统计结果
/// 成功返回其他部门业绩统计数据
/// 请求参数错误
/// 服务器内部错误
[HttpPost("OtherDepartmentStatistics")]
[AllowAnonymous]
public async Task GetOtherDepartmentStatistics(OtherDepartmentStatisticsInput input)
{
try
{
_logger.LogInformation("开始查询其他部门业绩统计,查询日期:{StartDate} - {EndDate},部门ID:{DepartmentId}", input.StartDate, input.EndDate, input.DepartmentId);
// 构建查询参数
var parameters = new Dictionary { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } };
// 构建WHERE条件
var whereClause = "WHERE 1=1";
if (!string.IsNullOrEmpty(input.DepartmentId))
{
whereClause += " AND dept.F_Id = @departmentId";
parameters.Add("@departmentId", input.DepartmentId);
}
// 构建SQL查询 - 先查询所有其他部门的子部门,然后左连接业绩数据
var sql =
$@"
SELECT
dept.F_Id AS DepartmentId,
dept.F_FullName AS DepartmentName,
dept.F_ParentId AS ParentId,
parent.F_FullName AS ParentName,
COALESCE(SUM(flow.actual_amount), 0) AS TotalActualAmount,
COALESCE(COUNT(flow.order_id), 0) AS TotalOrderCount,
CASE
WHEN COALESCE(SUM(flow.actual_amount), 0) > 0
THEN ROUND((COALESCE(SUM(flow.actual_amount), 0) / 50000) * 100, 2)
ELSE 0
END AS CompletionRate
FROM base_organize dept
LEFT JOIN base_organize parent ON dept.F_ParentId = parent.F_Id
LEFT JOIN v_other_department_performance_flow flow ON dept.F_Id = flow.department_id
AND (flow.order_date >= @startDate AND flow.order_date <= @endDate OR flow.order_date IS NULL)
WHERE dept.F_ParentId IN (SELECT F_Id FROM base_organize WHERE F_FullName IN ('教育部', '科技部', '大项目部'))
AND dept.F_EnabledMark = 1
AND dept.F_DeleteMark IS NULL
{whereClause.Replace("WHERE 1=1", "")}
GROUP BY
dept.F_Id,
dept.F_FullName,
dept.F_ParentId,
parent.F_FullName
ORDER BY TotalActualAmount DESC";
_logger.LogInformation("执行SQL查询:{Sql}", sql);
_logger.LogInformation("查询参数:{Parameters}", string.Join(", ", parameters.Select(p => $"{p.Key}={p.Value}")));
var results = await _db.Ado.SqlQueryAsync(sql, parameters);
_logger.LogInformation("查询到其他部门业绩数据数量:{Count}", results.Count);
// 转换为输出格式
var departmentList = results
.Select(r => new OtherDepartmentStatisticsInfo
{
DepartmentId = r.DepartmentId?.ToString() ?? "",
DepartmentName = r.DepartmentName?.ToString() ?? "",
ParentId = r.ParentId?.ToString() ?? "",
ParentName = r.ParentName?.ToString() ?? "",
TotalTargetAmount = 50000, // 默认目标业绩5万
TotalActualAmount = Convert.ToDecimal(r.TotalActualAmount ?? 0),
TotalOrderCount = Convert.ToInt32(r.TotalOrderCount ?? 0),
CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0),
})
.ToList();
_logger.LogInformation("其他部门业绩统计查询完成,返回{Count}条记录", departmentList.Count);
return new OtherDepartmentStatisticsOutput { DepartmentList = departmentList, TotalCount = departmentList.Count };
}
catch (Exception ex)
{
_logger.LogError(ex, "查询其他部门业绩统计时发生错误,查询日期:{StartDate} - {EndDate},部门ID:{DepartmentId}", input.StartDate, input.EndDate, input.DepartmentId);
throw NCCException.Oh("查询其他部门业绩统计失败", ex);
}
}
#endregion
#region 获取经理业绩统计
///
/// 获取经理业绩统计
///
///
/// 根据指定日期范围和事业部ID查询经理的业绩统计信息,按经理和门店维度进行统计
///
/// 示例请求:
/// ```json
/// {
/// "startDate": "2025-01-01T00:00:00",
/// "endDate": "2025-01-31T23:59:59",
/// "businessUnitId": "事业部ID(可选)"
/// }
/// ```
///
/// 参数说明:
/// - startDate: 开始日期,格式:yyyy-MM-ddTHH:mm:ss
/// - endDate: 结束日期,格式:yyyy-MM-ddTHH:mm:ss
/// - businessUnitId: 事业部ID,可选参数,不传则查询所有事业部
///
/// 返回数据说明:
/// - ManagerName: 经理姓名
/// - ManagerUserId: 经理用户ID
/// - BusinessUnitName: 事业部名称
/// - BusinessUnitId: 事业部ID
/// - StoreName: 门店名称
/// - StoreId: 门店ID
/// - TargetPerformance: 目标业绩
/// - ActualPerformance: 完成业绩
/// - OrderCount: 开单数量
/// - CompletionRate: 完成率(%)
///
/// 查询参数
/// 经理业绩统计结果
/// 成功返回经理业绩统计数据
/// 请求参数错误
/// 服务器内部错误
[HttpPost("ManagerStatistics")]
[AllowAnonymous]
public async Task GetManagerStatistics(ManagerStatisticsInput input)
{
try
{
_logger.LogInformation("开始查询经理业绩统计,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
// 构建查询参数
var parameters = new Dictionary { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } };
// 构建WHERE条件
var whereClause = "WHERE (flow.order_date >= @startDate AND flow.order_date <= @endDate OR flow.order_date IS NULL)";
if (!string.IsNullOrEmpty(input.BusinessUnitId))
{
whereClause += " AND basic.business_unit_id = @businessUnitId";
parameters.Add("@businessUnitId", input.BusinessUnitId);
}
// 构建SQL查询 - 按经理和门店统计
var sql =
$@"
SELECT
basic.manager_user_id AS ManagerUserId,
basic.manager_name AS ManagerName,
basic.business_unit_id AS BusinessUnitId,
basic.business_unit_name AS BusinessUnitName,
basic.store_id AS StoreId,
basic.store_name AS StoreName,
COALESCE(smx.smx1, 0) AS TargetPerformance,
SUM(COALESCE(flow.actual_amount, 0)) AS ActualPerformance,
COUNT(flow.order_id) AS OrderCount,
CASE
WHEN COALESCE(smx.smx1, 0) > 0
THEN ROUND((SUM(COALESCE(flow.actual_amount, 0)) / COALESCE(smx.smx1, 0)) * 100, 2)
ELSE 0
END AS CompletionRate
FROM v_manager_store_basic basic
LEFT JOIN lq_zjl_mdsmxsz smx ON basic.store_id = smx.md_id AND basic.manager_user_id = smx.zjl_userid
LEFT JOIN v_department_performance_flow flow ON basic.store_id = flow.store_id
{whereClause}
GROUP BY
basic.manager_user_id,
basic.manager_name,
basic.business_unit_id,
basic.business_unit_name,
basic.store_id,
basic.store_name,
smx.smx1
ORDER BY ActualPerformance DESC";
_logger.LogInformation("执行SQL查询:{Sql}", sql);
_logger.LogInformation("查询参数:{Parameters}", string.Join(", ", parameters.Select(p => $"{p.Key}={p.Value}")));
var results = await _db.Ado.SqlQueryAsync(sql, parameters);
_logger.LogInformation("查询到经理业绩数据数量:{Count}", results.Count);
// 转换为输出格式
var managerList = results
.Select(r => new ManagerStatisticsInfo
{
ManagerName = r.ManagerName?.ToString() ?? "",
ManagerUserId = r.ManagerUserId?.ToString() ?? "",
BusinessUnitName = r.BusinessUnitName?.ToString() ?? "",
BusinessUnitId = r.BusinessUnitId?.ToString() ?? "",
StoreName = r.StoreName?.ToString() ?? "",
StoreId = r.StoreId?.ToString() ?? "",
TargetPerformance = Convert.ToDecimal(r.TargetPerformance ?? 0),
ActualPerformance = Convert.ToDecimal(r.ActualPerformance ?? 0),
OrderCount = Convert.ToInt32(r.OrderCount ?? 0),
CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0),
})
.ToList();
_logger.LogInformation("经理业绩统计查询完成,返回{Count}条记录", managerList.Count);
return new ManagerStatisticsOutput { ManagerList = managerList, TotalCount = managerList.Count };
}
catch (Exception ex)
{
_logger.LogError(ex, "查询经理业绩统计时发生错误,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
throw NCCException.Oh("查询经理业绩统计失败", ex);
}
}
#endregion
#region 获取经理业绩汇总统计
///
/// 获取经理业绩汇总统计
///
///
/// 统计每个经理的目标业绩总和、完成业绩总和、完成率等汇总信息
///
/// 示例请求:
/// ```json
/// {
/// "startDate": "2025-01-01T00:00:00",
/// "endDate": "2025-01-31T23:59:59",
/// "businessUnitId": "事业部ID(可选)"
/// }
/// ```
///
/// 参数说明:
/// - startDate: 开始日期,格式:yyyy-MM-ddTHH:mm:ss
/// - endDate: 结束日期,格式:yyyy-MM-ddTHH:mm:ss
/// - businessUnitId: 事业部ID,可选参数,不传则查询所有事业部
///
/// 返回数据说明:
/// - ManagerName: 经理姓名
/// - ManagerUserId: 经理用户ID
/// - BusinessUnitName: 事业部名称
/// - BusinessUnitId: 事业部ID
/// - StoreCount: 管理门店数量
/// - TotalTargetPerformance: 目标业绩总和
/// - TotalActualPerformance: 完成业绩总和
/// - CompletionRate: 完成率(%)
/// - TotalOrderCount: 开单总数量
///
/// 查询参数
/// 经理业绩汇总统计结果
/// 成功返回经理业绩汇总统计数据
/// 请求参数错误
/// 服务器内部错误
[HttpPost("ManagerSummaryStatistics")]
[AllowAnonymous]
public async Task GetManagerSummaryStatistics(ManagerStatisticsInput input)
{
try
{
_logger.LogInformation("开始查询经理业绩汇总统计,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
// 构建查询参数
var parameters = new Dictionary { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } };
// 构建WHERE条件
var whereClause = "WHERE (flow.order_date >= @startDate AND flow.order_date <= @endDate OR flow.order_date IS NULL)";
if (!string.IsNullOrEmpty(input.BusinessUnitId))
{
whereClause += " AND basic.business_unit_id = @businessUnitId";
parameters.Add("@businessUnitId", input.BusinessUnitId);
}
// 构建SQL查询 - 按经理汇总统计
var sql =
$@"
SELECT
basic.manager_user_id AS ManagerUserId,
basic.manager_name AS ManagerName,
basic.business_unit_id AS BusinessUnitId,
basic.business_unit_name AS BusinessUnitName,
COUNT(DISTINCT basic.store_id) AS StoreCount,
SUM(COALESCE(smx.smx1, 0)) AS TotalTargetPerformance,
SUM(COALESCE(flow.actual_amount, 0)) AS TotalActualPerformance,
COUNT(flow.order_id) AS TotalOrderCount,
CASE
WHEN SUM(COALESCE(smx.smx1, 0)) > 0
THEN ROUND((SUM(COALESCE(flow.actual_amount, 0)) / SUM(COALESCE(smx.smx1, 0))) * 100, 2)
ELSE 0
END AS CompletionRate
FROM v_manager_store_basic basic
LEFT JOIN lq_zjl_mdsmxsz smx ON basic.store_id = smx.md_id AND basic.manager_user_id = smx.zjl_userid
LEFT JOIN v_department_performance_flow flow ON basic.store_id = flow.store_id
{whereClause}
GROUP BY
basic.manager_user_id,
basic.manager_name,
basic.business_unit_id,
basic.business_unit_name
ORDER BY TotalActualPerformance DESC";
_logger.LogInformation("执行SQL查询:{Sql}", sql);
_logger.LogInformation("查询参数:{Parameters}", string.Join(", ", parameters.Select(p => $"{p.Key}={p.Value}")));
var results = await _db.Ado.SqlQueryAsync(sql, parameters);
_logger.LogInformation("查询到经理业绩汇总数据数量:{Count}", results.Count);
// 转换为输出格式
var managerSummaryList = results
.Select(r => new ManagerSummaryStatisticsInfo
{
ManagerName = r.ManagerName?.ToString() ?? "",
ManagerUserId = r.ManagerUserId?.ToString() ?? "",
BusinessUnitName = r.BusinessUnitName?.ToString() ?? "",
BusinessUnitId = r.BusinessUnitId?.ToString() ?? "",
StoreCount = Convert.ToInt32(r.StoreCount ?? 0),
TotalTargetPerformance = Convert.ToDecimal(r.TotalTargetPerformance ?? 0),
TotalActualPerformance = Convert.ToDecimal(r.TotalActualPerformance ?? 0),
TotalOrderCount = Convert.ToInt32(r.TotalOrderCount ?? 0),
CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0),
})
.ToList();
_logger.LogInformation("经理业绩汇总统计查询完成,返回{Count}条记录", managerSummaryList.Count);
return new ManagerSummaryStatisticsOutput { ManagerSummaryList = managerSummaryList, TotalCount = managerSummaryList.Count };
}
catch (Exception ex)
{
_logger.LogError(ex, "查询经理业绩汇总统计时发生错误,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
throw NCCException.Oh("查询经理业绩汇总统计失败", ex);
}
}
#endregion
#region 私有方法
///
/// 递归获取子部门列表
///
/// 父部门ID
/// 子部门列表
private async Task> GetSubDepartmentsRecursively(string parentId)
{
var subDepartments = new List();
try
{
// 查询直接子部门
var directChildren = await _db.Queryable()
.Where(x => x.ParentId == parentId && x.EnabledMark == 1 && x.DeleteMark == null)
.Select(x => new DepartmentInfo
{
DepartmentId = x.Id,
DepartmentName = x.FullName,
ParentId = x.ParentId,
})
.ToListAsync();
subDepartments.AddRange(directChildren);
// 递归查询每个子部门的子部门
foreach (var child in directChildren)
{
var grandChildren = await GetSubDepartmentsRecursively(child.DepartmentId);
subDepartments.AddRange(grandChildren);
}
return subDepartments;
}
catch (Exception ex)
{
_logger.LogError(ex, "递归获取子部门列表时发生错误,父部门ID:{ParentId}", parentId);
return subDepartments;
}
}
#endregion
#region 匿名接口
///
/// 发送每日统计消息(匿名接口)
///
/// 发送结果
[HttpPost("SendDailyReportMessage")]
[AllowAnonymous]
public async Task