Merge branch 'development' of https://git.dlhis.com/liguoyang/jinko.yikatong into development

This commit is contained in:
cheche
2024-03-15 09:28:11 +08:00
25 changed files with 331 additions and 58 deletions

View File

@@ -25,6 +25,11 @@ public class BusinessPlaceSaveRequest
[Required(ErrorMessage = "营业点名称不能为空")]
public string Name { get; set; }
/// <summary>
/// 供应商
/// </summary>
public string Supplier { get; set; }
/// <summary>
/// 状态 CanteenBusinessPlaceStatusEnumType
/// </summary>

View File

@@ -23,6 +23,12 @@ public class BusinessPlaceResponse
/// </summary>
public string Name { get; set; }
/// <summary>
/// 供应商
/// </summary>
public string Supplier { get; set; }
/// <summary>
/// 状态,停用/启用
/// </summary>

View File

@@ -25,7 +25,7 @@ public class BusinessPlaceService : IBusinessPlaceService
var page = await _dbContext.Queryable<BusinessPlaceEntity>()
.LeftJoin<BusinessPlaceShiftRelationshipEntity>((x, ps) => x.Code == ps.PlaceCode)
.LeftJoin<BusinessShiftEntity>((x, ps, s) => s.Code == ps.ShiftCode)
.WhereIF(request.Search.IsPresent(), x => x.CustomCode.Contains(request.Search)
.WhereIF(request.Search.IsPresent(), x => x.CustomCode.Contains(request.Search)
|| x.Code.ToString().Contains(request.Search) || x.Name.Contains(request.Search))
.WhereIF(request.Catalog.HasValue, x => x.Catalog == request.Catalog)
.WhereIF(request.Status.HasValue, x => x.Status == request.Status)
@@ -39,7 +39,7 @@ public class BusinessPlaceService : IBusinessPlaceService
Catalog = x.Catalog,
CustomCode = x.CustomCode,
Source = x.Source,
Supplier = x.Supplier,
ShiftCode = s.Code,
ShiftName = s.Name
})
@@ -65,6 +65,7 @@ public class BusinessPlaceService : IBusinessPlaceService
if (!request.Id.HasValue)
{
var entity = request.Adapt<BusinessPlaceEntity>();
entity.CustomCode = request.CustomCode;
entity.Code = Guid.NewGuid();
await _dbContext.InsertAsync(entity);
}

View File

@@ -62,7 +62,8 @@ public class BusinessPlaceShiftService : IBusinessPlaceShiftService
public async Task<List<BusinessPlaceShiftResponse>> GetListAsync()
{
var result = await _dbContext.Queryable<BusinessShiftEntity>()
.Select<BusinessPlaceShiftResponse>().ToListAsync();
.Select<BusinessPlaceShiftResponse>()
.ToListAsync();
return result;
}
@@ -71,15 +72,14 @@ public class BusinessPlaceShiftService : IBusinessPlaceShiftService
{
await CheckExistsAsync(request);
Guid code = Guid.Empty;
if (!request.Id.HasValue)
{
var entity = request.Adapt<BusinessShiftEntity>();
entity.CustomCode = request.CustomCode;
entity.Code = Guid.NewGuid();
await _dbContext.InsertAsync(entity);
code = entity.Code;
return entity.Code;
}
else
{
@@ -89,10 +89,8 @@ public class BusinessPlaceShiftService : IBusinessPlaceShiftService
request.Adapt(entity);
await _dbContext.UpdateAsync(entity);
code = entity.Code;
return entity.Code;
}
return code;
}
public async Task SaveMealShiftsAsync(List<BusinessPlaceShiftSaveMealShiftRequest> requests)
@@ -198,7 +196,7 @@ public class BusinessPlaceShiftService : IBusinessPlaceShiftService
.ToListAsync();
var devices = await _dbContext.Queryable<DeviceEntity>().ToListAsync();
var list = new List<DeviceCodeNameDetail>();
if (regiss.Count > 0)
{

View File

@@ -2,6 +2,8 @@
using Dlhis.Basic.Device.Response;
using Dlhis.Basic.Device.Services;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop;
using Kurisu.AspNetCore.EventBus.Abstractions;
using Kurisu.AspNetCore.Scope;
using Kurisu.Core.DataAccess.Dto;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -218,5 +220,4 @@ public class DevicesController : ControllerBase
{
return await _deviceService.BulkUploadsAsync(request);
}
}

View File

@@ -82,6 +82,7 @@ public class DeviceService : IDeviceService
if (!request.Id.HasValue)
{
entity = request.Adapt<DeviceEntity>();
entity.UniqueNo = request.UniqueNo;
entity.Code = Guid.NewGuid();
await _dbContext.InsertAsync(entity);
//同时保存注册信息

View File

@@ -17,7 +17,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Kurisu.AspNetCore" Version="0.6.1" />
<PackageReference Include="Kurisu.AspNetCore" Version="0.7.1" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,6 +1,7 @@
using Dlhis.Entity.Canteen.Enums;
using Kurisu.Core.DataAccess.Entity;
using Kurisu.SqlSugar;
using Mapster;
using SqlSugar;
using SqlSugar.DbConvert;
@@ -21,9 +22,15 @@ public class BusinessPlaceEntity : SugarBaseEntity, ITenantId
/// <summary>
/// 自定义代号
/// </summary>
[AdaptIgnore(MemberSide.Destination)]
[SugarColumn(ColumnDescription = "自定义手工号")]
public string CustomCode { get; set; }
/// <summary>
/// 供应商
/// </summary>
[SugarColumn(ColumnDescription = "供应商")]
public string Supplier { get; set; }
/// <summary>
/// 营业点名称

View File

@@ -1,5 +1,6 @@
using Kurisu.Core.DataAccess.Entity;
using Kurisu.SqlSugar;
using Mapster;
using SqlSugar;
namespace Dlhis.Entity.Basic.Entity;
@@ -19,6 +20,7 @@ public class BusinessShiftEntity : SugarBaseEntity, ITenantId
/// <summary>
/// 自定义代号
/// </summary>
[AdaptIgnore(MemberSide.Destination)]
[SugarColumn(ColumnDescription = "自定义手工号")]
public string CustomCode { get; set; }

View File

@@ -1,6 +1,7 @@
using Dlhis.Entity.Device.Enums;
using Kurisu.Core.DataAccess.Entity;
using Kurisu.SqlSugar;
using Mapster;
using SqlSugar;
using SqlSugar.DbConvert;
@@ -21,6 +22,7 @@ public class DeviceEntity : SugarBaseEntity, ITenantId
/// <summary>
/// 设备唯一码,IP/MAC/SNO
/// </summary>
[AdaptIgnore(MemberSide.Destination)]
[SugarColumn(ColumnDescription = "设备唯一码", IsNullable = false, UniqueGroupNameList = new[] { "Idx_Device_UniqueNo" })]
public string UniqueNo { get; set; }

View File

@@ -9,24 +9,38 @@ namespace Dlhis.Entity.Basic.Entity;
/// 餐补记录
/// </summary>
[SugarTable(TableName = "MealSupplementRecord", TableDescription = "餐补记录")]
public class MealSupplementRecordEntity : SugarBaseEntity
public class MealSupplementRecordEntity : MealSupplementRequestRecordEntity
{
/// <summary>
/// 唯一号
/// </summary>
[SugarColumn(IsNullable = false, ColumnDescription = "唯一号", UniqueGroupNameList = new[] { "idx_MealSupplementRecord_UniqueId" })]
public string UniqueId { get; set; }
public override string UniqueId { get; set; }
/// <summary>
/// 工号
/// </summary>
[SugarColumn(IsNullable = false, ColumnDescription = "工号")]
public string Code { get; set; }
[SugarColumn(IsNullable = false, ColumnDescription = "工号", IndexGroupNameList = new[] { "idx_MealSupplementRecord_Code" })]
public override string Code { get; set; }
/// <summary>
/// 餐补状态
/// </summary>
[SugarColumn(ColumnDataType = "varchar(50)", SqlParameterDbType = typeof(EnumToStringConvert))]
public MealSupplementStatusEnumtype Status { get; set; }
}
[SugarTable(TableName = "MealSupplementRequestRecord", TableDescription = "餐补请求记录")]
public class MealSupplementRequestRecordEntity : SugarBaseEntity
{
public virtual string UniqueId { get; set; }
public virtual string Code { get; set; }
/// <summary>
/// 考勤日期
/// </summary>
[SugarColumn(IsNullable = false, ColumnDescription = "考勤日期")]
[SugarColumn(ColumnDataType = "date", IsNullable = false, ColumnDescription = "考勤日期")]
public DateTime Date { get; set; }
/// <summary>
@@ -41,9 +55,6 @@ public class MealSupplementRecordEntity : SugarBaseEntity
[SugarColumn(IsNullable = false, ColumnDescription = "厂区")]
public string Factory { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
/// <summary>
@@ -51,10 +62,4 @@ public class MealSupplementRecordEntity : SugarBaseEntity
/// </summary>
[SugarColumn(IsNullable = false, ColumnDescription = "餐补")]
public decimal Amount { get; set; }
/// <summary>
/// 餐补状态
/// </summary>
[SugarColumn(ColumnDataType = "varchar(50)", SqlParameterDbType = typeof(EnumToStringConvert))]
public MealSupplementStatusEnumtype Status { get; set; }
}

View File

@@ -16,4 +16,10 @@ public class WerkEntity : SugarBaseEntity
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 是否启用
/// </summary>
[SugarColumn(ColumnDataType = "bit", DefaultValue = "1")]
public bool Enable { get; set; }
}

View File

@@ -47,5 +47,11 @@ public class DeviceTaskEntity : SugarBaseEntity, ITenantId, IVersion
[SugarColumn(ColumnDataType = "longtext")]
public string ResultMessage { get; set; }
/// <summary>
/// 取消id
/// </summary>
public long CancellationId { get; set; }
public string TenantId { get; set; }
}

View File

@@ -26,6 +26,13 @@ public enum DeviceTaskStatusEnumType
[Description("下发完成")]
Success = 10,
/// <summary>
/// 取消
/// </summary>
[Description("取消")]
Cancel = 95,
/// <summary>
/// 异常
/// </summary>

View File

@@ -1,7 +1,9 @@
using Dlhis.External.MealSupplement.Channel;
using Dlhis.Entity.Basic.Entity;
using Dlhis.External.MealSupplement.Channel;
using Dlhis.External.MealSupplement.Request;
using Kurisu.AspNetCore.EventBus.Abstractions;
using Kurisu.SqlSugar.Services;
using Mapster;
namespace Dlhis.External.MealSupplement.Services.Implements;
@@ -10,7 +12,7 @@ public class MealSupplementService : IMealSupplementService
private readonly IEventBus _eventBus;
private readonly IDbContext _dbContext;
public MealSupplementService(IEventBus eventBus , IDbContext dbContext)
public MealSupplementService(IEventBus eventBus, IDbContext dbContext)
{
_eventBus = eventBus;
_dbContext = dbContext;
@@ -18,6 +20,7 @@ public class MealSupplementService : IMealSupplementService
public async Task DoSupplementsAsync(List<MealSupplementReceiveReuqest> reuqests)
{
await _dbContext.InsertAsync(reuqests.Adapt<List<MealSupplementRequestRecordEntity>>());
await _eventBus.PublishAsync(new MealSupplementMessage { Items = reuqests });
}
}

View File

@@ -0,0 +1,165 @@
using Dlhis.Entity.Device.Entities;
using Dlhis.Entity.Device.Enums;
using Kurisu.AspNetCore.Utils.Extensions;
using Kurisu.Core.DataAccess.Entity;
using Kurisu.SqlSugar.Services;
using SqlSugar;
using System.Linq.Expressions;
namespace Dlhis.ScheduledTask.CommonJobs;
public class CancelDuplicationTaskJob
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<CancelDuplicationTaskJob> _logger;
public CancelDuplicationTaskJob(IServiceProvider serviceProvider, ILogger<CancelDuplicationTaskJob> logger)
{
_serviceProvider = serviceProvider;
_logger = logger;
}
public async Task RunAsync()
{
_logger.LogInformation("抵消任务开始处理");
using (var scope = _serviceProvider.CreateScope())
{
var optionService = scope.ServiceProvider.GetService<ISqlSugarOptionsService>();
var db = scope.ServiceProvider.GetService<IDbContext>();
db.Client.QueryFilter.ClearAndBackup<ITenantId>();
optionService.IgnoreTenant = true;
try
{
//人员下发任务相关
var taskTypes = new List<DeviceTaskEnumType>() { DeviceTaskEnumType.Add, DeviceTaskEnumType.Delete, DeviceTaskEnumType.Update };
var deviceTasks = await db.Queryable<DeviceTaskEntity>()
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)//没有被获取
.Where(x => taskTypes.Contains(x.Type))
.OrderBy(x => x.CreateTime, OrderByType.Desc)
.ToListAsync();
var groupData = deviceTasks.GroupBy(x => new { x.TenantId, x.UserNo, x.DeviceUniqueNo });
foreach (var deviceTaskPack in groupData)
{
var uniqueInfo = deviceTaskPack.Key;
var data = deviceTaskPack.ToList();
foreach (var item in data)
{
try
{
Expression<Func<DeviceTaskEntity, bool>> where = LinqExpressionExtension.False<DeviceTaskEntity>();
var ignoreData = new List<IdVersion>();
//最新一条更新人员信息
if (item.Type == DeviceTaskEnumType.Update && item.Status == DeviceTaskStatusEnumType.Wait)
{
//获取过往的更新人员任务
ignoreData = data.Where(x => x.Type == DeviceTaskEnumType.Update)
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
.Where(x => x.Id != item.Id)
.Where(x => item.CreateTime > x.CreateTime)
.Select(x => new IdVersion { Id = x.Id, Version = x.Version }).ToList();
}
//最新一条删除人员信息
else if (item.Type == DeviceTaskEnumType.Delete && item.Status == DeviceTaskStatusEnumType.Wait)
{
//存在成功下发的任务,此处可以直接把其他任务取消
if (await db.Queryable<DeviceTaskEntity>().Where(x => x.UserNo == item.UserNo)
.Where(x => x.DeviceUniqueNo == item.DeviceUniqueNo)
.Where(x => x.TenantId == item.TenantId).Where(x => x.Status == DeviceTaskStatusEnumType.Success).AnyAsync())
{
ignoreData.AddRange(data.Where(x => x.Type == DeviceTaskEnumType.Add
|| x.Type == DeviceTaskEnumType.Delete
|| x.Type == DeviceTaskEnumType.Update)
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
.Where(x => x.Id != item.Id)
.Where(x => item.CreateTime > x.CreateTime)
.Select(x => new IdVersion { Id = x.Id, Version = x.Version })
);
}
else
{
var currentIds = new List<long> { item.Id };
var beforeTask = data.Where(x => x.Type == DeviceTaskEnumType.Add || x.Type == DeviceTaskEnumType.Update)
.Where(x => !currentIds.Contains(x.Id))
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
.Where(x => item.CreateTime > x.CreateTime)
.FirstOrDefault();
//逻辑正确,最终beforeTask.type == DeviceTaskEnumType.Add
while (beforeTask != null && beforeTask.Type == DeviceTaskEnumType.Update)
{
ignoreData.Add(new IdVersion() { Id = beforeTask.Id, Version = beforeTask.Version });
currentIds.Add(beforeTask.Id);
beforeTask = data.Where(x => x.Type == DeviceTaskEnumType.Add || x.Type == DeviceTaskEnumType.Update)
.Where(x => !currentIds.Contains(x.Id))
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
.Where(x => item.CreateTime > x.CreateTime)
.FirstOrDefault();
}
if (beforeTask != null)
{
ignoreData.Add(new IdVersion() { Id = beforeTask.Id, Version = beforeTask.Version });
ignoreData.Add(new IdVersion() { Id = item.Id, Version = item.Version });
}
}
}
if (ignoreData.Any())
{
ignoreData.ForEach(p =>
{
where = where.Or(x => x.Id == p.Id && x.Version == p.Version && x.Status == DeviceTaskStatusEnumType.Wait);
});
await db.Updateable<DeviceTaskEntity>()
.SetColumns(x => x.Version == x.Version + 1)
.SetColumns(x => x.Status == DeviceTaskStatusEnumType.Cancel)
.SetColumns(x => x.CancellationId == item.Id)
.SetColumns(x => x.ModifiedTime == DateTime.Now)
.Where(where)
.ExecuteCommandAsync();
data.ForEach(x =>
{
if (ignoreData.Any(p => p.Id == x.Id))
x.Status = DeviceTaskStatusEnumType.Cancel;
});
}
}
catch (Exception ex)
{
_logger.LogError(ex, "抵消处理异常:{message}", ex.Message);
}
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "抵消处理异常:{message}", ex.Message);
}
finally
{
db.Client.QueryFilter.Restore();
optionService.IgnoreTenant = false;
}
}
_logger.LogInformation("抵消任务处理完成");
}
class IdVersion
{
public long Id { get; set; }
public int Version { get; set; }
}
}

View File

@@ -53,10 +53,16 @@ public class JobPack : BaseAppPack
TimeZone = TimeZoneInfo.Local
});
//处理重复下发任务
RecurringJob.AddOrUpdate<CancelDuplicationTaskJob>("CancelDuplicationTask", s => s.RunAsync(), "0/15 * * * * ?", new RecurringJobOptions
{
TimeZone = TimeZoneInfo.Local
});
RecurringJob.AddOrUpdate<TempCreateUserJob>("TempCreateUser", s => s.RunAsync(), "0 0 5 * * ?", new RecurringJobOptions
{
TimeZone = TimeZoneInfo.Local
});
}
}

View File

@@ -65,7 +65,7 @@ public class JinkoSapService : IJinkoSapService
{
var apiUrl = "/RESTAdapter/Rest/EHR_PERSONNEL/";
var werks = await _dbContext.Queryable<WerkEntity>().ToListAsync();
var werks = await _dbContext.Queryable<WerkEntity>().Where(x => x.Enable).ToListAsync();
List<SapPersonItem> persons = new();
List<SapPersonJobStatus> jobInfos = new();

View File

@@ -1,6 +1,5 @@
using Dlhis.Entity.Device.Enums;
using Kurisu.AspNetCore.Utils.Extensions;
using SqlSugar;
namespace Dlhis.ScheduledTask.TaskAssignment.Response;
@@ -83,14 +82,4 @@ public class DeviceTaskAssignmentResponse
/// 部署点
/// </summary>
public string DeployPlace { get; set; }
/// <summary>
/// 连接信息
/// </summary>
public string ConnectionInfo { get; set; }
/// <summary>
/// 设备名称
/// </summary>
public string DeviceName { get; set; }
}

View File

@@ -54,8 +54,6 @@ public class DeviceTaskAssignmentService : IDeviceTaskAssignmentService
LastUpdateTime = deviceTask.ModifiedTime,
TenantId = deviceTask.TenantId,
DeployPlace = device.DeployPlace,
ConnectionInfo = device.ConnectionInfo,
DeviceName = device.Supplier
})
.ToPageListAsync(request);

View File

@@ -10,6 +10,8 @@
<ItemGroup>
<PackageReference Include="Ocelot" Version="23.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.8" />
</ItemGroup>
</Project>

View File

@@ -1,16 +1,19 @@
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("ocelot.json", true, true);
// Add services to the container.
using Gateway;
builder.Services.AddOcelot();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseOcelot().Wait();
app.Run();
public class Program
{
public static void Main(string[] args)
{
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(builder =>
{
builder.AddJsonFile("ocelot.json", true, true);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.Build().Run();
}
}

41
Src/Gateway/Startup.cs Normal file
View File

@@ -0,0 +1,41 @@
using Microsoft.OpenApi.Models;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
namespace Gateway;
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddEndpointsApiExplorer();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Gateway API", Version = "v1", Description = "# gateway api..." });
});
services.AddOcelot();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
var services = Configuration.GetSection("Services").Get<List<string>>();
foreach (var s in services)
{
c.SwaggerEndpoint($"/{s.ToLower()}/swagger/v1/swagger.json", s);
}
});
app.UseOcelot().Wait();
}
}

View File

@@ -5,5 +5,13 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"Services": [
"Basic",
"Common",
"Canteen",
"Scheduled",
"User",
"Sys"
]
}

View File

@@ -84,6 +84,17 @@
"Port": 31007
}
]
},
{
"UpstreamPathTemplate": "/{url}/swagger/v1/swagger.json",
"DownstreamPathTemplate": "/{url}/swagger/v1/swagger.json",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "yikatong.isawesome.cn",
"Port": 443
}
]
}
],
"GlobalConfiguration": {}