From 846d0e3a09c11401545761116431a74b51534461 Mon Sep 17 00:00:00 2001 From: liguoyang Date: Tue, 15 Jul 2025 14:34:24 +0800 Subject: [PATCH] =?UTF-8?q?test=20=E7=BD=91=E6=A0=BC=E6=8E=A8=E9=80=81sap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/WorkGridsController.cs | 1 + .../Request/WorkGridUserRemoveRequest.cs | 4 + .../Implements/WorkGridScheduleService.cs | 215 ++++++++++++------ .../Services/Implements/WorkGridService.cs | 9 +- .../Basic/Entity/WorkGridScheduleEntity.cs | 8 +- Src/Dlhis.Jip.Api/IJinkoJipApi.cs | 5 + .../Requests/SyncWorkShiftRequest.cs | 42 ++++ .../Responses/SyncWorkShiftResponse.cs | 42 ++++ 8 files changed, 256 insertions(+), 70 deletions(-) create mode 100644 Src/Dlhis.Jip.Api/Requests/SyncWorkShiftRequest.cs create mode 100644 Src/Dlhis.Jip.Api/Responses/SyncWorkShiftResponse.cs diff --git a/Src/Dlhis.Basic/WorkGrids/Controllers/WorkGridsController.cs b/Src/Dlhis.Basic/WorkGrids/Controllers/WorkGridsController.cs index 313bd292..7bb4f8a7 100644 --- a/Src/Dlhis.Basic/WorkGrids/Controllers/WorkGridsController.cs +++ b/Src/Dlhis.Basic/WorkGrids/Controllers/WorkGridsController.cs @@ -158,6 +158,7 @@ public class WorkGridsController : ControllerBase /// /// [HttpPost("user/schedule/remove")] + [Transactional] public async Task RemoveAsyncScheduleAsync(WorkGridScheduleSaveRequest request) { await _workGridScheduleService.RemoveAsync(request); diff --git a/Src/Dlhis.Basic/WorkGrids/Request/WorkGridUserRemoveRequest.cs b/Src/Dlhis.Basic/WorkGrids/Request/WorkGridUserRemoveRequest.cs index e5358bc5..43d98592 100644 --- a/Src/Dlhis.Basic/WorkGrids/Request/WorkGridUserRemoveRequest.cs +++ b/Src/Dlhis.Basic/WorkGrids/Request/WorkGridUserRemoveRequest.cs @@ -4,6 +4,10 @@ namespace Dlhis.Basic.WorkGrids.Request; public class WorkGridUserRemoveRequest { + /// + /// 网格code + /// + /// 兼容被非档案用户操作 eg:wyz要求 public Guid? WorkGridCode { get; set; } /// diff --git a/Src/Dlhis.Basic/WorkGrids/Services/Implements/WorkGridScheduleService.cs b/Src/Dlhis.Basic/WorkGrids/Services/Implements/WorkGridScheduleService.cs index 6d1f1bf2..73aa1b2d 100644 --- a/Src/Dlhis.Basic/WorkGrids/Services/Implements/WorkGridScheduleService.cs +++ b/Src/Dlhis.Basic/WorkGrids/Services/Implements/WorkGridScheduleService.cs @@ -58,7 +58,8 @@ public class WorkGridScheduleService : IWorkGridScheduleService .Where(x => x.Code == request.WorkGridCode) .Select((x, ga) => new { - x.Code, x.Name, + x.Code, + x.Name, x.LeaderUserCode, LeaderUserName = ga.Name, x.MaxConsecutiveLimitCount @@ -73,6 +74,7 @@ public class WorkGridScheduleService : IWorkGridScheduleService timeSetting.ThrowIfNull("工作网格时间尚未配置,无法操作"); + //班次开始前一个小时不可操作 var currentLimit = request.Date.ToDateTime(timeSetting.Start.Add(-TimeSpan.FromHours(1))); (DateTime.Now >= currentLimit).ThrowIfTrue("当前时间不可修改排班信息"); @@ -84,6 +86,7 @@ public class WorkGridScheduleService : IWorkGridScheduleService var others = request.UserCodes.Except(workGridUserCodes).ToList(); others.ThrowIfExists($"{others.Join(",")}非当前网格人员"); + //处理排班冲突问题 var dateBefore = request.Date.AddDays(-1); var dateAfter = request.Date.AddDays(1); @@ -94,9 +97,11 @@ public class WorkGridScheduleService : IWorkGridScheduleService ) .ToListAsync(); + //重复排班 var existsUserCodes = scheduleRange.Where(x => x.Date == request.Date && request.UserCodes.Contains(x.UserCode)).Select(x => x.UserCode).ToList(); existsUserCodes.ThrowIfExists(existsUserCodes.Join(",") + "当天已存在排班"); + //当前排班为白班,那么上一天不能存在晚班 if (request.PeriodType == WorkGridTimePeriodEnumType.Day) { existsUserCodes = scheduleRange @@ -104,6 +109,7 @@ public class WorkGridScheduleService : IWorkGridScheduleService .Select(x => x.UserCode).ToList(); existsUserCodes.ThrowIfExists(existsUserCodes.Join(",") + $"在{dateBefore.ToString("yyyy-MM-dd")}已存在{WorkGridTimePeriodEnumType.Night.GetDescription()}"); } + //当前排班为晚班,那么下一天不能存在白班 else if (request.PeriodType == WorkGridTimePeriodEnumType.Night) { existsUserCodes = scheduleRange @@ -111,10 +117,20 @@ public class WorkGridScheduleService : IWorkGridScheduleService .Select(x => x.UserCode).ToList(); existsUserCodes.ThrowIfExists(existsUserCodes.Join(",") + $"在{dateAfter.ToString("yyyy-MM-dd")}已存在{WorkGridTimePeriodEnumType.Day.GetDescription()}"); } + else + { + throw new ArgumentException("排班类型错误,请检查"); + } - var maximumConsecutiveListDto = await _workGridScheduleRepository.MaximumConsecutiveUserCodesAsync(request.UserCodes, workGrid.MaxConsecutiveLimitCount, request.Date); + //连续排班限制 + var maximumConsecutiveListDto = await _workGridScheduleRepository.MaximumConsecutiveUserCodesAsync( + request.UserCodes, + workGrid.MaxConsecutiveLimitCount, + request.Date + ); maximumConsecutiveListDto.ThrowIfExists(maximumConsecutiveListDto.Select(x => $"{x.UserCode}已经连续排班{workGrid.MaxConsecutiveLimitCount}天({x.Start}-{x.End}),禁止排班").Join("\r\n")); + //数据保存 var toInserts = request.UserCodes.Select(x => new WorkGridScheduleEntity { WorkGridCode = request.WorkGridCode, @@ -126,7 +142,41 @@ public class WorkGridScheduleService : IWorkGridScheduleService await _dbContext.InsertAsync(toInserts); await _operateLog.LogAsync(OperateLogType.WorkGrid, $"新增网格({workGrid.Name}){request.Date.ToString("yyyy-M-d")}的{request.PeriodType.GetDescription()}人员:{request.UserCodes.Join(",")}"); + if (workGrid.Code.ToString() == "769ace3b-28fa-4c4e-ba46-fc399a25085f") + { + //推送到SAP + var items = toInserts.Select(x => new SyncWorkShiftDayItem + { + UserCode = x.UserCode, + Begin = x.Date.ToString("yyyyMMdd"), + End = x.Date.ToString("yyyyMMdd"), + Plan = request.PeriodType == WorkGridTimePeriodEnumType.Day ? "JK03" : "JK04", + Operate = "INS" + }).ToList(); + var response = await _jinkoJipApi.SyncWorkShiftAsync(new SyncWorkShiftRequest { Items = items }); + if (response.Items.Any(x => x.Result != "S")) + { + var errorMessages = response.Items.Where(x => x.Result != "S") + .Select(x => $"{x.UserCode}排班新增失败:{x.Message}").Join("\r\n"); + throw new UserFriendlyException(errorMessages); + } + + foreach (var workGridSchedule in toInserts) + { + var msg = response.Items.FirstOrDefault(x => x.UserCode == workGridSchedule.UserCode)?.Message; + await _dbContext.Updateable() + .SetColumns(x => x.SyncResult == msg) + .Where(x => x.WorkGridCode == workGrid.Code) + .Where(x => x.UserCode == workGridSchedule.UserCode) + .Where(x => x.Date == workGridSchedule.Date) + .Where(x => x.PeriodType == workGridSchedule.PeriodType) + .ExecuteCommandAsync(); + } + } + + //todo sub pub + //推送排班通知 try { var codeAndNameList = await _dbContext.Queryable().Where(x => request.UserCodes.Contains(x.Code)) @@ -151,7 +201,103 @@ public class WorkGridScheduleService : IWorkGridScheduleService } catch (Exception e) { - _logger.LogError("推送信息错误save,{error}", e.Message); + _logger.LogError("推送信息错误save:{error}", e.Message); + } + } + + + public async Task RemoveAsync(WorkGridScheduleSaveRequest request) + { + var workGrid = await _dbContext.Queryable() + .LeftJoin((x, ga) => x.LeaderUserCode == ga.Code) + .Where(x => x.Code == request.WorkGridCode) + .Select((x, ga) => new + { + x.Code, + x.Name, + x.LeaderUserCode, + LeaderUserName = ga.Name + }) + .SingleAsync(); + workGrid.ThrowIfNull("工作网格不存在"); + + var timeSetting = await _dbContext.Queryable() + .Where(x => x.Type == request.PeriodType) + .Select(x => new { x.Start, x.Before }) + .SingleAsync(); + + //班次识别区间内禁止操作移除 + var currentLimit = request.Date.ToDateTime(timeSetting.Start.Add(-TimeSpan.FromSeconds(timeSetting.Before))); + (DateTime.Now >= currentLimit).ThrowIfTrue("当前时间不可修改排班信息"); + + //获取需要移除的班次数据 + var data = await _dbContext.Queryable() + .Where(x => x.WorkGridCode == request.WorkGridCode) + .Where(x => x.Date == request.Date) + .Where(x => x.PeriodType == request.PeriodType) + .Where(x => request.UserCodes.Contains(x.UserCode)) + .ToListAsync(); + + if (data.Any()) + { + if (workGrid.Code.ToString() == "769ace3b-28fa-4c4e-ba46-fc399a25085f") + { + //推送到SAP + var items = data.Select(x => new SyncWorkShiftDayItem + { + UserCode = x.UserCode, + Begin = x.Date.ToString("yyyyMMdd"), + End = x.Date.ToString("yyyyMMdd"), + Plan = request.PeriodType == WorkGridTimePeriodEnumType.Day ? "JK03" : "JK04", + Operate = "DEL" + }).ToList(); + + var response = await _jinkoJipApi.SyncWorkShiftAsync(new SyncWorkShiftRequest { Items = items }); + if (response.Items.Any(x => x.Result != "S")) + { + var errorMessages = response.Items.Where(x => x.Result != "S") + .Select(x => $"{x.UserCode}排班删除失败:{x.Message}").Join("\r\n"); + throw new UserFriendlyException(errorMessages); + } + + foreach (var workGridSchedule in data) + { + workGridSchedule.SyncResult = response.Items.FirstOrDefault(x => x.UserCode == workGridSchedule.UserCode)?.Message; + } + + await _dbContext.UpdateAsync(data); + } + + + await _dbContext.DeleteAsync(data); + await _operateLog.LogAsync(OperateLogType.WorkGrid, $"移除网格({workGrid.Name}){request.Date.ToString("yyyy-M-d")}的{request.PeriodType.GetDescription()}人员:{request.UserCodes.Join(",")}"); + + //todo sub pub + //推送移除通知 + try + { + var userCodes = data.Select(x => x.UserCode).Distinct().ToList(); + var gainfos = await _dbContext.Queryable().Where(x => userCodes.Contains(x.Code)).Select(x => new { x.Code, x.Name }).ToListAsync(); + foreach (var gainfo in gainfos) + { + try + { + await _jinkoApiService.SendWorkMessageAsync(new DingTalkWorkMessageRequest + { + Content = $"{gainfo.Name}({gainfo.Code})你好,系统检测到你被{workGrid.Name}网格的网格长{workGrid.LeaderUserName}({workGrid.LeaderUserCode})删除了{request.Date.ToString("yyyy年MM月dd日")}{request.PeriodType.GetDescription()},如有疑问,请联系网格长!", + WorkCodes = new List { gainfo.Code } + }); + } + catch (Exception e) + { + _logger.LogError("推送信息错误{code}:{error}", gainfo.Code, e.Message); + } + } + } + catch (Exception e) + { + _logger.LogError("推送信息错误remove,{error}", e.Message); + } } } @@ -204,65 +350,6 @@ public class WorkGridScheduleService : IWorkGridScheduleService return currentLimit; } - - /// - public async Task RemoveAsync(WorkGridScheduleSaveRequest request) - { - var workGrid = await _dbContext.Queryable() - .LeftJoin((x, ga) => x.LeaderUserCode == ga.Code) - .Where(x => x.Code == request.WorkGridCode) - .Select((x, ga) => new - { - x.Code, x.Name, - x.LeaderUserCode, - LeaderUserName = ga.Name - }) - .SingleAsync(); - workGrid.ThrowIfNull("工作网格不存在"); - - var timeSetting = await _dbContext.Queryable().Where(x => x.Type == request.PeriodType).Select(x => new { x.Start, x.Before }).SingleAsync(); - var currentLimit = request.Date.ToDateTime(timeSetting.Start.Add(-TimeSpan.FromSeconds(timeSetting.Before))); - (DateTime.Now >= currentLimit).ThrowIfTrue("当前时间不可修改排班信息"); - - var data = await _dbContext.Queryable() - .Where(x => x.WorkGridCode == request.WorkGridCode) - .Where(x => x.Date == request.Date) - .Where(x => x.PeriodType == request.PeriodType) - .Where(x => request.UserCodes.Contains(x.UserCode)) - .ToListAsync(); - - if (data.Any()) - { - await _dbContext.DeleteAsync(data); - await _operateLog.LogAsync(OperateLogType.WorkGrid, $"移除网格({workGrid.Name}){request.Date.ToString("yyyy-M-d")}的{request.PeriodType.GetDescription()}人员:{request.UserCodes.Join(",")}"); - - try - { - var userCodes = data.Select(x => x.UserCode).Distinct().ToList(); - var gainfos = await _dbContext.Queryable().Where(x => userCodes.Contains(x.Code)).Select(x => new { x.Code, x.Name }).ToListAsync(); - foreach (var gainfo in gainfos) - { - try - { - await _jinkoApiService.SendWorkMessageAsync(new DingTalkWorkMessageRequest - { - Content = $"{gainfo.Name}({gainfo.Code})你好,系统检测到你被{workGrid.Name}网格的网格长{workGrid.LeaderUserName}({workGrid.LeaderUserCode})删除了{request.Date.ToString("yyyy年MM月dd日")}{request.PeriodType.GetDescription()},如有疑问,请联系网格长!", - WorkCodes = new List { gainfo.Code } - }); - } - catch (Exception e) - { - _logger.LogError("推送信息错误{code}:{error}", gainfo.Code, e.Message); - } - } - } - catch (Exception e) - { - _logger.LogError("推送信息错误remove,{error}", e.Message); - } - } - } - public async Task> GetListAsync(Guid workGridCode, DateOnly date, WorkGridTimePeriodEnumType? periodType) { var data = await _dbContext.Queryable() @@ -294,7 +381,7 @@ public class WorkGridScheduleService : IWorkGridScheduleService ); } - /// + public async Task> GetAttendancePageAsync(WorkGridScheduleAttendancePageRequest request) { var jinkoCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode); @@ -417,8 +504,6 @@ public class WorkGridScheduleService : IWorkGridScheduleService return page; } - - /// public async Task ManuallyUploadAsync(List logIds) { var sub = _currentUser.GetIntSubjectId(); diff --git a/Src/Dlhis.Basic/WorkGrids/Services/Implements/WorkGridService.cs b/Src/Dlhis.Basic/WorkGrids/Services/Implements/WorkGridService.cs index 63e3b289..a18aacd0 100644 --- a/Src/Dlhis.Basic/WorkGrids/Services/Implements/WorkGridService.cs +++ b/Src/Dlhis.Basic/WorkGrids/Services/Implements/WorkGridService.cs @@ -258,26 +258,27 @@ public class WorkGridService : IWorkGridService var specific = (role is "admin" or "tenant-admin" or "WGZGLY") && request.WorkGridCode.HasValue; var currentUserCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode); - var myWorkGrid = await _dbContext.Queryable() + var workGrid = await _dbContext.Queryable() .WhereIF(specific, x => x.Code == request.WorkGridCode) .WhereIF(specific == false, x => x.LeaderUserCode == currentUserCode) .SingleAsync(); var workGridUsers = await _dbContext.Queryable() - .Where(x => x.WorkGridCode == myWorkGrid.Code) + .Where(x => x.WorkGridCode == workGrid.Code) .Where(x => request.UserCodes.Contains(x.UserCode)) .ToListAsync(); + //获取今天之后的排班信息 var date = DateOnly.FromDateTime(DateTime.Today); var workGridSchedules = await _dbContext.Queryable() .Where(x => x.Date > date) - .Where(x => x.WorkGridCode == myWorkGrid.Code) + .Where(x => x.WorkGridCode == workGrid.Code) .Where(x => request.UserCodes.Contains(x.UserCode)) .ToListAsync(); await _dbContext.DeleteAsync(workGridUsers); await _dbContext.DeleteAsync(workGridSchedules); - await _operateLog.LogAsync(OperateLogType.WorkGrid, $"从网格({myWorkGrid.Name})移除人员:{request.UserCodes.Join(",")}"); + await _operateLog.LogAsync(OperateLogType.WorkGrid, $"从网格({workGrid.Name})移除人员:{request.UserCodes.Join(",")}"); } } \ No newline at end of file diff --git a/Src/Dlhis.Entity/Basic/Entity/WorkGridScheduleEntity.cs b/Src/Dlhis.Entity/Basic/Entity/WorkGridScheduleEntity.cs index 2b402712..74fc7b5e 100644 --- a/Src/Dlhis.Entity/Basic/Entity/WorkGridScheduleEntity.cs +++ b/Src/Dlhis.Entity/Basic/Entity/WorkGridScheduleEntity.cs @@ -10,7 +10,7 @@ namespace Dlhis.Entity.Basic.Entity; /// /// [SugarTable(TableName = "WorkGridSchedules")] -public class WorkGridScheduleEntity : SugarBaseEntity , ISoftDeleted +public class WorkGridScheduleEntity : SugarBaseEntity, ISoftDeleted { /// /// 网格code @@ -42,5 +42,11 @@ public class WorkGridScheduleEntity : SugarBaseEntity , ISoftDeleted [SugarColumn(IsNullable = false, ColumnDescription = "是否取消", ColumnDataType = "bit")] public bool IsCancel { get; set; } + /// + /// 同步结果 + /// + [SugarColumn(IsNullable = true, ColumnDataType = "text", ColumnDescription = "同步结果")] + public string SyncResult { get; set; } + public bool IsDeleted { get; set; } } \ No newline at end of file diff --git a/Src/Dlhis.Jip.Api/IJinkoJipApi.cs b/Src/Dlhis.Jip.Api/IJinkoJipApi.cs index eeba7dbc..23214f21 100644 --- a/Src/Dlhis.Jip.Api/IJinkoJipApi.cs +++ b/Src/Dlhis.Jip.Api/IJinkoJipApi.cs @@ -81,4 +81,9 @@ public interface IJinkoJipApi /// [Post("/JIP/HCM/HCM_I_PHOTO")] Task SyncFaceToSapAsync(SyncFaceRequest request); + + + [RequestLog] + [Post("/JIP/HCM/HCM_I_SHIFTREP")] + Task SyncWorkShiftAsync(SyncWorkShiftRequest request); } \ No newline at end of file diff --git a/Src/Dlhis.Jip.Api/Requests/SyncWorkShiftRequest.cs b/Src/Dlhis.Jip.Api/Requests/SyncWorkShiftRequest.cs new file mode 100644 index 00000000..e7e0e41a --- /dev/null +++ b/Src/Dlhis.Jip.Api/Requests/SyncWorkShiftRequest.cs @@ -0,0 +1,42 @@ +using Newtonsoft.Json; + +namespace Dlhis.Jip.Api.Requests; + +public class SyncWorkShiftRequest +{ + [JsonProperty("IT_2003")] + public List Items { get; set; } +} + +public class SyncWorkShiftDayItem +{ + /// + /// 员工编码 + /// + [JsonProperty("IV_GONGH")] + public string UserCode { get; set; } + + /// + /// 开始日期 yyyyMMdd + /// + [JsonProperty("IV_BEGDA")] + public string Begin { get; set; } + + /// + /// 结束日期 yyyyMMdd + /// + [JsonProperty("IV_ENDDA")] + public string End { get; set; } + + /// + /// 排班计划 JK03白板 JK04夜班 + /// + [JsonProperty("IV_TPROG")] + public string Plan { get; set; } + + /// + /// 操作 INS / MOD /DEL + /// + [JsonProperty("IV_OP")] + public string Operate { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Jip.Api/Responses/SyncWorkShiftResponse.cs b/Src/Dlhis.Jip.Api/Responses/SyncWorkShiftResponse.cs new file mode 100644 index 00000000..8257196d --- /dev/null +++ b/Src/Dlhis.Jip.Api/Responses/SyncWorkShiftResponse.cs @@ -0,0 +1,42 @@ +using Newtonsoft.Json; + +namespace Dlhis.Jip.Api.Responses; + +public class SyncWorkShiftResponse +{ + [JsonProperty("OT_2003")] + public List Items { get; set; } +} + +public class SyncWorkShiftItem +{ + /// + /// 员工编码 + /// + [JsonProperty("OV_GONGH")] + public string UserCode { get; set; } + + /// + /// 开始日期 yyyyMMdd + /// + [JsonProperty("OV_BEGDA")] + public string Begin { get; set; } + + /// + /// 结束日期 yyyyMMdd + /// + [JsonProperty("OV_ENDDA")] + public string End { get; set; } + + /// + /// 排班计划 JK03白板 JK04夜班 + /// + [JsonProperty("OV_TPROG")] + public string Plan { get; set; } + + [JsonProperty("OV_MSGTY")] + public string Result { get; set; } + + [JsonProperty("OV_MSGTXT")] + public string Message { get; set; } +} \ No newline at end of file