fix 外包人员,餐补导入,人员列表

This commit is contained in:
2024-05-24 15:28:31 +08:00
parent db094bc768
commit 7e2c0c7e39
19 changed files with 410 additions and 73 deletions

View File

@@ -0,0 +1,52 @@
using Dlhis.Basic.Organization.Request;
using Dlhis.Basic.Organization.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Dlhis.Basic.Organization.Controllers;
/// <summary>
/// 外包人员
/// </summary>
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class GainfoOutSourceController : ControllerBase
{
private readonly IGainfoOutSourceService _gainfoOutSourceService;
public GainfoOutSourceController(IGainfoOutSourceService gainfoOutSourceService)
{
_gainfoOutSourceService = gainfoOutSourceService;
}
/// <summary>
/// 入职
/// </summary>
/// <param name="request"></param>
[HttpPost("entry")]
public async Task EntryAsync(GainfoOutEntryRequest request)
{
await _gainfoOutSourceService.EntryAsync(request);
}
/// <summary>
/// 离职
/// </summary>
/// <param name="request"></param>
[HttpPost("resign")]
public async Task ResignAsync(GainfoOutResignRequest request)
{
await _gainfoOutSourceService.ResignAsync(request);
}
/// <summary>
/// 编辑
/// </summary>
/// <param name="request"></param>
[HttpPost("edit")]
public async Task EditAsync(GainfoOutEntryRequest request)
{
await _gainfoOutSourceService.EditAsync(request);
}
}

View File

@@ -7,7 +7,7 @@ using Kurisu.Core.DataAccess.Dto;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Dlhis.Basic.MealUser.Controllers;
namespace Dlhis.Basic.Organization.Controllers;
/// <summary>
/// sap档案表

View File

@@ -0,0 +1,119 @@
using Dlhis.Entity.Basic.Enums;
using SqlSugar;
namespace Dlhis.Basic.Organization.Request;
public class GainfoOutEntryRequest
{
public long? Id { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 证件类型代码
/// </summary>
public string IdClass { get; set; }
/// <summary>
/// 身份证号
/// </summary>
public string IdNo { get; set; }
/// <summary>
/// 身份证籍贯区域代码
/// </summary>
public string Native { get; set; }
/// <summary>
/// 性别 GenderEnumType
/// </summary>
public GenderEnumType Gender { get; set; }
/// <summary>
/// 生日
/// </summary>
public DateTime Birthday { get; set; }
/// <summary>
/// 身份证地址
/// </summary>
public string Address { get; set; }
/// <summary>
/// 部门编码
/// </summary>
public string DepartmentNo { get; set; }
/// <summary>
/// 民族代码
/// </summary>
public string Nation { get; set; }
/// <summary>
/// 手机号码
/// </summary>
public string Phone { get; set; }
/// <summary>
/// 学历
/// </summary>
public string Degree { get; set; }
/// <summary>
/// 岗位
/// </summary>
public string PositionNo { get; set; }
/// <summary>
/// 职等
/// </summary>
public string Grade { get; set; }
/// <summary>
/// 职级
/// </summary>
public string Title { get; set; }
/// <summary>
/// 卡号
/// </summary>
public string CardNo { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
/// <summary>
/// 人事范围
/// </summary>
public string Werks { get; set; }
/// <summary>
/// 工作地
/// </summary>
public string Workplace { get; set; }
/// <summary>
/// 厂区
/// </summary>
public string Factory { get; set; }
/// <summary>
/// 成本中心
/// </summary>
public string CostId { get; set; }
/// <summary>
/// 入职日期
/// </summary>
public DateTime? EntryDate { get; set; }
/// <summary>
/// 离职日期
/// </summary>
public DateTime? ResignationDate { get; set; }
}

View File

@@ -0,0 +1,23 @@
using System.ComponentModel.DataAnnotations;
namespace Dlhis.Basic.Organization.Request
{
public class GainfoOutResignRequest : IValidatableObject
{
public long Id { get; set; }
[Required]
public string Reason { get; set; }
public DateTime Date { get; set; }
/// <inheritdoc />
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Date < DateTime.Now.Date)
{
yield return new ValidationResult("离职日期不能小于当前时间", new[] { nameof(Date) });
}
}
}
}

View File

@@ -18,6 +18,12 @@ public class GainfoPageRequest : PageDto, IValidatableObject
/// </summary>
public List<TenantDepartmentRequest> DepartmentSelections { get; set; } = new List<TenantDepartmentRequest>();
/// <summary>
/// 是否为外包
/// </summary>
public bool? IsOutSource { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
DepartmentSelections.ForEach(d =>

View File

@@ -0,0 +1,12 @@
using Dlhis.Basic.Organization.Request;
namespace Dlhis.Basic.Organization.Services;
public interface IGainfoOutSourceService : IScopeDependency
{
Task EntryAsync(GainfoOutEntryRequest request);
Task ResignAsync(GainfoOutResignRequest request);
Task EditAsync(GainfoOutEntryRequest request);
}

View File

@@ -0,0 +1,85 @@
using Dlhis.Basic.Organization.Request;
using Dlhis.Entity.Basic.Entity;
using Kurisu.AspNetCore.Utils;
using Kurisu.AspNetCore.Utils.Extensions;
using Kurisu.SqlSugar.Services;
using Mapster;
using SqlSugar;
namespace Dlhis.Basic.Organization.Services.Implements;
public class GainfoOutSourceService : IGainfoOutSourceService
{
private readonly IDbContext _dbContext;
private readonly RedisCache _redisCache;
public GainfoOutSourceService(IDbContext dbContext, RedisCache redisCache)
{
_dbContext = dbContext;
_redisCache = redisCache;
}
public async Task EntryAsync(GainfoOutEntryRequest request)
{
await SaveAsync(request);
}
public async Task ResignAsync(GainfoOutResignRequest request)
{
//todo 生成任务处理
}
public async Task EditAsync(GainfoOutEntryRequest request)
{
await SaveAsync(request);
}
//********************************************************************** help methods ***********************************************************************************
private async Task<string> GetOutSourceCodeAsync()
{
await using var handler = await _redisCache.LockAsync("gainfo:outsource:code-generate", expiry: TimeSpan.FromSeconds(3), retryInterval: TimeSpan.FromSeconds(1), retryCount: 3);
handler.Acquired.ThrowIfFalse("生成虚拟工号失败");
int code;
var entity = await _dbContext.Queryable<OutSourceEntity>().OrderBy(x => x.Id, OrderByType.Desc).FirstAsync();
if (entity == null)
{
code = 1;
}
else
{
code = int.Parse(entity.Code.Replace("LS", "").Replace("0", "")) + 1;
}
return "LS" + code.ToString().PadLeft(6, '0');
}
private async Task SaveAsync(GainfoOutEntryRequest request)
{
if (!request.Id.HasValue)
{
var entity = request.Adapt<GainfoEntity>();
entity.No = Guid.NewGuid().ToString();
entity.Code = await GetOutSourceCodeAsync();
await _dbContext.InsertAsync(entity);
await _dbContext.InsertAsync(new OutSourceEntity
{
Code = entity.Code
});
}
else
{
var entity = await _dbContext.Queryable<GainfoEntity>().FirstAsync(x => x.Id == request.Id);
entity.ThrowIfNull("档案数据不存在");
(await _dbContext.Queryable<OutSourceEntity>().AnyAsync(x => x.Code == entity.Code)).ThrowIfFalse("不可编辑非外包人员档案数据");
request.Adapt(entity);
await _dbContext.UpdateAsync(entity);
}
}
}

View File

@@ -11,6 +11,7 @@ using Kurisu.Core.User.Abstractions;
using Kurisu.SqlSugar.Extensions;
using Kurisu.SqlSugar.Services;
using Microsoft.AspNetCore.DataProtection;
using SqlSugar;
namespace Dlhis.Basic.Organization.Services.Implements;
@@ -64,6 +65,8 @@ public class GainfoService : IGainfoService
var page = await _gainfoStore.Queryable(request.Status)
.WhereIF(request.DepartmentSelections.IsPresent(), where)
.WhereIF(request.DepartmentSelections.IsEmpty(), gainfo => gainfo.Factory == currentTenantId)
.WhereIF(request.IsOutSource.HasValue && request.IsOutSource.Value, gainfo => SqlFunc.Subqueryable<OutSourceEntity>().Where(x => x.Code == gainfo.Code).Any())
.WhereIF(request.IsOutSource.HasValue && !request.IsOutSource.Value, gainfo => SqlFunc.Subqueryable<OutSourceEntity>().Where(x => x.Code == gainfo.Code).NotAny())
.WhereIF(request.Search.IsPresent(), gainfo =>
gainfo.Name.Contains(request.Search)
|| gainfo.Code == request.Search
@@ -101,6 +104,7 @@ public class GainfoService : IGainfoService
_logger.LogWarning("工号为空尝试获取人员信息");
return null;
}
var gainfo = await _gainfoStore.Queryable().Where(x => x.Code == code).SingleAsync();
if (gainfo == null)
@@ -259,7 +263,6 @@ public class GainfoService : IGainfoService
}
catch (Exception)
{
}
}

View File

@@ -1,15 +1,32 @@
using System.ComponentModel.DataAnnotations;
using Kurisu.AspNetCore.Utils.Extensions;
namespace Dlhis.Canteen.MealSupplementRecord.Request;
public class MealSupplementInitImportRequest
public class MealSupplementInitImportRequest : IValidatableObject
{
[Required(ErrorMessage = "工号不能为空")]
public string Code { get; set; }
public string Name { get; set; }
/// <summary>
/// 余额
/// </summary>
[Range(1, int.MaxValue, ErrorMessage = "余额有误")]
public decimal Balance { get; set; }
/// <inheritdoc />
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Name.IsEmpty())
{
yield return new ValidationResult($"工号{Code}姓名不能为空", new[] { nameof(Name) });
}
if (Balance <= 0)
{
yield return new ValidationResult($"工号{Code}余额有误", new[] { nameof(Balance) });
}
}
}

View File

@@ -117,10 +117,10 @@ public class MealSupplementRecordService : IMealSupplementRecordService
foreach (var request in requests)
{
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.Code == request.Code).FirstAsync();
if (gainfo == null)
{
continue;
}
gainfo.ThrowIfNull($"工号{request.Code}不存在");
(_currentUser.GetStringTenantId() != gainfo.Factory).ThrowIfTrue($"工号{request.Code}属于{gainfo.Factory}人员,无法导入");
(gainfo.Name != request.Name).ThrowIfTrue($"工号{request.Code}姓名不一致");
await CommonHelper.RetryAsync(async () =>
{
@@ -150,6 +150,9 @@ public class MealSupplementRecordService : IMealSupplementRecordService
.ExecuteCommandThrowVersionAsync();
}, 5);
(await _dbContext.Queryable<BalanceRecordEntity>().Where(x => x.UserCode == request.Code).Where(x => x.Remark == "期初导入").AnyAsync()).ThrowIfTrue($"工号{request.Code}已导入期初余额");
await _dbContext.InsertAsync(new BalanceRecordEntity
{
Amount = request.Balance,

View File

@@ -0,0 +1,10 @@
using Kurisu.SqlSugar;
using SqlSugar;
namespace Dlhis.Entity.Basic.Entity;
[SugarTable(TableName = "OutSources")]
public class OutSourceEntity : SugarBaseEntity
{
public string Code { get; set; }
}

View File

@@ -99,10 +99,10 @@ public class JinkoJIPService : IJinkoJIPService
{
var jwtKey = _configuration.GetSection("JinkoOptions:Jip:Key").Value;
var jwtSecret = _configuration.GetSection("JinkoOptions:Jip:Secret").Value;
var mins = 5;
const int min = 5;
var now = DateTime.Now.AddMinutes(-mins);
var expires = DateTime.Now.AddMinutes(mins);
var now = DateTime.Now.AddMinutes(-min);
var expires = DateTime.Now.AddMinutes(min);
var claims = new List<Claim>
{

View File

@@ -18,6 +18,11 @@ public class DeviceUploadLogPageRequest : PageDto, IValidatableObject
/// </summary>
public bool? Sync { get; set; }
/// <summary>
/// 是否为外包
/// </summary>
public bool? IsOutSource { get; set; }
/// <summary>
/// 日期范围查询
/// </summary>

View File

@@ -27,7 +27,8 @@ public class DeviceUploadLogService : IDeviceUploadLogService
{
DeviceUploadLogTypeEnumType? type = request.Type == DeviceTypeEnumType.Attendance
? DeviceUploadLogTypeEnumType.Attendance
: request.Type == DeviceTypeEnumType.Door ? DeviceUploadLogTypeEnumType.Door
: request.Type == DeviceTypeEnumType.Door
? DeviceUploadLogTypeEnumType.Door
: null;
return await _dbContext.Queryable<DeviceUploadLogEntity>()
@@ -37,6 +38,8 @@ public class DeviceUploadLogService : IDeviceUploadLogService
.WhereIF(request.Sync.HasValue, deviceUp => deviceUp.Sync == request.Sync)
.WhereIF(request.SearchDateTimePeriod?.Start.HasValue == true, deviceUp => deviceUp.RaiseDateTime >= request.SearchDateTimePeriod.Start)
.WhereIF(request.SearchDateTimePeriod?.End.HasValue == true, deviceUp => deviceUp.RaiseDateTime <= request.SearchDateTimePeriod.End)
.WhereIF(request.IsOutSource.HasValue && request.IsOutSource.Value, deviceUp => SqlFunc.Subqueryable<OutSourceEntity>().Where(x => x.Code == deviceUp.UserUniqueNo).Any())
.WhereIF(request.IsOutSource.HasValue && !request.IsOutSource.Value, deviceUp => SqlFunc.Subqueryable<OutSourceEntity>().Where(x => x.Code == deviceUp.UserUniqueNo).NotAny())
.WhereIF(request.Search.IsPresent(), (deviceUp, device, ga) =>
ga.Code == request.Search
|| ga.Name == request.Search
@@ -65,10 +68,7 @@ public class DeviceUploadLogService : IDeviceUploadLogService
{
//判断存在的记录
Expression<Func<DeviceUploadLogEntity, bool>> where = LinqExpressionExtensions.False<DeviceUploadLogEntity>();
requests.ForEach(p =>
{
where = where.Or(x => x.DeviceUniqueNo == p.DeviceUniqueNo && x.SerialNo == p.SerialNo && x.RaiseDateTime == p.RaiseDateTime);
});
requests.ForEach(p => { where = where.Or(x => x.DeviceUniqueNo == p.DeviceUniqueNo && x.SerialNo == p.SerialNo && x.RaiseDateTime == p.RaiseDateTime); });
//处理冗余的请求数据
var exists = await _dbContext.Queryable<DeviceUploadLogEntity>().Where(where).ToListAsync();
@@ -94,12 +94,10 @@ public class DeviceUploadLogService : IDeviceUploadLogService
Type = device.Type == DeviceTypeEnumType.Attendance ? DeviceUploadLogTypeEnumType.Attendance : DeviceUploadLogTypeEnumType.Door,
TenantId = device.TenantId,
}).ToList();
}
return null;
}).Where(x => x != null).ToList();
await _dbContext.InsertAsync(records);

View File

@@ -33,24 +33,21 @@ public class SyncOriginCardInfoJob : BaseJob
//获取上传日志(有效的)
var deviceUniqueNos = devices.Select(x => x.UniqueNo).ToList();
var logs = await DbContext.Queryable<DeviceUploadLogEntity>()
var requests = await DbContext.Queryable<DeviceUploadLogEntity>()
.Where(x => deviceUniqueNos.Contains(x.DeviceUniqueNo))
.Where(x => !string.IsNullOrEmpty(x.UserUniqueNo))
.Where(x => x.Sync == false)
.ToListAsync();
//获取人员信息
var userCodes = logs.Select(x => x.UserUniqueNo).ToList();
var gainfoCodes = await DbContext.Queryable<GainfoEntity>().Where(x => userCodes.Contains(x.Code)).Select(x => x.Code).ToListAsync();
var requests = logs.Select(x => new UploadAttendanceRequest
.Where(x => SqlFunc.Subqueryable<GainfoEntity>().Where(p => p.Code == x.UserUniqueNo).Any())
.Where(x => SqlFunc.Subqueryable<OutSourceEntity>().Where(p => p.Code == x.UserUniqueNo).NotAny())
.Select(x => new UploadAttendanceRequest
{
Id = x.Id,
RaiseDateTime = x.RaiseDateTime,
ZNOTE = devices.First(item => item.UniqueNo == x.DeviceUniqueNo).DeployPlace,
ZWORKCODE = gainfoCodes.Contains(x.UserUniqueNo) ? x.UserUniqueNo?.TrimEnd('\0') : string.Empty,
}).Where(x => x.ZWORKCODE.IsPresent()).ToList();
ZWORKCODE = x.UserUniqueNo.TrimEnd('\0')
})
.ToListAsync();
if (requests.Any())
{

View File

@@ -1,3 +1,4 @@
using Dlhis.ScheduledTask.Common.Services;
using Kurisu.AspNetCore.Startup;
using Kurisu.AspNetCore.Utils;
using Kurisu.AspNetCore.Utils.Extensions;

View File

@@ -30,7 +30,7 @@ public class DeviceTaskAssignmentService : IDeviceTaskAssignmentService
.LeftJoin<DeviceEntity>((deviceTask, ga, device) => deviceTask.DeviceUniqueNo == device.UniqueNo)
.WhereIF(request.Type.HasValue, (deviceTask, ga, device) => deviceTask.DeviceType == request.Type)
.WhereIF(request.SearchDateTimePeriod?.Start.HasValue == true && request.SearchDateTimePeriod?.End.HasValue == true,
deviceTask => deviceTask.CreateTime >= request.SearchDateTimePeriod.Start && deviceTask.CreateTime <= request.SearchDateTimePeriod.End
deviceTask => deviceTask.ModifiedTime >= request.SearchDateTimePeriod.Start && deviceTask.ModifiedTime <= request.SearchDateTimePeriod.End
)
.WhereIF(request.TaskTypes.IsPresent(), deviceTask => request.TaskTypes.Contains(deviceTask.Type))
.WhereIF(request.Status.IsPresent(), deviceTask => request.Status.Contains(deviceTask.Status))

View File

@@ -7,6 +7,9 @@ using Microsoft.AspNetCore.Mvc;
namespace Dlhis.Sys.Identity.Controllers;
/// <summary>
/// 租户
/// </summary>
[Authorize]
[Route("api/[controller]")]
[ApiController]
@@ -84,7 +87,7 @@ public class TenantsController : ControllerBase
}
/// <summary>
/// 获取我的管理租户
/// 获取我管理的租户
/// </summary>
/// <returns></returns>
[HttpGet("my")]

View File

@@ -6,6 +6,9 @@ using Microsoft.AspNetCore.Mvc;
namespace Dlhis.Sys.Identity.Controllers;
/// <summary>
/// 用户租户
/// </summary>
[Authorize(Roles = "admin")]
[Route("api/[controller]")]
[ApiController]