Files
jinko.yikatong/Src/Dlhis.External/Appointment/Services/Implements/AppointmentService.cs
2025-09-15 16:14:34 +08:00

265 lines
11 KiB
C#

using System.Text;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Basic.Enums;
using Dlhis.Entity.Visitor.Entity;
using Dlhis.Entity.Visitor.Enums;
using Dlhis.External.Appointment.Request;
using Kurisu.AspNetCore.Cache;
using Kurisu.AspNetCore.CustomClass;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Utils.Extensions;
namespace Dlhis.External.Appointment.Services.Implements;
public class AppointmentService : IAppointmentService
{
private readonly IDbContext _dbContext;
private readonly RedisCache _redisCache;
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<AppointmentService> _logger;
public AppointmentService(IDbContext dbContext,
RedisCache redisCache,
IHttpClientFactory httpClientFactory,
ILogger<AppointmentService> logger)
{
_dbContext = dbContext;
_redisCache = redisCache;
_httpClientFactory = httpClientFactory;
_logger = logger;
}
public async Task ReceiveAsync(VisitorAppointmentReceiveRequest request)
{
if (request.Factory == "501")
{
await ReSendTo501Async(request);
return;
}
var exists = await _dbContext.Queryable<VisitorAppointmentEntity>().Where(x => x.No == request.No).AnyAsync();
exists.ThrowIfTrue("已经存在申请");
var areas = await _dbContext.Queryable<AppointmentAreaEntity>().Where(x => x.TenantId == request.Factory).ToListAsync();
var mst = new VisitorAppointmentEntity
{
No = request.No,
Title = request.Title,
Code = request.Code,
Source = request.Source,
Date = request.Date,
Factory = request.Factory,
Reason = request.Reason,
Remark = request.Remark,
};
await _dbContext.InsertAsync(mst);
var invalids = new[] { GainfoUserTypeEnumType.Normal, GainfoUserTypeEnumType.SecurityWhite };
var idNos = request.Items.Where(x => x.IsEnterDoorArea).Select(x => x.IdNo).Distinct().ToList();
var errors = await _dbContext.Queryable<GainfoEntity>()
.Where(x => idNos.Contains(x.IdNo) || idNos.Contains(x.Code))
.Where(x => invalids.Contains(x.Type))
.Select(x => x.IdNo + x.Name)
.ToListAsync();
errors.ThrowIfExists($"内部人员无法发起门岗预约({errors.Join(",")})");
foreach (var item in request.Items)
{
if (item.IsEnterDoorArea && areas.Where(x => x.Type == AppointmentAreaEnumType.Door)
.Select(x => x.CustomCode)
.Contains(item.ApplyDoorArea) == false)
{
throw new UserFriendlyException($"门岗区域{item.ApplyDoorArea}无效");
}
if (item.IsEnterWorkplace &&
item.ApplyWorkplaceAreas.All(p => areas.Where(x => x.Type == AppointmentAreaEnumType.Workplace)
.Select(x => x.CustomCode)
.Contains(p)) == false)
{
var workplaceAreas = areas.Where(x => x.Type == AppointmentAreaEnumType.Workplace).Select(x => x.CustomCode);
var notExistsAreas = item.ApplyWorkplaceAreas.Where(x => !workplaceAreas.Contains(x));
throw new UserFriendlyException($"车间区域{notExistsAreas.Join(",")}无效");
}
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.IdNo == item.IdNo || x.Code == item.IdNo).SingleAsync();
//外部人员
if (gainfo == null)
{
gainfo = new GainfoEntity
{
No = Guid.NewGuid().ToString(),
Code = await GetNextExternalCodeAsync(),
Gender = GetGender(item.IdNo),
Type = GainfoUserTypeEnumType.External,
IdNo = item.IdNo,
Name = item.Name,
Source = request.Source,
Phone = item.Phone,
Factory = mst.Factory
};
await _dbContext.InsertAsync(gainfo);
}
else
{
(invalids.Contains(gainfo.Type) && item.IsEnterDoorArea).ThrowIfTrue("内部人员无法发起门岗预约");
if (gainfo.Type == GainfoUserTypeEnumType.External)
{
gainfo.Source = request.Source;
gainfo.Phone = item.Phone;
gainfo.Factory = mst.Factory;
await _dbContext.UpdateAsync(gainfo);
}
}
var detail = new VisitorAppointmentDetailEntity
{
UserNo = gainfo.No,
No = request.No,
IdType = item.IdType,
IdNo = item.IdNo,
Name = item.Name,
Phone = item.Phone,
Remark = item.Remark,
DoorStatus = item.IsEnterDoorArea && areas.Where(x => x.Type == AppointmentAreaEnumType.Door)
.Select(x => x.CustomCode)
.Contains(item.ApplyDoorArea)
? VisitorAppointmentDetailStatusEnumType.Wait
: VisitorAppointmentDetailStatusEnumType.Obsolete,
LicensePlate = item.LicensePlate,
IsEnterDoorArea = item.IsEnterDoorArea,
ApplyDoorArea = item.ApplyDoorArea,
DoorStart = item.DoorStart,
DoorEnd = item.DoorEnd,
IsEnterWorkplace = item.IsEnterWorkplace,
WorkplaceStatus = item.IsEnterWorkplace &&
item.ApplyWorkplaceAreas.All(p => areas.Where(x => x.Type == AppointmentAreaEnumType.Workplace)
.Select(x => x.CustomCode)
.Contains(p))
? VisitorAppointmentDetailStatusEnumType.Wait
: VisitorAppointmentDetailStatusEnumType.Obsolete,
ApplyWorkplaceAreas = item.ApplyWorkplaceAreas,
WorkplaceStart = item.WorkplaceStart,
WorkplaceEnd = item.WorkplaceEnd,
ImageUrl = item.ImageUrl
};
await _dbContext.InsertAsync(detail);
}
}
private static GenderEnumType GetGender(string idNo)
{
try
{
if (idNo.Length == 18)
{
return int.Parse(idNo.ToCharArray()[16].ToString()) % 2 == 0
? GenderEnumType.Female
: GenderEnumType.Male;
}
}
catch (Exception)
{
//ignore
}
return GenderEnumType.Unknown;
}
public async Task<string> GetNextExternalCodeAsync()
{
await using var handler = await _redisCache.LockAsync("gainfo:external:code-generate", expiry: TimeSpan.FromSeconds(3), retryInterval: TimeSpan.FromSeconds(1), retryCount: 3);
handler.Acquired.ThrowIfFalse("生成虚拟工号失败");
int code;
var entity = await _dbContext.Queryable<BasicTypeEntity>().Where(x => x.Type == "gainfoExternalMaxNum").SingleAsync();
if (entity == null)
{
code = 1;
await _dbContext.InsertAsync(new BasicTypeEntity
{
Type = "gainfoExternalMaxNum",
Code = "1",
Display = "外部人员序号",
DisplayEn = "外部人员序号",
Remark = string.Empty,
Sequence = 1
});
}
else
{
code = int.Parse(entity.Code) + 1;
entity.Code = code.ToString();
await _dbContext.UpdateAsync(entity);
}
return "EXT" + code.ToString().PadLeft(6, '0');
}
private async Task ReSendTo501Async(VisitorAppointmentReceiveRequest request)
{
var gainfo = await _dbContext.Queryable<GainfoEntity>()
.LeftJoin<DepartmentEntity>((ga, dept) => ga.DepartmentNo == dept.No)
.Where((ga, dept) => ga.Code == request.Code)
.Select((ga, dept) => new
{
ga.No,
ga.Name,
ga.Phone,
DeptName = dept.Name
})
.SingleAsync();
gainfo.ThrowIfNull("501被访人工号不存在");
//501厂区发送访客预约
var httpClient = _httpClientFactory.CreateClient();
var list = request.Items.Where(x => x.IsEnterDoorArea).ToList();
var areas = await _dbContext.Queryable<AppointmentAreaEntity>().Where(x => x.TenantId == request.Factory).ToListAsync();
foreach (var dto in list)
{
var json = new
{
arr = dto.DoorStart!.Value.ToString("yyyy-MM-dd HH:mm:ss"), // [必填] 到达时间
dep = dto.DoorEnd!.Value.ToString("yyyy-MM-dd HH:mm:ss"), // 离开时间
company = request.Source, // 公司
deptdes = gainfo.DeptName, // 被访人部门
askName = request.Code, // 被访人姓名
askPhone = gainfo.Phone, //被访人手机号
gname = dto.Name, // 访客姓名
idNo = dto.IdNo, // 访客身份证号
phone = dto.Phone, // 访客电话
reason = request.Reason, // 访问原因
carNo = dto.LicensePlate, // 车牌号
carDes = "", // 物品描述
remark = dto.Remark, // 备注
//logId = null, // 操作员ID,null或空时后台保存为"face"
//logShift = null, // 操作员班别 null或空时后台保存为"1"
//sta = null, //状态 null或空时后台保存为"R"
newFunc = dto.IsEnterWorkplace ? 1 : 0, // 是否进入车间
yqgw = dto.IsEnterWorkplace
? areas.Where(x => x.Type == AppointmentAreaEnumType.Workplace)
.Where(x => dto.ApplyWorkplaceAreas.Contains(x.CustomCode))
.Select(x => x.Name)
.Distinct().Join(",")
: string.Empty // 门岗名称
}.ToJson();
var response = await httpClient.PostAsync("https://pay.aizhuhotel.com/jschuneng/api/guest/GainfoReserveAdd", new StringContent(json, Encoding.UTF8, "application/json"));
var responseJson = await response.Content.ReadAsStringAsync();
_logger.LogInformation("发送到501访客预约{idNo}--{name},发送:{json} ,返回:{responseJson}", dto.IdNo, dto.Name, json, responseJson);
}
}
}