fix 逻辑删除增加,消息通知

This commit is contained in:
2025-03-06 16:49:02 +08:00
parent 7e71884b32
commit bf392a7c46
16 changed files with 170 additions and 28 deletions

View File

@@ -51,6 +51,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dlhis.Constants", "Src\Dlhi
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dlhis.Canteen.Api", "Src\Dlhis.Canteen.Api\Dlhis.Canteen.Api.csproj", "{7934BE46-9409-4D28-8B35-82A0F900DD01}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dlhis.Message.Api", "Src\Dlhis.Message.Api\Dlhis.Message.Api.csproj", "{78B80FBD-E7B0-4352-B7FD-B6DCE2D48AEE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -129,6 +131,10 @@ Global
{7934BE46-9409-4D28-8B35-82A0F900DD01}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7934BE46-9409-4D28-8B35-82A0F900DD01}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7934BE46-9409-4D28-8B35-82A0F900DD01}.Release|Any CPU.Build.0 = Release|Any CPU
{78B80FBD-E7B0-4352-B7FD-B6DCE2D48AEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{78B80FBD-E7B0-4352-B7FD-B6DCE2D48AEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78B80FBD-E7B0-4352-B7FD-B6DCE2D48AEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78B80FBD-E7B0-4352-B7FD-B6DCE2D48AEE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -147,6 +153,7 @@ Global
{841B7B43-5394-413F-9D68-A07EBDD6D4CD} = {4EBCE46B-CE3A-4A47-9432-82A1854CA58A}
{E673CA04-3567-4E03-9A86-994F50291ACC} = {4EBCE46B-CE3A-4A47-9432-82A1854CA58A}
{7934BE46-9409-4D28-8B35-82A0F900DD01} = {3D8A98C1-83C9-4375-AEAB-4F72AFAF365B}
{78B80FBD-E7B0-4352-B7FD-B6DCE2D48AEE} = {65E76F97-E78A-4C95-B788-4091236B1A79}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7439494A-E2FD-4FEA-8ABF-74AE57A4A5A0}

View File

@@ -31,6 +31,7 @@
<ProjectReference Include="..\Dlhis.Entity\Dlhis.Entity.csproj" />
<ProjectReference Include="..\Dlhis.InfoCheck.Api\Dlhis.InfoCheck.Api.csproj" />
<ProjectReference Include="..\Dlhis.Jip.Api\Dlhis.Jip.Api.csproj" />
<ProjectReference Include="..\Dlhis.Message.Api\Dlhis.Message.Api.csproj" />
<ProjectReference Include="..\Dlhis.Sys.Api\Dlhis.Sys.Api.csproj" />
</ItemGroup>

View File

@@ -5,6 +5,8 @@ using Dlhis.Entity.Device.Enums;
using Dlhis.Entity.Sys.Entities;
using Dlhis.Entity.Sys.Enums;
using Dlhis.Jip.Api.Dto;
using Dlhis.Message.Api;
using Dlhis.Message.Api.Requests;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Utils.Extensions;
@@ -16,12 +18,14 @@ public class GainfoUpdateService : IGainfoUpdateService
private readonly ILogger<GainfoUpdateService> _logger;
private readonly IJinkoSapService _jinkoSapService;
private readonly IGainfoPermissionService _gainfoPermissionService;
private readonly IDingTalkApi _dingTalkApi;
private readonly IIdentityUserSyncService _identityUserSyncService;
public GainfoUpdateService(IDbContext dbContext,
ILogger<GainfoUpdateService> logger,
IJinkoSapService jinkoSapService,
IGainfoPermissionService gainfoPermissionService,
IDingTalkApi dingTalkApi,
IIdentityUserSyncService identityUserSyncService)
{
_dbContext = dbContext;
@@ -29,6 +33,7 @@ public class GainfoUpdateService : IGainfoUpdateService
_logger = logger;
_jinkoSapService = jinkoSapService;
_gainfoPermissionService = gainfoPermissionService;
_dingTalkApi = dingTalkApi;
_identityUserSyncService = identityUserSyncService;
}
@@ -276,7 +281,7 @@ public class GainfoUpdateService : IGainfoUpdateService
if (change.IsPresent())
{
await _identityUserSyncService.SyncAccountAsync(gainfo.Code, gainfo.Name, gainfo.IdNo, factory);
await _gainfoPermissionService.ResetPermissionsAsync(gainfo.No, DeviceTaskEnumType.Delete, null, $"异动生成({change})");
await _gainfoPermissionService.ResetPermissionsAsync(gainfo.No, DeviceTaskEnumType.Delete, null, $"异动生成({change})");
}
}
@@ -303,6 +308,43 @@ public class GainfoUpdateService : IGainfoUpdateService
if (change.IsPresent())
{
await _gainfoPermissionService.ResetPermissionsAsync(gainfo.No, DeviceTaskEnumType.Add, null, $"异动生成({change})");
var workGridUser = await _dbContext.Queryable<WorkGridUserEntity>().Where(x => x.UserCode == gainfo.Code).SingleAsync();
if (workGridUser != null)
{
try
{
var resignationDate = DateOnly.FromDateTime(gainfo.ResignationDate!.Value);
var workGridSchedules = await _dbContext.Queryable<WorkGridScheduleEntity>().Where(x => x.UserCode == gainfo.Code)
.Where(x => x.Date >= resignationDate)
.ToListAsync();
if (workGridSchedules.Any())
{
var dates = workGridSchedules.Select(x => $"{x.Date.ToString("yyyy年-MM月-dd日")}的{x.PeriodType.GetDescription()}").Join(",");
var workGrid = await _dbContext.Queryable<WorkGridEntity>().Where(x => x.Code == workGridUser.WorkGridCode).Select(x => new
{
x.LeaderUserCode, x.Name
}).SingleAsync();
var content = $"{workGrid.Name}的网格长,你好,检测到你网格中 {gainfo.Name}({gainfo.Code}),因发生离职或者异动,现已经删除该员工{dates}的排班信息,请前往系统处理!";
await _dingTalkApi.SendWorkMessageAsync(new JinkoSendWorkMessageRequest
{
Content = content,
WorkCodes = new List<string> { workGrid.LeaderUserCode }
});
}
await _dbContext.DeleteAsync(workGridUser);
await _dbContext.DeleteAsync(workGridSchedules);
}
catch (Exception e)
{
_logger.LogError(e, "网格异动处理异常:{error}", e.Message);
}
}
}
}
else
@@ -322,6 +364,42 @@ public class GainfoUpdateService : IGainfoUpdateService
await _dbContext.Deleteable<GainfoGroupRelationshipEntity>().Where(x => x.UserNo == gainfo.No).ExecuteCommandAsync();
await _dbContext.Deleteable<DevicePermissionEntity>().Where(x => x.AssignType == AssignTypeEnumType.User && x.AssignValue == gainfo.No).ExecuteCommandAsync();
var workGridUser = await _dbContext.Queryable<WorkGridUserEntity>().Where(x => x.UserCode == gainfo.Code).SingleAsync();
if (workGridUser != null)
{
try
{
var resignationDate = DateOnly.FromDateTime(gainfo.ResignationDate!.Value);
var workGridSchedules = await _dbContext.Queryable<WorkGridScheduleEntity>().Where(x => x.UserCode == gainfo.Code)
.Where(x => x.Date >= resignationDate)
.ToListAsync();
if (workGridSchedules.Any())
{
var dates = workGridSchedules.Select(x => $"{x.Date.ToString("yyyy年-MM月-dd日")}的{x.PeriodType.GetDescription()}").Join(",");
var workGrid = await _dbContext.Queryable<WorkGridEntity>().Where(x => x.Code == workGridUser.WorkGridCode).Select(x => new
{
x.LeaderUserCode, x.Name
}).SingleAsync();
var content = $"{workGrid.Name}的网格长,你好,检测到你网格中 {gainfo.Name}({gainfo.Code}),因发生离职或者异动,现已经删除该员工{dates}的排班信息,请前往系统处理!";
await _dingTalkApi.SendWorkMessageAsync(new JinkoSendWorkMessageRequest
{
Content = content,
WorkCodes = new List<string> { workGrid.LeaderUserCode }
});
}
await _dbContext.DeleteAsync(workGridUser);
await _dbContext.DeleteAsync(workGridSchedules);
}
catch (Exception e)
{
_logger.LogError(e, "网格异动处理异常:{error}", e.Message);
}
}
gainfo.Id = gainfo.IdentityUserId;
await _dbContext.DeleteReallyAsync(gainfo);
await _identityUserSyncService.LockAccountAsync(gainfo.Code);

View File

@@ -83,7 +83,7 @@ public class WorkGridScheduleService : IWorkGridScheduleService
.Where(x => request.UserCodes.Contains(x.UserCode))
.ToListAsync();
await _dbContext.DeleteReallyAsync(data);
await _dbContext.DeleteAsync(data);
await _operateLog.LogAsync(OperateLogType.WorkGrid, $"移除网格({workGrid.Name}){request.Date.ToString("yyyy-M-d")}的{request.PeriodType.GetDescription()}人员:{request.UserCodes.Join(",")}");
}
@@ -113,7 +113,7 @@ public class WorkGridScheduleService : IWorkGridScheduleService
item.MaximumConsecutiveSchedules = maximumConsecutiveUserCodes.FirstOrDefault(x => x.UserCode == item.UserCode);
}
}
return data;
}
@@ -228,7 +228,8 @@ public class WorkGridScheduleService : IWorkGridScheduleService
var p = userCodes.Select(x => $"@param{x}").Join(",");
var values = userCodes.ToDictionary(x => $"param{x}", x => x);
values.Add("date", date.ToString("yyyy-MM-dd"));
values.Add("dateBefore", date.AddDays(-1).ToString("yyyy-MM-dd"));
values.Add("dateAfter", date.AddDays(1).ToString("yyyy-MM-dd"));
values.Add("days", days.ToString());
var sql = $@"
@@ -250,7 +251,11 @@ WITH ranked_dates AS (SELECT UserCode,
GROUP BY UserCode, grp
HAVING streak_days >= @days)
SELECT UserCode, streak_days as Count, start_date as Start, end_date as End
FROM streaks where @date>= start_date and @date<= end_date;
FROM streaks
where (@dateBefore >= start_date
and @dateBefore <= end_date)
or (@dateAfter >= start_date
and @dateAfter <= end_date);
";

View File

@@ -247,8 +247,8 @@ public class WorkGridService : IWorkGridService
.Where(x => request.UserCodes.Contains(x.UserCode))
.ToListAsync();
await _dbContext.DeleteReallyAsync(workGridUsers);
await _dbContext.DeleteReallyAsync(workGridSchedules);
await _dbContext.DeleteAsync(workGridUsers);
await _dbContext.DeleteAsync(workGridSchedules);
await _operateLog.LogAsync(OperateLogType.WorkGrid, $"从网格({myWorkGrid.Name})移除人员:{request.UserCodes.Join(",")}");
}

View File

@@ -9,7 +9,8 @@
"CommonRequestUrl": "http://localhost:5001",
"SysRequestUrl": "http://localhost:5003",
"ScheduledRequestUrl": "http://localhost:5010",
"InfoCheckRequestUrl":"http://localhost:5048"
"InfoCheckRequestUrl":"http://localhost:5048",
"MessageRequestUrl": "http://localhost:5050"
},
"FaceUrlOptions": {
"Url": "http://localhost:5002/api/gainfos/face?token=",

View File

@@ -10,7 +10,8 @@
"CommonRequestUrl": "http://common",
"SysRequestUrl": "http://sys",
"ScheduledRequestUrl": "http://Scheduled",
"InfoCheckRequestUrl": "http://192.168.199.115:5048"
"InfoCheckRequestUrl": "http://192.168.199.115:5048",
"MessageRequestUrl": "http://message"
},
"FaceUrlOptions": {
"Url": "https://yikatong.isawesome.cn/api/basic/gainfos/face?token=",
@@ -18,7 +19,7 @@
},
"DataProtectionOptions": {
"Enable": true,
"AppName": "yiliantong"
"AppName": "yikatong"
},
"SqlSugarOptions": {
"DefaultConnectionString": "server=192.168.199.124;port=3306;userid=root;password=dlhis123;database=yikatong;charset=utf8mb4;",

View File

@@ -1,3 +1,4 @@
using Kurisu.AspNetCore.DataAccess.Entity;
using Kurisu.AspNetCore.DataAccess.SqlSugar;
using Mapster;
using SqlSugar;
@@ -7,8 +8,8 @@ namespace Dlhis.Entity.Basic.Entity;
/// <summary>
/// 工作网格
/// </summary>
[SugarTable(TableName = "WorkGrid")]
public class WorkGridEntity : SugarBaseEntity
[SugarTable(TableName = "WorkGrids")]
public class WorkGridEntity : SugarBaseEntity, ISoftDeleted
{
/// <summary>
/// 网格code
@@ -35,4 +36,7 @@ public class WorkGridEntity : SugarBaseEntity
/// </summary>
[SugarColumn(IsNullable = true, ColumnDescription = "备注")]
public string Remark { get; set; }
public bool IsDeleted { get; set; }
}

View File

@@ -1,4 +1,5 @@
using Dlhis.Entity.Basic.Enums;
using Kurisu.AspNetCore.DataAccess.Entity;
using Kurisu.AspNetCore.DataAccess.SqlSugar;
using SqlSugar;
using SqlSugar.DbConvert;
@@ -9,7 +10,7 @@ namespace Dlhis.Entity.Basic.Entity;
///
/// </summary>
[SugarTable(TableName = "WorkGridSchedules")]
public class WorkGridScheduleEntity : SugarBaseEntity
public class WorkGridScheduleEntity : SugarBaseEntity , ISoftDeleted
{
/// <summary>
/// 网格code
@@ -34,4 +35,7 @@ public class WorkGridScheduleEntity : SugarBaseEntity
/// </summary>
[SugarColumn(IsNullable = false, ColumnDescription = "工号", IndexGroupNameList = new[] { "idx_WorkGridSchedules_userCode" })]
public string UserCode { get; set; }
public bool IsDeleted { get; set; }
}

View File

@@ -10,8 +10,8 @@ namespace Dlhis.Entity.Basic.Entity;
/// <summary>
/// 工作网格
/// </summary>
[SugarTable(TableName = "WorkGridTimePeriod")]
public class WorkGridTimePeriodEntity : SugarBaseEntity, ITenantId
[SugarTable(TableName = "WorkGridTimePeriods")]
public class WorkGridTimePeriodEntity : SugarBaseEntity, ITenantId , ISoftDeleted
{
/// <summary>
/// 班次
@@ -43,4 +43,8 @@ public class WorkGridTimePeriodEntity : SugarBaseEntity, ITenantId
public TimeOnly End { get; set; }
public string TenantId { get; set; }
/// <inheritdoc />
public bool IsDeleted { get; set; }
}

View File

@@ -1,3 +1,4 @@
using Kurisu.AspNetCore.DataAccess.Entity;
using Kurisu.AspNetCore.DataAccess.SqlSugar;
using SqlSugar;
@@ -7,7 +8,7 @@ namespace Dlhis.Entity.Basic.Entity;
/// 网格人员
/// </summary>
[SugarTable(TableName = "WorkGridUsers")]
public class WorkGridUserEntity : SugarBaseEntity
public class WorkGridUserEntity : SugarBaseEntity, ISoftDeleted
{
/// <summary>
/// 网格code
@@ -18,6 +19,9 @@ public class WorkGridUserEntity : SugarBaseEntity
/// <summary>
/// 网格人员
/// </summary>
[SugarColumn(IsNullable = false, ColumnDescription = "网格人员", UniqueGroupNameList = new[] { "idx_WorkGridUsers_userCode" })]
[SugarColumn(IsNullable = false, ColumnDescription = "网格人员", IndexGroupNameList = new[] { "idx_WorkGridUsers_userCode" })]
public string UserCode { get; set; }
/// <inheritdoc />
public bool IsDeleted { get; set; }
}

View File

@@ -5,6 +5,8 @@ using Dlhis.Entity.Device.Entities;
using Dlhis.Entity.Device.Enums;
using Dlhis.Jip.Api;
using Dlhis.Jip.Api.Requests;
using Dlhis.Message.Api;
using Dlhis.Message.Api.Requests;
using Dlhis.ScheduledTask.DeviceUploadLog.Request;
using Dlhis.ScheduledTask.DeviceUploadLog.Response;
using Kurisu.AspNetCore.Authentication.Abstractions;
@@ -21,12 +23,20 @@ public class DeviceUploadLogService : IDeviceUploadLogService
private readonly IDbContext _dbContext;
private readonly ICurrentUser _currentUser;
private readonly IJinkoJipApi _jinkoJipApi;
private readonly ILogger<DeviceUploadLogService> _logger;
private readonly IDingTalkApi _dingTalkApi;
public DeviceUploadLogService(IDbContext dbContext, ICurrentUser currentUser, IJinkoJipApi jinkoJipApi)
public DeviceUploadLogService(IDbContext dbContext,
ICurrentUser currentUser,
IJinkoJipApi jinkoJipApi,
ILogger<DeviceUploadLogService> logger,
IDingTalkApi dingTalkApi)
{
_dbContext = dbContext;
_currentUser = currentUser;
_jinkoJipApi = jinkoJipApi;
_logger = logger;
_dingTalkApi = dingTalkApi;
}
public async Task UploadLogsAsync(List<DeviceUploadLogUploadRequest> requests)
@@ -36,10 +46,10 @@ public class DeviceUploadLogService : IDeviceUploadLogService
var existsDeviceUniqueNos = devices.Select(x => x.UniqueNo).ToList();
var userCodes = requests.Where(x => x.UserUniqueNo.IsPresent()).Select(x => x.UserUniqueNo).Distinct().ToList();
var gainfo1 = await _dbContext.Queryable<GainfoEntity>().Where(x => userCodes.Contains(x.Code)).Select(x => new { x.Code, x.Type }).ToListAsync();
var gainfo2 = await _dbContext.Queryable<GainfoEntity>().AS("GainfoLeave").Where(x => userCodes.Contains(x.Code)).Select(x => new { x.Code, x.Type }).ToListAsync();
var gainfo1 = await _dbContext.Queryable<GainfoEntity>().Where(x => userCodes.Contains(x.Code)).Select(x => new { x.Code, x.Name, x.Type }).ToListAsync();
var gainfo2 = await _dbContext.Queryable<GainfoEntity>().AS("GainfoLeave").Where(x => userCodes.Contains(x.Code)).Select(x => new { x.Code, x.Name, x.Type }).ToListAsync();
var gainfoCardNos = requests.Where(x => x.CardNo.IsPresent() && x.UserUniqueNo != x.CardNo).Select(x => x.CardNo).Distinct().ToList();
var gainfo3 = await _dbContext.Queryable<GainfoEntity>().Where(x => gainfoCardNos.Contains(x.Code)).Select(x => new { x.Code, x.Type }).ToListAsync();
var gainfo3 = await _dbContext.Queryable<GainfoEntity>().Where(x => gainfoCardNos.Contains(x.Code)).Select(x => new { x.Code, x.Name, x.Type }).ToListAsync();
var gainfos = gainfo1.Concat(gainfo2).Concat(gainfo3).DistinctBy(x => x.Code).ToList();
var userCodes2 = gainfos.Select(x => x.Code).Distinct().ToList();
@@ -52,7 +62,7 @@ public class DeviceUploadLogService : IDeviceUploadLogService
.Where(x => userCodes2.Contains(x.UserCode))
.Select((x, wg) => new
{
x.WorkGridCode, x.UserCode, wg.LeaderUserCode, wg.Name
x.WorkGridCode, x.UserCode, wg.LeaderUserCode, WorkGridName = wg.Name
})
.ToListAsync();
@@ -94,7 +104,8 @@ public class DeviceUploadLogService : IDeviceUploadLogService
var device = devices.First(x => x.UniqueNo == request.DeviceUniqueNo);
var userType = gainfos.FirstOrDefault(x => x.Code == request.UserUniqueNo)?.Type;
var currentGainfo = gainfos.FirstOrDefault(x => x.Code == request.UserUniqueNo);
var userType = currentGainfo?.Type;
var needUpload = ((userType is GainfoUserTypeEnumType.Normal or GainfoUserTypeEnumType.SecurityWhite)
&& (device.Type == DeviceTypeEnumType.Attendance || (device.Type == DeviceTypeEnumType.Door && device.AsAttendance)));
var dataType = device.Type == DeviceTypeEnumType.Attendance
@@ -114,7 +125,7 @@ public class DeviceUploadLogService : IDeviceUploadLogService
workGridInfo.WorkGrid = new
{
workGridUser.WorkGridCode,
workGridUser.Name,
workGridUser.WorkGridName,
workGridUser.LeaderUserCode
};
var currentDate = request.RaiseDateTime.Date;
@@ -165,6 +176,22 @@ public class DeviceUploadLogService : IDeviceUploadLogService
}
needUpload = workGridInfo.PeriodType.HasValue;
if (!needUpload)
{
try
{
await _dingTalkApi.SendWorkMessageAsync(new JinkoSendWorkMessageRequest
{
Content = $"{workGridUser.WorkGridName}的网格长,你好,检测到你网格中 {currentGainfo.Name}({currentGainfo.Code})今日未排班,但是有考勤记录,请前往系统处理!",
WorkCodes = new List<string> { workGridUser.LeaderUserCode }
});
}
catch (Exception e)
{
_logger.LogError(e, "推送信息错误:{error}", e.Message);
}
}
}
inserts.Add(new DeviceUploadLogEntity

View File

@@ -14,6 +14,9 @@
<Content Remove="log\**" />
<EmbeddedResource Remove="log\**" />
<None Remove="log\**" />
<Content Update="appsettings.Development.json">
<DependentUpon>appsettings.json</DependentUpon>
</Content>
</ItemGroup>
<ItemGroup>
@@ -29,6 +32,7 @@
<ProjectReference Include="..\Dlhis.Constants\Dlhis.Constants.csproj" />
<ProjectReference Include="..\Dlhis.Entity\Dlhis.Entity.csproj" />
<ProjectReference Include="..\Dlhis.Jip.Api\Dlhis.Jip.Api.csproj" />
<ProjectReference Include="..\Dlhis.Message.Api\Dlhis.Message.Api.csproj" />
<ProjectReference Include="..\Dlhis.Sys.Api\Dlhis.Sys.Api.csproj" />
</ItemGroup>

View File

@@ -2,7 +2,7 @@
"profiles": {
"Dlhis.ScheduledTask": {
"commandName": "Project",
"launchBrowser": true,
"launchBrowser": false,
"launchUrl": "swagger/index.html",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"

View File

@@ -8,7 +8,8 @@
"InternalRequest": {
"SysRequestUrl": "http://localhost:5003",
"BasicRequestUrl": "http://localhost:5002",
"CanteenRequestUrl": "http://localhost:5008"
"CanteenRequestUrl": "http://localhost:5008",
"MessageRequestUrl": "http://localhost:5050"
},
"FaceUrlOptions": {
"Url": "http://192.168.199.115:5002/api/gainfos/face?token=",

View File

@@ -8,11 +8,12 @@
"InternalRequest": {
"SysRequestUrl": "http://sys",
"BasicRequestUrl": "http://basic",
"CanteenRequestUrl": "http://canteen"
"CanteenRequestUrl": "http://canteen",
"MessageRequestUrl": "http://message"
},
"DataProtectionOptions": {
"Enable": true,
"AppName": "yiliantong"
"AppName": "yikatong"
},
"SqlSugarOptions": {
"DefaultConnectionString": "server=192.168.199.124;port=3306;userid=root;password=dlhis123;database=yikatong;charset=utf8mb4;",