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.FriendlyException; using NCC.Extend.Interfaces.LqStatistics; using NCC.Extend.Entitys.Dto.LqStatistics; using Microsoft.AspNetCore.Mvc; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using NCC.Extend.Entitys.lq_mdxx; using NCC.Extend.Entitys.Dto.LqMdxx; using NCC.System.Entitys.Permission; using Microsoft.Extensions.Logging; 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; /// /// 初始化一个类型的新实例 /// public LqStatisticsService( ISqlSugarRepository lqMdxxRepository, IUserManager userManager, ILogger logger) { _lqMdxxRepository = lqMdxxRepository; _db = _lqMdxxRepository.Context; _userManager = userManager; _logger = logger; } #region 获取门店业绩统计列表 /// /// 获取门店业绩统计列表 /// /// /// 查询所有门店的目标业绩、完成业绩、完成率等关键指标 /// /// 返回数据包含: /// - 门店编码和店名 /// - 目标业绩(生命线) /// - 完成业绩(实付业绩) /// - 完成率(百分比) /// - 开单数量 /// /// 数据来源:v_store_performance_simple 视图 /// /// 门店业绩统计列表 /// 成功返回门店业绩统计列表 /// 服务器内部错误 [HttpGet] public async Task> GetStorePerformanceList() { try { var result = await _db.Ado.SqlQueryAsync( "SELECT " + "store_code AS StoreCode, " + "store_name AS StoreName, " + "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"); return result ?? new List(); } catch (Exception ex) { throw NCCException.Oh(ErrorCode.COM1005, ex.Message); } } #endregion #region 门店统计信息 /// /// 获取门店统计信息 /// /// /// 统计各个门店在员工数量、项目数(耗卡里面的项目数量)和消耗业绩(耗卡里面的金额) /// 可以传入日期,然后去统计本月一号到传入的日期 /// /// 示例请求: /// ```json /// { /// "queryDate": "2025-09-14" /// } /// ``` /// /// 参数说明: /// - queryDate: 查询日期,系统会自动计算本月1号到该日期的统计范围 /// /// 查询参数 /// 门店统计结果 /// 查询成功 /// 参数错误 /// 服务器内部错误 [HttpPost("StoreStatistics")] public async Task GetStoreStatistics([FromBody] StoreStatisticsInput input) { try { _logger.LogInformation("开始查询门店统计信息,查询日期:{QueryDate}", input.QueryDate); // 计算查询时间范围:本月1号到传入日期 var startDate = new DateTime(input.QueryDate.Year, input.QueryDate.Month, 1); var endDate = input.QueryDate.Date.AddDays(1).AddSeconds(-1); // 包含当天结束时间 _logger.LogInformation("统计时间范围:{StartDate} 到 {EndDate}", startDate, endDate); // 1. 查询门店基础信息 var storeList = await _db.Queryable() .Select(it => new StoreStatisticsInfo { StoreId = it.Id, StoreCode = it.Mdbm, StoreName = it.Dm, City = it.Cs, BusinessUnit = it.Syb, EmployeeCount = 0, ProjectCount = 0, ConsumeAmount = 0 }) .ToListAsync(); _logger.LogInformation("查询到门店数量:{Count}", storeList.Count); // 2. 查询员工数量(按门店统计) var employeeCounts = await _db.Queryable() .Where(u => !string.IsNullOrEmpty(u.Mdid) && u.DeleteMark != 1) .GroupBy(u => u.Mdid) .Select(g => new { StoreId = g.Mdid, Count = SqlFunc.AggregateCount(g.Id) }) .ToListAsync(); _logger.LogInformation("查询到员工统计数量:{Count}", employeeCounts.Count); // 3. 从视图查询项目数和消耗业绩 var consumeStats = await _db.SqlQueryable(@" SELECT store_id, SUM(total_project_count) as total_project_count, SUM(total_consume_amount) as total_consume_amount FROM v_store_daily_consume_stats WHERE consume_date >= @startDate AND consume_date <= @endDate GROUP BY store_id") .AddParameters(new { startDate = startDate.ToString("yyyy-MM-dd"), endDate = input.QueryDate.ToString("yyyy-MM-dd") }) .ToListAsync(); _logger.LogInformation("查询到消耗统计数量:{Count}", consumeStats.Count); // 4. 合并统计数据 foreach (var store in storeList) { // 匹配员工数量 var employeeCount = employeeCounts.FirstOrDefault(e => e.StoreId == store.StoreId); if (employeeCount != null) { store.EmployeeCount = employeeCount.Count; } // 匹配项目数和消耗业绩 var consumeStat = consumeStats.FirstOrDefault(c => c.store_id?.ToString() == store.StoreId); if (consumeStat != null) { store.ProjectCount = Convert.ToDecimal(consumeStat.total_project_count ?? 0); store.ConsumeAmount = Convert.ToDecimal(consumeStat.total_consume_amount ?? 0); } } // 5. 计算汇总统计 var summary = new StoreSummaryInfo { TotalStoreCount = storeList.Count, TotalEmployeeCount = storeList.Sum(s => s.EmployeeCount), TotalProjectCount = storeList.Sum(s => s.ProjectCount), TotalConsumeAmount = storeList.Sum(s => s.ConsumeAmount) }; var result = new StoreStatisticsOutput { StartDate = startDate, EndDate = input.QueryDate, StoreList = storeList.OrderByDescending(s => s.ConsumeAmount).ToList(), Summary = summary }; _logger.LogInformation("门店统计查询完成,门店数:{StoreCount},总员工数:{EmployeeCount},总项目数:{ProjectCount},总消耗业绩:{ConsumeAmount}", summary.TotalStoreCount, summary.TotalEmployeeCount, summary.TotalProjectCount, summary.TotalConsumeAmount); return result; } catch (Exception ex) { _logger.LogError(ex, "查询门店统计信息时发生错误,查询日期:{QueryDate}", input.QueryDate); throw NCCException.Oh(ErrorCode.COM1000, "查询门店统计信息失败"); } } #endregion } }