|
@@ -2,23 +2,25 @@
|
|
|
using FluentValidation;
|
|
using FluentValidation;
|
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
|
using OASystem.API.OAMethodLib;
|
|
using OASystem.API.OAMethodLib;
|
|
|
|
|
+using OASystem.API.OAMethodLib.DeepSeekAPI;
|
|
|
using OASystem.API.OAMethodLib.Hub.HubClients;
|
|
using OASystem.API.OAMethodLib.Hub.HubClients;
|
|
|
using OASystem.API.OAMethodLib.Hub.Hubs;
|
|
using OASystem.API.OAMethodLib.Hub.Hubs;
|
|
|
using OASystem.API.OAMethodLib.QiYeWeChatAPI;
|
|
using OASystem.API.OAMethodLib.QiYeWeChatAPI;
|
|
|
using OASystem.API.OAMethodLib.QiYeWeChatAPI.AppNotice;
|
|
using OASystem.API.OAMethodLib.QiYeWeChatAPI.AppNotice;
|
|
|
using OASystem.Domain.Dtos.Groups;
|
|
using OASystem.Domain.Dtos.Groups;
|
|
|
using OASystem.Domain.Dtos.PersonnelModule;
|
|
using OASystem.Domain.Dtos.PersonnelModule;
|
|
|
|
|
+using OASystem.Domain.Dtos.Statistics;
|
|
|
using OASystem.Domain.Entities.Groups;
|
|
using OASystem.Domain.Entities.Groups;
|
|
|
using OASystem.Domain.Entities.PersonnelModule;
|
|
using OASystem.Domain.Entities.PersonnelModule;
|
|
|
using OASystem.Domain.ViewModels.PersonnelModule;
|
|
using OASystem.Domain.ViewModels.PersonnelModule;
|
|
|
using OASystem.Domain.ViewModels.QiYeWeChat;
|
|
using OASystem.Domain.ViewModels.QiYeWeChat;
|
|
|
|
|
+using OASystem.Domain.ViewModels.Statistics;
|
|
|
using OASystem.Infrastructure.Repositories.Groups;
|
|
using OASystem.Infrastructure.Repositories.Groups;
|
|
|
using OASystem.Infrastructure.Repositories.PersonnelModule;
|
|
using OASystem.Infrastructure.Repositories.PersonnelModule;
|
|
|
using System.Data;
|
|
using System.Data;
|
|
|
using System.Diagnostics;
|
|
using System.Diagnostics;
|
|
|
using System.Globalization;
|
|
using System.Globalization;
|
|
|
using static OASystem.API.OAMethodLib.JWTHelper;
|
|
using static OASystem.API.OAMethodLib.JWTHelper;
|
|
|
-using OASystem.API.OAMethodLib.DeepSeekAPI;
|
|
|
|
|
|
|
|
|
|
namespace OASystem.API.Controllers
|
|
namespace OASystem.API.Controllers
|
|
|
{
|
|
{
|
|
@@ -3208,8 +3210,211 @@ OPTION (MAXRECURSION 0); -- 允许无限递归 ";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Ai绩效分析
|
|
|
|
|
+ /// 列表查询基础数据
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ /// <returns></returns>
|
|
|
|
|
+ [HttpGet]
|
|
|
|
|
+ [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
|
|
|
|
|
+ public async Task<IActionResult> AiPerformanceAnalysis_InitAsync()
|
|
|
|
|
+ {
|
|
|
|
|
+ var companyDatas = await _sqlSugar.Queryable<Sys_Company>().Where(x => x.IsDel == 0).Select(x => new { x.Id, x.CompanyName }).ToListAsync();
|
|
|
|
|
+ var jobPostDatas = await _sqlSugar.Queryable<Sys_JobPost>().Where(x => x.IsDel == 0).Select(x => new { x.Id, x.CompanyId, x.JobName }).ToListAsync();
|
|
|
|
|
+ var userDatas = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0).Select(x => new { x.Id, x.JobPostId, x.CnName }).ToListAsync();
|
|
|
|
|
+
|
|
|
|
|
+ companyDatas.Insert(0, new { Id = 0, CompanyName = "全部" });
|
|
|
|
|
+ jobPostDatas.Insert(0, new { Id = 0, CompanyId = 0, JobName = "全部" });
|
|
|
|
|
+ userDatas.Insert(0, new { Id = 0, JobPostId = 0, CnName = "全部" });
|
|
|
|
|
+ return Ok(JsonView(true, "操作成功!", new
|
|
|
|
|
+ {
|
|
|
|
|
+ companyDatas,
|
|
|
|
|
+ jobPostDatas,
|
|
|
|
|
+ userDatas
|
|
|
|
|
+ }));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Ai绩效分析
|
|
|
|
|
+ /// 用户列表
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ /// <returns></returns>
|
|
|
|
|
+ [HttpPost]
|
|
|
|
|
+ [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
|
|
|
|
|
+ public async Task<IActionResult> AiPerformanceAnalysis_UserListAsync(AiPerformanceAnalysis_UserListDto dto)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (dto.CompanyId < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ return Ok(JsonView(false, "请传入有效的公司Id。"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (dto.JobPostId < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ return Ok(JsonView(false, "请传入有效的岗位Id。"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (dto.UserId < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ return Ok(JsonView(false, "请传入有效的员工Id。"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (dto.PageIndex < 1)
|
|
|
|
|
+ {
|
|
|
|
|
+ dto.PageIndex = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (dto.PageSize < 1 || dto.PageSize > 100)
|
|
|
|
|
+ {
|
|
|
|
|
+ dto.PageSize = 10;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ RefAsync<int> total = 0;
|
|
|
|
|
+
|
|
|
|
|
+ var query = _sqlSugar.Queryable<Sys_Users>()
|
|
|
|
|
+ .LeftJoin<Sys_Company>((u, c) => u.CompanyId == c.Id)
|
|
|
|
|
+ .LeftJoin<Sys_JobPost>((u, c, jp) => u.JobPostId == jp.Id)
|
|
|
|
|
+ .Where((u, c, jp) => u.IsDel == 0)
|
|
|
|
|
+ .WhereIF(dto.CompanyId > 0, (u, c, jp) => u.CompanyId == dto.CompanyId)
|
|
|
|
|
+ .WhereIF(dto.JobPostId > 0, (u, c, jp) => u.JobPostId == dto.JobPostId)
|
|
|
|
|
+ .WhereIF(dto.UserId > 0, (u, c, jp) => u.Id == dto.UserId)
|
|
|
|
|
+ .OrderBy(u => u.CompanyId)
|
|
|
|
|
+ .OrderBy(u => u.JobPostId)
|
|
|
|
|
+ .OrderBy(u => u.Id);
|
|
|
|
|
+
|
|
|
|
|
+ var view = await query.Select((u, c, jp) => new AiPerformanceAnalysis_UserView()
|
|
|
|
|
+ {
|
|
|
|
|
+ RowNumber = SqlFunc.RowNumber("u.CompanyId ASC, u.JobPostId ASC, u.Id ASC"),
|
|
|
|
|
+ Id = u.Id,
|
|
|
|
|
+ UserName = u.CnName,
|
|
|
|
|
+ CompanyId = u.CompanyId,
|
|
|
|
|
+ CompanyName = c.CompanyName,
|
|
|
|
|
+ JobPostId = u.JobPostId,
|
|
|
|
|
+ JobName = jp.JobName,
|
|
|
|
|
+ WorkYears = SqlFunc.DateDiff(DateType.Year, u.Edate, DateTime.Now)
|
|
|
|
|
+ })
|
|
|
|
|
+ .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
|
|
|
|
|
+
|
|
|
|
|
+ return Ok(JsonView(true, "操作成功!", view, total));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Ai绩效分析
|
|
|
|
|
+ /// 团组统计
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ /// <param name="userId">用户ID</param>
|
|
|
|
|
+ /// <param name="start">开始日期(eg:2025-01-01)</param>
|
|
|
|
|
+ /// <param name="end">结束日期(eg:2025-12-31)</param>
|
|
|
|
|
+ /// <returns></returns>
|
|
|
|
|
+ [HttpGet]
|
|
|
|
|
+ [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
|
|
|
|
|
+ public async Task<IActionResult> AiPerformanceAnalysis_GroupStatisticsAsync(int userId, DateTime start, DateTime end)
|
|
|
|
|
+ {
|
|
|
|
|
+ #region 参数验证
|
|
|
|
|
+
|
|
|
|
|
+ if (userId < 1)
|
|
|
|
|
+ {
|
|
|
|
|
+ return Ok(JsonView(false, "请传入有效UserId。"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (start > end)
|
|
|
|
|
+ {
|
|
|
|
|
+ return Ok(JsonView(false, "开始日期不能晚于结束日期。"));
|
|
|
|
|
+ }
|
|
|
|
|
+ #endregion
|
|
|
|
|
+
|
|
|
|
|
+ var parameters = new
|
|
|
|
|
+ {
|
|
|
|
|
+ UserId = userId,
|
|
|
|
|
+ StartDate = start.Date,
|
|
|
|
|
+ EndDate = end.Date.AddDays(1).AddSeconds(-1) // 包含结束日期的最后一秒
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ string sql = @"
|
|
|
|
|
+SELECT
|
|
|
|
|
+ ROW_NUMBER() OVER (ORDER BY MonthNumber, CollectionDays) AS RowNumber,
|
|
|
|
|
+ Id,
|
|
|
|
|
+ TeamName,
|
|
|
|
|
+ ClientUnit,
|
|
|
|
|
+ ClientName,
|
|
|
|
|
+ VisitDate,
|
|
|
|
|
+ VisitPNumber,
|
|
|
|
|
+ JietuanOperator,
|
|
|
|
|
+ VisitEndDate,
|
|
|
|
|
+ MonthNumber,
|
|
|
|
|
+ GroupSales,
|
|
|
|
|
+ GroupPickupUser,
|
|
|
|
|
+ CollectionDays
|
|
|
|
|
+FROM
|
|
|
|
|
+(
|
|
|
|
|
+ SELECT
|
|
|
|
|
+ di.Id,
|
|
|
|
|
+ di.TeamName,
|
|
|
|
|
+ di.ClientUnit,
|
|
|
|
|
+ di.ClientName,
|
|
|
|
|
+ di.VisitDate,
|
|
|
|
|
+ di.VisitPNumber,
|
|
|
|
|
+ di.JietuanOperator,
|
|
|
|
|
+ di.VisitEndDate,
|
|
|
|
|
+ DATEPART(MONTH, di.VisitEndDate) AS MonthNumber,
|
|
|
|
|
+ (
|
|
|
|
|
+ SELECT CAST(COALESCE(SUM(ItemSumPrice * Rate), 0) AS DECIMAL(12, 2))
|
|
|
|
|
+ FROM Fin_ForeignReceivables
|
|
|
|
|
+ WHERE IsDel = 0
|
|
|
|
|
+ AND di.Id = Diid
|
|
|
|
|
+ AND AddingWay IN (0, 1, 2)
|
|
|
|
|
+ ) AS GroupSales,
|
|
|
|
|
+ u.CnName AS GroupPickupUser,
|
|
|
|
|
+ DATEADD(DAY, 7, di.VisitEndDate) AS CollectionDays
|
|
|
|
|
+ FROM Grp_DelegationInfo di WITH (NOLOCK)
|
|
|
|
|
+ LEFT JOIN Sys_Users u ON di.JietuanOperator = u.Id
|
|
|
|
|
+ WHERE di.Isdel = 0
|
|
|
|
|
+ AND di.IsBid = 0
|
|
|
|
|
+ AND di.JietuanOperator = @UserId
|
|
|
|
|
+ AND di.TeamName NOT LIKE '%投标%'
|
|
|
|
|
+ AND di.VisitDate BETWEEN @StartDate AND @EndDate
|
|
|
|
|
+ AND EXISTS (
|
|
|
|
|
+ SELECT 1
|
|
|
|
|
+ FROM Fin_ForeignReceivables fr
|
|
|
|
|
+ WHERE fr.IsDel = 0
|
|
|
|
|
+ AND fr.Diid = di.Id
|
|
|
|
|
+ AND fr.AddingWay IN (0, 1, 2)
|
|
|
|
|
+ )
|
|
|
|
|
+) Temp
|
|
|
|
|
+ORDER BY MonthNumber, CollectionDays";
|
|
|
|
|
+
|
|
|
|
|
+ var groupData = await _sqlSugar.SqlQueryable<AiPerformanceAnalysis_GroupStatisticsView>(sql)
|
|
|
|
|
+ .AddParameters(parameters)
|
|
|
|
|
+ .ToListAsync();
|
|
|
|
|
+
|
|
|
|
|
+ return Ok(JsonView(true, "操作成功!", groupData, groupData?.Count ?? 0));
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private class AiPerformanceAnalysis_GroupStatisticsView : MarketingSalesGroupList
|
|
|
|
|
+ {
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ ///月份
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ public int MonthNumber { get; set; }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// AI绩效分析用户列表视图模型
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ private class AiPerformanceAnalysis_UserView
|
|
|
|
|
+ {
|
|
|
|
|
+ public int RowNumber { get; set; }
|
|
|
|
|
+ public int Id { get; set; }
|
|
|
|
|
+ public string UserName { get; set; }
|
|
|
|
|
+ public int CompanyId { get; set; }
|
|
|
|
|
+ public string CompanyName { get; set; }
|
|
|
|
|
+ public int JobPostId { get; set; }
|
|
|
|
|
+ public string JobName { get; set; }
|
|
|
|
|
+ public int WorkYears { get; set; }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
#endregion
|
|
#endregion
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
+}
|