feat 设备连接注册,sap人事范围,部门

This commit is contained in:
2023-12-28 16:04:00 +08:00
parent 25f7b3270c
commit d7cf07d940
48 changed files with 633 additions and 65 deletions

View File

@@ -17,11 +17,13 @@ public class DevicesController : ControllerBase
{
private readonly IDeviceService _deviceService;
private readonly IDeviceTemplateService _deviceTemplateService;
private readonly IDeviceConnectService _deviceConnectService;
public DevicesController(IDeviceService deviceService, IDeviceTemplateService deviceTemplateService)
public DevicesController(IDeviceService deviceService, IDeviceTemplateService deviceTemplateService, IDeviceConnectService deviceConnectService)
{
_deviceService = deviceService;
_deviceTemplateService = deviceTemplateService;
_deviceConnectService = deviceConnectService;
}
/// <summary>
@@ -67,4 +69,49 @@ public class DevicesController : ControllerBase
{
await _deviceService.SaveAsync(request);
}
/// <summary>
/// 设备注册
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpPost("resigter")]
public async Task<string> ResigterAsync(DeviceResigterRequest request)
{
return await _deviceConnectService.ResigterAsync(request);
}
/// <summary>
/// 获取尚未设置营业点的设备
/// </summary>
/// <returns></returns>
[HttpGet("businessplaces/incompletion")]
public async Task<List<DeviceNotSetBusinessPlaceResponse>> GetNotSetBusinessPlaceDevicesAsync()
{
return await _deviceConnectService.GetNotSetBusinessPlaceDevicesAsync();
}
/// <summary>
/// 设置设备营业点
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpPost("businessplaces")]
public async Task SetResigterBusinessPlaceAsync(DeviceSetResigterBusinessPlaceRequest request)
{
await _deviceConnectService.SetResigterBusinessPlaceAsync(request);
}
/// <summary>
/// 设备心跳
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpPost("heartbeat")]
public async Task HeartbeatAsync(DeviceHeartbeatRequest request)
{
await _deviceConnectService.HeartbeatAsync(request);
}
}

View File

@@ -0,0 +1,7 @@
namespace Dlhis.Basic.Device.Request
{
public class DeviceHeartbeatRequest
{
public string UniqueNo { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace Dlhis.Basic.Device.Request;
public class DeviceResigterRequest
{
/// <summary>
/// 唯一编码
/// </summary>
[Required(ErrorMessage = "设备唯一编码不能为空")]
public string UniqueNo { get; set; }
}

View File

@@ -0,0 +1,15 @@
namespace Dlhis.Basic.Device.Request
{
public class DeviceSetResigterBusinessPlaceRequest
{
/// <summary>
/// 唯一编码
/// </summary>
public string UniqueNo { get; set; }
/// <summary>
/// 营业点
/// </summary>
public Guid BusinessPlaceCode { get; set; }
}
}

View File

@@ -0,0 +1,5 @@
namespace Dlhis.Basic.Device.Response;
public class DeviceNotSetBusinessPlaceResponse
{
}

View File

@@ -1,5 +1,79 @@
namespace Dlhis.Basic.Device.Response;
using Dlhis.Entity.Device.Enums;
namespace Dlhis.Basic.Device.Response;
public class DeviceResponse
{
public long Id { get; set; }
/// <summary>
/// 设备code
/// </summary>
public Guid Code { get; set; }
/// <summary>
/// 设备唯一码,IP/MAC/SNO
/// </summary>
public string UniqueNo { get; set; }
/// <summary>
/// 心跳间隔
/// </summary>
public int HeartbeatInterval { get; set; }
/// <summary>
/// 品牌
/// </summary>
public string Brand { get; set; }
/// <summary>
/// 供应商
/// </summary>
public string Supplier { get; set; }
/// <summary>
/// 设备功能
/// </summary>
public List<DeviceFuncEnumType> Funcs { get; set; }
/// <summary>
/// 部署点
/// </summary>
public string DeployPlace { get; set; }
/// <summary>
/// 部署坐标
/// </summary>
public string DeployPosition { get; set; }
/// <summary>
/// 部署方向
/// </summary>
public string DeployDirection { get; set; }
/// <summary>
/// 模板code
/// </summary>
public Guid TemplateCode { get; set; }
/// <summary>
/// 连接信息
/// </summary>
public string ConnectionInfo { get; set; }
/// <summary>
/// 最后使用人
/// </summary>
public DateTime LastLogId { get; set; }
/// <summary>
/// 最后使用日期
/// </summary>
public DateTime LastLogDateTime { get; set; }
/// <summary>
/// 是否启用
/// </summary>
public bool Enable { get; set; }
}

View File

@@ -0,0 +1,36 @@
using Dlhis.Basic.Device.Request;
using Dlhis.Basic.Device.Response;
namespace Dlhis.Basic.Device.Services;
public interface IDeviceConnectService
{
/// <summary>
/// 设备注册
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task<string> ResigterAsync(DeviceResigterRequest request);
/// <summary>
/// 获取尚未设置营业点的设备
/// </summary>
/// <returns></returns>
Task<List<DeviceNotSetBusinessPlaceResponse>> GetNotSetBusinessPlaceDevicesAsync();
/// <summary>
/// 设置设备营业点
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task SetResigterBusinessPlaceAsync(DeviceSetResigterBusinessPlaceRequest request);
/// <summary>
/// 设备心跳
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task HeartbeatAsync(DeviceHeartbeatRequest request);
}

View File

@@ -0,0 +1,99 @@
using Dlhis.Basic.Device.Request;
using Dlhis.Basic.Device.Response;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Device.Entities;
using Dlhis.Entity.Device.Enums;
using Kurisu.AspNetCore.UnifyResultAndValidation;
using Kurisu.AspNetCore.Utils.Extensions;
using Kurisu.SqlSugar.Services;
using Mapster;
namespace Dlhis.Basic.Device.Services.Implements;
public class DeviceConnectService : IDeviceConnectService
{
private readonly IDbContext _dbContext;
public DeviceConnectService(IDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<string> ResigterAsync(DeviceResigterRequest request)
{
var device = await GetEnableDeviceAsync(request.UniqueNo);
var registry = await _dbContext.Queryable<DeviceRegistryEntity>().Where(x => x.DeviceUniqueNo == request.UniqueNo).FirstAsync();
if (registry == null)
{
registry = new DeviceRegistryEntity()
{
DeviceUniqueNo = request.UniqueNo,
LastHeartbeatTime = DateTime.Now,
};
await _dbContext.InsertAsync(registry);
return "设备注册成功";
}
return "请勿重复注册设备";
}
public async Task<List<DeviceNotSetBusinessPlaceResponse>> GetNotSetBusinessPlaceDevicesAsync()
{
var devices = await _dbContext.Queryable<DeviceEntity>().ToListAsync();
devices = devices.Where(x => x.Funcs.Any(item => item == DeviceFuncEnumType.Meal)).ToList();
return devices.Adapt<List<DeviceNotSetBusinessPlaceResponse>>();
}
public async Task SetResigterBusinessPlaceAsync(DeviceSetResigterBusinessPlaceRequest request)
{
var device = await GetEnableDeviceAsync(request.UniqueNo);
if (device.Funcs?.Any(x => x == DeviceFuncEnumType.Meal) != true)
{
throw new UserFriendlyException("当前设备无用餐功能,无法设置");
}
var registry = await _dbContext.Queryable<DeviceRegistryEntity>().Where(x => x.DeviceUniqueNo == request.UniqueNo).FirstAsync();
registry.ThrowIfNull($"{request.UniqueNo}的设备注册信息不存在,无法设置营业点");
var businessPlace = await _dbContext.Queryable<CanteenBusinessPlaceEntity>().Where(x => x.Code == request.BusinessPlaceCode).FirstAsync();
businessPlace.ThrowIfNull("营业点不存在,无法设置到设备注册信息中");
//更新营业点信息
registry.BusinessPlaceCode = businessPlace.Code;
registry.BusinessPlaceCustomCode = businessPlace.CustomCode;
await _dbContext.UpdateAsync(registry);
//todo 通知设备重新获取
}
public async Task HeartbeatAsync(DeviceHeartbeatRequest request)
{
var registry = await _dbContext.Queryable<DeviceRegistryEntity>().Where(x => x.DeviceUniqueNo == request.UniqueNo).FirstAsync();
registry.ThrowIfNull($"{request.UniqueNo}的设备注册信息不存在,心跳无效");
registry.LastHeartbeatTime = DateTime.Now;
await _dbContext.UpdateAsync(registry);
}
//******************************************************** help methods **********************************************************
/// <summary>
/// 获取启用的设备
/// </summary>
/// <param name="uniqueNo"></param>
/// <returns></returns>
private async Task<DeviceEntity> GetEnableDeviceAsync(string uniqueNo)
{
var device = await _dbContext.Queryable<DeviceEntity>()
.Where(x => x.UniqueNo == uniqueNo)
.FirstAsync();
device.ThrowIfNull($"未知的设备唯一编码{uniqueNo}");
device.Enable.ThrowIfFalse("设备尚未启用");
return device;
}
}

View File

@@ -1,6 +1,8 @@
using Dlhis.Basic.Device.Request;
using Dlhis.Basic.Device.Response;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Device.Entities;
using Dlhis.Entity.Device.Enums;
using Kurisu.AspNetCore.UnifyResultAndValidation;
using Kurisu.AspNetCore.Utils.Extensions;
using Kurisu.Core.DataAccess.Dto;
@@ -30,7 +32,6 @@ public class DeviceService : IDeviceService
return page;
}
public async Task SaveAsync(DeviceSaveRequest request)
{
await CheckUniqueNoExistsAsync(request);
@@ -56,7 +57,7 @@ public class DeviceService : IDeviceService
}
}
//******************************************************** help method **********************************************************
//******************************************************** help methods **********************************************************
/// <summary>
/// 检查设备模板是否存在
@@ -116,5 +117,6 @@ public class DeviceService : IDeviceService
exists.ThrowIfTrue("唯一号已经存在");
}
}

View File

@@ -27,7 +27,6 @@
<ItemGroup>
<Folder Include="Organization\Request\" />
<Folder Include="Organization\Response\" />
</ItemGroup>
</Project>

View File

@@ -116,10 +116,5 @@ namespace Dlhis.Basic.MealUser.Services.Implements
.AnyAsync();
checkGainfoGuestno.ThrowIfTrue($"档案号[{request.gainfoPageResponse.Guestno}]已存在");
}
public Task OnboardingAsync(GainfoDImissionRequest request)
{
throw new NotImplementedException();
}
}
}

View File

@@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Authorization;
using Dlhis.Basic.Organization.Response;
using Dlhis.Basic.Organization.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Dlhis.Basic.Organization.Controllers;
@@ -11,4 +13,20 @@ namespace Dlhis.Basic.Organization.Controllers;
[ApiController]
public class DepartmentsController : ControllerBase
{
private readonly IDepartmentService _departmentService;
public DepartmentsController(IDepartmentService departmentService)
{
_departmentService = departmentService;
}
/// <summary>
/// 获取部门树
/// </summary>
/// <returns></returns>
[HttpGet("tree")]
public async Task<List<DepartmentTreeResponse>> GetTreeAsync()
{
return await _departmentService.GetTreeAsync();
}
}

View File

@@ -1,13 +0,0 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Dlhis.Basic.Organization.Controllers;
/// <summary>
/// 人事范围
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class PersonalScopesController : ControllerBase
{
}

View File

@@ -0,0 +1,26 @@
using Dlhis.Basic.Organization.Response;
using Dlhis.Basic.Organization.Services;
using Microsoft.AspNetCore.Mvc;
namespace Dlhis.Basic.Organization.Controllers;
/// <summary>
/// 人事范围
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class WerksController : ControllerBase
{
private readonly IWerkService _werkService;
public WerksController(IWerkService werkService)
{
_werkService = werkService;
}
[HttpGet("list")]
public async Task<List<WerkResponse>> GetListAsync()
{
return await _werkService.GetListAsync();
}
}

View File

@@ -0,0 +1,21 @@
using SqlSugar;
namespace Dlhis.Basic.Organization.Response;
public class DepartmentTreeResponse
{
/// <summary>
/// 部门号
/// </summary>
public string Code { get; set; }
/// <summary>
/// 部门名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 下级部门
/// </summary>
public List<DepartmentTreeResponse> Next { get; set; }
}

View File

@@ -0,0 +1,23 @@
using SqlSugar;
namespace Dlhis.Basic.Organization.Response;
public class WerkResponse
{
public long Id { get; set; }
/// <summary>
/// 代号
/// </summary>
public string Code { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 是否可见
/// </summary>
public bool Visible { get; set; }
}

View File

@@ -0,0 +1,8 @@
using Dlhis.Basic.Organization.Response;
namespace Dlhis.Basic.Organization.Services;
public interface IDepartmentService : IScopeDependency
{
Task<List<DepartmentTreeResponse>> GetTreeAsync();
}

View File

@@ -0,0 +1,8 @@
using Dlhis.Basic.Organization.Response;
namespace Dlhis.Basic.Organization.Services;
public interface IWerkService : IScopeDependency
{
Task<List<WerkResponse>> GetListAsync();
}

View File

@@ -0,0 +1,41 @@
using Dlhis.Basic.Organization.Response;
using Dlhis.Entity.Basic.Entity;
using Kurisu.AspNetCore.Utils.Extensions;
using Kurisu.SqlSugar.Services;
using Mapster;
namespace Dlhis.Basic.Organization.Services.Implements;
public class DepartmentService : IDepartmentService
{
private readonly IDbContext _dbContext;
public DepartmentService(IDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<List<DepartmentTreeResponse>> GetTreeAsync()
{
var departments = await _dbContext.Queryable<DepartmentEntity>().ToListAsync();
var tops = departments.Where(x => x.PCode.IsEmpty()).Adapt<List<DepartmentTreeResponse>>();
tops.ForEach(x =>
{
RecursionGetNext(x, departments);
});
return tops;
}
private void RecursionGetNext(DepartmentTreeResponse current, List<DepartmentEntity> departments)
{
var next = departments.Where(x => x.PCode == current.Code).ToList();
current.Next = next.Adapt<List<DepartmentTreeResponse>>();
foreach (var item in next)
{
RecursionGetNext(item.Adapt<DepartmentTreeResponse>(), departments);
}
}
}

View File

@@ -0,0 +1,22 @@
using Dlhis.Basic.Organization.Response;
using Dlhis.Entity.Basic.Entity;
using Kurisu.SqlSugar.Services;
namespace Dlhis.Basic.Organization.Services.Implements;
public class WerkService : IWerkService
{
private readonly IDbContext _dbContext;
public WerkService(IDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<List<WerkResponse>> GetListAsync()
{
return await _dbContext.Queryable<WerkEntity>()
.Select<WerkResponse>()
.ToListAsync();
}
}

View File

@@ -0,0 +1,7 @@
using Kurisu.Core.DataAccess.Dto;
namespace Dlhis.Canteen.BalanceRecord.Request;
public class BalanceRecordRequest : PageDto
{
}

View File

@@ -0,0 +1,5 @@
namespace Dlhis.Canteen.BalanceRecord.Response;
public class BalanceRecordResponse
{
}

View File

@@ -0,0 +1,10 @@
using Dlhis.Canteen.BalanceRecord.Request;
using Dlhis.Canteen.BalanceRecord.Response;
using Kurisu.Core.DataAccess.Dto;
namespace Dlhis.Canteen.BalanceRecord.Services;
public interface IBalanceRecordService : IScopeDependency
{
Task<Pagination<BalanceRecordResponse>> GetPageAsync(BalanceRecordRequest request);
}

View File

@@ -0,0 +1,25 @@
using Dlhis.Canteen.BalanceRecord.Request;
using Dlhis.Canteen.BalanceRecord.Response;
using Dlhis.Entity.Canteen.Entities;
using Kurisu.Core.DataAccess.Dto;
using Kurisu.SqlSugar.Extensions;
using Kurisu.SqlSugar.Services;
namespace Dlhis.Canteen.BalanceRecord.Services.Implements;
public class BalanceRecordService : IBalanceRecordService
{
private readonly IDbContext _dbContext;
public BalanceRecordService(IDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<Pagination<BalanceRecordResponse>> GetPageAsync(BalanceRecordRequest request)
{
return await _dbContext.Queryable<BalanceRecordEntity>()
.Select<BalanceRecordResponse>()
.ToPageListAsync(request);
}
}

View File

@@ -29,9 +29,6 @@
<ItemGroup>
<Folder Include="BalanceRecord\Controllers\" />
<Folder Include="BalanceRecord\Request\" />
<Folder Include="BalanceRecord\Response\" />
<Folder Include="BalanceRecord\Services\Implements\" />
<Folder Include="OaEMealVoucher\Controllers\" />
<Folder Include="OaEMealVoucher\Request\" />
<Folder Include="OaEMealVoucher\Response\" />

View File

@@ -1,5 +1,44 @@
namespace Dlhis.Canteen.Order.Request;
using System.ComponentModel.DataAnnotations;
using Dlhis.Entity.Canteen.Enums;
namespace Dlhis.Canteen.Order.Request;
public class OrderAddRequest
{
/// <summary>
/// 消费机器唯一信息
/// </summary>
public string UniqueNo { get; set; }
/// <summary>
/// 档案号/QrCode
/// </summary>
public string UserId { get; set; }
/// <summary>
/// 学工号
/// </summary>
public string UserCode { get; set; }
/// <summary>
/// 来源
/// </summary>
[EnumDataType(typeof(BalanceRecordSourceEnumType))]
public BalanceRecordSourceEnumType Source { get; set; }
/// <summary>
/// 收入/支出
/// </summary>
[EnumDataType(typeof(BalanceRecordTypeEnumType))]
public BalanceRecordTypeEnumType Type { get; set; }
/// <summary>
/// 金额 + - 表示
/// </summary>
public decimal Amount { get; set; }
/// <summary>
/// 餐补月份
/// </summary>
public string SubsidiesFromMonth { get; set; }
}

View File

@@ -25,8 +25,8 @@ public class OrderService : IOrderService
return page;
}
public Task AddAsync(OrderAddRequest request)
public async Task AddAsync(OrderAddRequest request)
{
throw new NotImplementedException();
}
}

View File

@@ -13,13 +13,4 @@ public class SqlSugarPack : BaseAppPack
{
services.AddSqlSugar();
}
public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//using var scope = app.ApplicationServices.CreateScope();
//var db = scope.ServiceProvider.GetService<ISqlSugarClient>();
//var tables = App.ActiveTyps.Where(x => x.IsDefined(typeof(SugarTable), false)).ToArray();
//db.DbMaintenance.CreateDatabase();
//db.CodeFirst.InitTables(tables);
}
}

View File

@@ -0,0 +1,28 @@
using SqlSugar;
namespace Dlhis.Entity.Basic.Entity;
/// <summary>
/// 部门
/// </summary>
[SugarTable(TableName = "Department", TableDescription = "部门")]
public class DepartmentEntity : SugarBaseEntity
{
/// <summary>
/// 部门号
/// </summary>
[SugarColumn(ColumnDescription = "部门号")]
public string Code { get; set; }
/// <summary>
/// 上级部门号
/// </summary>
[SugarColumn(ColumnDescription = "上级部门号")]
public string PCode { get; set; }
/// <summary>
/// 部门名称
/// </summary>
[SugarColumn(ColumnDescription = "部门名称")]
public string Name { get; set; }
}

View File

@@ -43,7 +43,7 @@ public class DeviceEntity : SugarBaseEntity, ITenantId
/// <summary>
/// 设备功能
/// </summary>
[SugarColumn(ColumnDataType = "varchar(150)", IsJson = true, ColumnDescription = "设备功能")]
[SugarColumn(ColumnDataType = "varchar(150)", IsJson = true, ColumnDescription = "设备功能", DefaultValue = "[]")]
public List<DeviceFuncEnumType> Funcs { get; set; }
/// <summary>
@@ -95,12 +95,5 @@ public class DeviceEntity : SugarBaseEntity, ITenantId
[SugarColumn(ColumnDataType = "bit", ColumnDescription = "是否启用")]
public bool Enable { get; set; }
/// <summary>
/// 设别状态
/// </summary>
[SugarColumn(ColumnDescription = "设别状态")]
public string Status { get; set; }
public string TenantId { get; set; }
}

View File

@@ -144,9 +144,10 @@ public class GainfoEntity : SugarBaseEntity
/// </summary>
[SugarColumn(ColumnDescription = "外文名字")]
public string Gname_en { get; set; }
/// <summary>
/// 卡号
/// </summary>
[SugarColumn(ColumnDescription = "人事范围")]
public string Werks { get; set; }
[SugarColumn(ColumnDescription = "卡号")]
public string CarNo { get; set; }
}

View File

@@ -0,0 +1,25 @@
using SqlSugar;
namespace Dlhis.Entity.Basic.Entity;
[SugarTable(TableName = "Werk", TableDescription = "人事范围")]
public class WerkEntity : SugarBaseEntity
{
/// <summary>
/// 代号
/// </summary>
[SugarColumn(ColumnDescription = "代号")]
public string Code { get; set; }
/// <summary>
/// 名称
/// </summary>
[SugarColumn(ColumnDescription = "名称")]
public string Name { get; set; }
/// <summary>
/// 是否可见
/// </summary>
[SugarColumn(ColumnDescription = "是否可见", ColumnDataType = "bit")]
public bool Visible { get; set; }
}

View File

@@ -84,12 +84,6 @@ public class BalanceRecordEntity : SugarBaseEntity, ITenantId
[SugarColumn(ColumnDescription = "所属成本日期")]
public DateTime CostDate { get; set; }
/// <summary>
/// 操作人
/// </summary>
[SugarColumn(ColumnDescription = "操作人")]
public string OperateUser { get; set; }
/// <summary>
/// 消费机器唯一信息
/// </summary>

View File

@@ -29,13 +29,13 @@ public enum BalanceRecordSourceEnumType
/// <summary>
/// 来自本基地补贴
/// </summary>
[Description("来自本基地补贴")]
[Description("本基地补贴")]
LocalTenantSubsidies,
/// <summary>
/// 来自其他基地补贴
/// </summary>
[Description("来自其他基地补贴")]
[Description("其他基地补贴")]
OtherTenantSubsidies,

View File

@@ -31,7 +31,7 @@ public class DeviceRegistryEntity : SugarBaseEntity, ITenantId
/// 营业点code(可为空)
/// </summary>
[SugarColumn(IsNullable = true, ColumnDescription = "注册时间")]
public string BusinessPlaceCode { get; set; }
public Guid BusinessPlaceCode { get; set; }
/// <summary>
/// 营业点手工号(可为空)