using FlexJobApi.Core; using FlexJobApi.Core.Models.ElectronSignServer.Common; using FlexJobApi.Core.Models.ElectronSignServer.Contracts; using FlexJobApi.Core.Models.ElectronSignServer.PersonalUserReals; using FlexJobApi.Core.Models.ElectronSignServer.Users; using Furion; using Furion.DatabaseAccessor; using Furion.DataValidation; using Furion.DistributedIDGenerator; using Furion.FriendlyException; using Furion.HttpRemote; using Mapster; using MediatR; using Microsoft.AspNetCore.Components.Forms; using Microsoft.EntityFrameworkCore; using MiniExcelLibs; using NetTopologySuite.Index.HPRtree; using System; using System.Collections.Generic; using System.Linq; using System.Security.Principal; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using static System.Runtime.InteropServices.JavaScript.JSType; namespace FlexJobApi.UserServer.Application { /// /// 灵工命令处理器 /// public class EnterpriseEmployeesCommandHandler( SmsUtils smsUtils, WxmpUtils wxmpUtils, IMediator mediator, IRepository rep, IRepository repUser, IRepository repEnterprise, IRepository repEnterpriseEmployeeContract, IRepository repElectronSignSetting, IRepository repContractTemplate, IRepository repEnterpriseCost, IRepository repTaskInfoUser, IRepository repCodeUrl ) : IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler { private readonly SmsUtils smsUtils = smsUtils; private readonly WxmpUtils wxmpUtils = wxmpUtils; private readonly IMediator mediator = mediator; private readonly IRepository rep = rep; private readonly IRepository repUser = repUser; private readonly IRepository repEnterprise = repEnterprise; private readonly IRepository repEnterpriseEmployeeContract = repEnterpriseEmployeeContract; private readonly IRepository repElectronSignSetting = repElectronSignSetting; private readonly IRepository repContractTemplate = repContractTemplate; private readonly IRepository repEnterpriseCost = repEnterpriseCost; private readonly IRepository repTaskInfoUser = repTaskInfoUser; private readonly IRepository repCodeUrl = repCodeUrl; /// /// 导入灵工信息 /// /// /// /// public async Task Handle(ImportEnterpriseEmployeesCommand request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); var result = new ImportEnterpriseEmployeesCommandResult(); var models = await request.ExcelUrl.ImportExcelFromOSS(); var identities = models.DistinctSelect(it => it.Identity); var enterpriseEmployees = await rep.AsQueryable() .Where(it => it.EnterpriseId == logier.EnterpriseId && identities.Contains(it.Identity)) .ToListAsync(); var userIds = enterpriseEmployees.DistinctSelect(it => it.UserId.HasValue, it => it.UserId!.Value); var users = await repUser.AsQueryable() .Where(it => userIds.Contains(it.Id)) .ToListAsync(); var successList = new List(); foreach (var model in models) { var errors = new List(); if (model.Name.IsNull()) { errors.Add("请填写姓名"); } if (model.ContactPhoneNumber.IsNull()) { errors.Add("请填写手机号"); } else if (!model.ContactPhoneNumber.TryValidate(EnumValidationTypes.ValidPhoneNumber).IsValid) { errors.Add("手机号格式不正确"); } if (model.Identity.IsNull()) { errors.Add("请填写身份证号"); } else if (!model.Identity.TryValidate(EnumValidationTypes.ValiIdentity).IsValid) { errors.Add("身份证号格式不正确"); } else if (successList.Any(it => it.Identity == model.Identity)) { errors.Add("身份证号重复"); } else { model.Gender = model.Identity.GetGender(); model.Birthday = model.Identity.GetBirthday(); model.Age = model.Identity.GetAge(); } if (errors.IsNull()) { var enterpriseEmployee = enterpriseEmployees.FirstOrDefault(it => it.Identity == model.Identity); if (enterpriseEmployee == null) { enterpriseEmployee = new EnterpriseEmployee { EnterpriseId = logier.EnterpriseId!.Value, Name = model.Name, Identity = model.Identity, ContactPhoneNumber = model.ContactPhoneNumber, Gender = model.Gender, Birthday = model.Birthday, Age = model.Age, }; await rep.InsertAsync(enterpriseEmployee); successList.Add(model); } else { var canUpdate = true; if (enterpriseEmployee.UserId.HasValue) { var user = users.FirstOrDefault(it => it.Id == enterpriseEmployee.UserId.Value)!; if (user.IsReal == true) { canUpdate = false; errors.Add("已实名无法修改信息"); } else { user.Name = model.Name; user.ContactPhoneNumber = model.ContactPhoneNumber; user.Identity = model.Identity; user.Gender = model.Gender; user.Birthday = model.Birthday; user.Age = model.Age; await repUser.UpdateAsync(user); } } if (canUpdate) { enterpriseEmployee.Name = model.Name; enterpriseEmployee.ContactPhoneNumber = model.ContactPhoneNumber; enterpriseEmployee.Gender = model.Gender; enterpriseEmployee.Birthday = model.Birthday; enterpriseEmployee.Age = model.Age; await rep.UpdateAsync(enterpriseEmployee); successList.Add(model); } } } else { var error = model.Adapt(); error.ErrorMessage = errors.SplitJoin(","); result.Errors.Add(error); } } result.TotalCount = models.Count; result.FailCount = result.Errors.Count; result.SuccessCount = result.TotalCount - result.FailCount; return result; } /// /// 编辑灵工信息 /// /// /// /// public async Task Handle(EditEnterpriseEmployeeCommand request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); var entity = await request.SaveData( q => q.Where(it => it.EnterpriseId == logier.EnterpriseId), it => it.EnterpriseId == logier.EnterpriseId && it.Id != request.Id && it.Identity == request.Identity, (entity) => { if (request.Id.HasValue && entity.UserId.HasValue) { var user = repUser.AsQueryable().FirstOrDefault(it => it.Id == entity.UserId.Value); if (user!.IsReal == true) { throw Oops.Oh(EnumErrorCodeType.s510, "已实名无法修改信息"); } else { user.Name = request.Name; user.ContactPhoneNumber = request.ContactPhoneNumber; user.Identity = request.Identity; user.Birthday = request.Identity.GetBirthday(); user.Gender = request.Gender; user.Age = request.Age; repUser.Update(user); } } request.Adapt(entity); }, cancellationToken); return entity.Id; } /// /// 邀请灵工签约 /// /// /// /// public async Task Handle(InviteElectronSignCommand request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); await mediator.Send(new CheckContractTemplateCommand { Id = request.ContractTemplateId }, cancellationToken); var entities = await rep.AsQueryable() .Where(it => it.EnterpriseId == logier.EnterpriseId && request.Ids.Contains(it.Id)) .ToListAsync(); foreach (var id in request.Ids) { var entity = entities.FirstOrDefault(it => it.Id == id); if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "灵工"); if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Wait) throw Oops.Oh(EnumErrorCodeType.s400, $"已邀请{entity.Name}"); if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Pass) throw Oops.Oh(EnumErrorCodeType.s400, $"已签约{entity.Name}"); entity.ContractTemplateId = request.ContractTemplateId; entity.UserSignContractStatus = EnumTaskUserSignContractStatus.Wait; entity.UserSignContractTime = null; entity.EnterpriseSignContractStatus = null; entity.EnterpriseSignContractTime = null; entity.ContractCode = $"{DateTime.Now:yyyyMMddHHmmss}{new Random(IDGen.NextID().GetHashCode()).Next(1000, 9999)}"; entity.ContractUrl = null; var contract = new EnterpriseEmployeeContract { EnterpriseEmployeeId = entity.Id, ContractTemplateId = entity.ContractTemplateId, ContractCode = entity.ContractCode, UserSignContractStatus = entity.UserSignContractStatus, }; await repEnterpriseEmployeeContract.InsertAsync(contract); //await mediator.Send(new SaveEnterpriseCostCommand //{ // EnterpriseId = logier.EnterpriseId!.Value, // ContractTemplateId = request.ContractTemplateId, // EnterpriseEmployeeContractId = contract.Id, // Type = EnumEnterpriseCostType.ElectronSign //}); await rep.UpdateAsync(entity); } return entities.Count; } /// /// 发送邀请签约短信 /// /// /// /// public async Task Handle(SendInviteElectronSignSmsCommand request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); var entities = await rep.AsQueryable() .Include(it => it.Enterprise) .Include(it => it.ContractTemplate) .Where(it => it.EnterpriseId == logier.EnterpriseId && request.Ids.Contains(it.Id) && it.UserSignContractStatus == EnumTaskUserSignContractStatus.Wait) .ToListAsync(); foreach (var entity in entities) { await smsUtils.Send(new SendSmsModel { PhoneNumber = entity.ContactPhoneNumber, TemplateCode = EnumSmsTemplateCode.InviteElectronSign, }, new { name = entity.Enterprise.EnterpriseName, code = entity.ContractTemplate.Code }); } return entities.Count; } /// /// 个人用户签约 /// /// /// /// public async Task Handle(PersonalUserElectronSignCommand request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); var entity = await rep.AsQueryable() .Include(it => it.Enterprise) .Include(it => it.ContractTemplate).ThenInclude(it => it.Values) .Where(it => it.UserId == logier.Id && it.Id == request.Id) .FirstOrDefaultAsync(); if (entity == null) throw Oops.Oh(EnumErrorCodeType.s510, "未报名该企业"); if (entity.UserSignContractStatus == null) throw Oops.Oh(EnumErrorCodeType.s510, "企业未发起签约"); if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Pass) throw Oops.Oh(EnumErrorCodeType.s510, "已签约"); if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Refuse) throw Oops.Oh(EnumErrorCodeType.s510, "已拒签"); if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Stop) throw Oops.Oh(EnumErrorCodeType.s510, "已终止"); var contract = await repEnterpriseEmployeeContract.AsQueryable() .OrderByDescending(it => it.CreatedTime) .Where(it => it.EnterpriseEmployeeId == request.Id) .FirstOrDefaultAsync(); if (contract == null) throw Oops.Oh(EnumErrorCodeType.s404, "合同"); var user = await repUser.AsQueryable().AsNoTracking() .Include(it => it.UserAuth) .Where(it => it.Id == logier.Id) .FirstOrDefaultAsync(); if (user == null) throw Oops.Oh(EnumErrorCodeType.s404, "用户"); if (entity.ContractTemplate.Access == EnumElectronSignAccess.BestSign && !user.IsReal) throw Oops.Oh(EnumErrorCodeType.s510, "请先实名"); var result = await new SendContractInput { OutContractId = contract.Id.ToString(), TemplateId = entity.ContractTemplate.ElectronSignContractTemplateId!.Value, Title = entity.ContractTemplate.Name, OutUserId = logier.Id.ToString(), Values = entity.ContractTemplate.Values .Where(it => it.UserType == EnumUserType.Personal) .Select(it => { string? value = null; switch (it.BindProperty) { case "Name": value = user.UserAuth.Name; break; case "PhoneNumber": value = user.ContactPhoneNumber; break; case "Identity": value = user.UserAuth.Identity; break; default: break; } return new SendContractInputValue { Name = it.Name, Value = value }; }) .ToList(), UserCount = 2 }.SendHttpAsync>(EnumResourceHttpProvider.ElectronSignServerCustomer); if (result?.Success != true) { throw Oops.Oh(EnumErrorCodeType.s510, result?.Message ?? "签约失败"); } var model = result.Result.Adapt(); model.SignContractLongUrl = model.SignContractLongUrl .Replace("https://openapi.bestsign.info:443", "https://wx115.bestsign.info") .Replace("https://openapi.bestsign.cn:443", "https://wx115.bestsign.cn"); if (entity.ContractTemplate.Access == EnumElectronSignAccess.AlipaySign) { var codeUrl = new SaveCodeUrlCommand { Scene = EnumCodeUrlScene.ElectronSignUrl, Url = model.SignContractLongUrl, ExpiredTime = DateTime.Now.AddMonths(1) }; var code = await mediator.Send(codeUrl); await smsUtils.Send(new SendSmsModel { PhoneNumber = entity.ContactPhoneNumber, TemplateCode = EnumSmsTemplateCode.ElectronSignUrl, }, new { name = entity.Enterprise.EnterpriseName, code = code }); } return model; } /// /// 企业用户签约 /// /// /// /// public async Task Handle(EnterpriseUserElectronSignCommand request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); var entity = await rep.AsQueryable() .Include(it => it.ContractTemplate).ThenInclude(it => it.Values) .Where(it => it.EnterpriseId == logier.EnterpriseId && it.Id == request.Id) .FirstOrDefaultAsync(); if (entity == null) throw Oops.Oh(EnumErrorCodeType.s510, "灵工不存在"); if (entity.UserSignContractStatus == null) throw Oops.Oh(EnumErrorCodeType.s510, "未邀请签约"); if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Wait) throw Oops.Oh(EnumErrorCodeType.s510, "请先等待灵工签约完成"); if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Refuse) throw Oops.Oh(EnumErrorCodeType.s510, "已拒签"); if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Stop) throw Oops.Oh(EnumErrorCodeType.s510, "已终止"); var contract = await repEnterpriseEmployeeContract.AsQueryable() .OrderByDescending(it => it.CreatedTime) .Where(it => it.EnterpriseEmployeeId == request.Id) .FirstOrDefaultAsync(); if (contract == null) throw Oops.Oh(EnumErrorCodeType.s404, "合同"); var enterprise = await repEnterprise.AsQueryable().AsNoTracking() .Include(it => it.EnterpriseAuth) .Where(it => it.Id == logier.EnterpriseId) .FirstOrDefaultAsync(); if (enterprise == null) throw Oops.Oh(EnumErrorCodeType.s404, "企业"); if (entity.ContractTemplate.Access == EnumElectronSignAccess.BestSign && !enterprise.IsReal) throw Oops.Oh(EnumErrorCodeType.s510, "请先实名"); var result = await new SendContractInput { OutContractId = contract.Id.ToString(), TemplateId = entity.ContractTemplate.ElectronSignContractTemplateId!.Value, Title = entity.ContractTemplate.Name, OutUserId = logier.EnterpriseId.ToString(), Values = entity.ContractTemplate.Values .Where(it => it.UserType == EnumUserType.Enterprise) .Select(it => new SendContractInputValue { Name = it.Name, }) .ToList(), UserCount = 2 }.SendHttpAsync>(EnumResourceHttpProvider.ElectronSignServerCustomer); if (result?.Success != true) { throw Oops.Oh(EnumErrorCodeType.s510, result?.Message ?? "签约失败"); } var model = result.Result.Adapt(); model.SignContractLongUrl = model.SignContractLongUrl .Replace("https://openapi.bestsign.info:443", "https://wx115.bestsign.info") .Replace("https://openapi.bestsign.cn:443", "https://wx115.bestsign.cn"); if (entity.ContractTemplate.Access == EnumElectronSignAccess.AlipaySign) { var codeUrl = new SaveCodeUrlCommand { Scene = EnumCodeUrlScene.ElectronSignUrl, Url = model.SignContractLongUrl, ExpiredTime = DateTime.Now.AddMonths(1) }; var code = await mediator.Send(codeUrl); await smsUtils.Send(new SendSmsModel { PhoneNumber = entity.Enterprise.ContactPhoneNumber, TemplateCode = EnumSmsTemplateCode.ElectronSignUrl, }, new { name = entity.Name, code = code }); } return model; } /// /// 灵工解约 /// /// /// /// public async Task Handle(StopElectronSignCommand request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); var entities = await rep.AsQueryable() .Include(it => it.Contracts) .Where(it => it.EnterpriseId == logier.EnterpriseId && request.Ids.Contains(it.Id)) .ToListAsync(); foreach (var id in request.Ids) { var entity = entities.FirstOrDefault(it => it.Id == id); if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "灵工"); if (entity.UserSignContractStatus != EnumTaskUserSignContractStatus.Pass) throw Oops.Oh(EnumErrorCodeType.s400, $"未签约{entity.Name}"); entity.UserSignContractStatus = EnumTaskUserSignContractStatus.Stop; entity.EnterpriseSignContractStatus = EnumTaskUserSignContractStatus.Stop; await rep.UpdateAsync(entity); var contract = entity.Contracts .OrderByDescending(it => it.CreatedTime) .FirstOrDefault(); if (contract == null) throw Oops.Oh(EnumErrorCodeType.s404, $"与{entity.Name}的合同"); contract.UserSignContractStatus = EnumTaskUserSignContractStatus.Stop; contract.EnterpriseSignContractStatus = EnumTaskUserSignContractStatus.Stop; await repEnterpriseEmployeeContract.UpdateAsync(contract); } var taskUsers = await repTaskInfoUser.AsQueryable() .Where(it => it.HireStatus == EnumTaskUserHireStatus.Pass && request.Ids.Contains(it.EnterpriseEmployeeId)) .ToListAsync(); if (taskUsers.IsNotNull()) { foreach (var taskUser in taskUsers) { taskUser.HireStatus = EnumTaskUserHireStatus.Wait; } await repTaskInfoUser.UpdateAsync(taskUsers); } return entities.Count; } } }