//-------------------------------------------------------------------- // 此代码由T4模板自动生成 byzhouhang 20210918 // 生成时间 2021-12-23 13:20:59 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 //-------------------------------------------------------------------- using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Domain.Share; using System.Text.RegularExpressions; using IRaCIS.Core.Infrastructure; using IRaCIS.Application.Services; using IRaCIS.Core.Application.Auth; using IRaCIS.Application.Contracts; using Microsoft.AspNetCore.Authorization; using MailKit.Security; using MimeKit; using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Infrastructure.Extention; using Microsoft.VisualBasic; using DocumentFormat.OpenXml.Spreadsheet; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Application.ViewModel; using Medallion.Threading; using Microsoft.Extensions.Options; using NPOI.SS.Formula.Functions; using Newtonsoft.Json; namespace IRaCIS.Core.Application.Contracts { /// /// TrialSiteSurveyService /// [ApiExplorerSettings(GroupName = "Trial")] public class TrialSiteSurveyService : BaseService, ITrialSiteSurveyService { private readonly IRepository _trialSiteSurveyRepository; private readonly IRepository _trialSiteUserSurveyRepository; private readonly IRepository _userRepository; private readonly IRepository _trialSiteRepository; private readonly IRepository _trialUserRepository; private readonly IRepository _trialSiteUserRepository; private readonly IDistributedLockProvider _distributedLockProvider; private readonly ITokenService _tokenService; private readonly IMailVerificationService _mailVerificationService; private readonly SystemEmailSendConfig _systemEmailConfig; public TrialSiteSurveyService(IRepository trialSiteSurveyRepository, IRepository trialUserRepository, IRepository trialSiteUserSurveyRepository, IRepository userRepository, IRepository trialSiteRepository, ITokenService tokenService, IMailVerificationService mailVerificationService, IRepository trialSiteUserRepository, IDistributedLockProvider distributedLockProvider, IOptionsMonitor systemEmailConfig) { _trialSiteSurveyRepository = trialSiteSurveyRepository; _trialSiteUserSurveyRepository = trialSiteUserSurveyRepository; _userRepository = userRepository; _trialUserRepository = trialUserRepository; _trialSiteRepository = trialSiteRepository; _tokenService = tokenService; _mailVerificationService = mailVerificationService; _trialSiteUserRepository = trialSiteUserRepository; _distributedLockProvider = distributedLockProvider; _systemEmailConfig = systemEmailConfig.CurrentValue; } /// /// 发送验证码 /// /// /// [AllowAnonymous] public async Task SendEmialVerifyCode(SendEmialVerifyCodeInDto userInfo) { //检查手机或者邮箱是否有效 if (!Regex.IsMatch(userInfo.Email, @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")) { //---请输入正确的邮箱地址。 throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_InvalidEmail"]); } //邮箱 //验证码 6位 int verificationCode = new Random().Next(100000, 1000000); await _mailVerificationService.SendEmailVerification(userInfo.Email, verificationCode); return ResponseOutput.Ok(); } /// /// 验证邮箱验证码 获取医生信息Id /// /// /// [HttpPost] [AllowAnonymous] public async Task VerifyEmialGetDoctorInfo(VerifyEmialGetDoctorInfoInDto inDto) { var verificationRecord = await _repository.GetQueryable().OrderByDescending(x => x.ExpirationTime).Where(t => (t.EmailOrPhone == inDto.EmailOrPhone) && t.Code == inDto.VerificationCode && t.CodeType == VerifyType.Email).FirstOrDefaultAsync(); VerifyEmialGetDoctorInfoOutDto result = new VerifyEmialGetDoctorInfoOutDto(); //检查数据库是否存在该验证码 if (verificationRecord == null) { //---验证码错误。 throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_WrongVerificationCode"]); } else { //检查验证码是否失效 if (verificationRecord.ExpirationTime < DateTime.Now) { //---验证码已经过期。 throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_ExpiredVerificationCode"]); } else //验证码正确 并且 没有超时 { var dockerInfo = await _repository.Where(t => t.EMail == inDto.EmailOrPhone || t.Phone == inDto.EmailOrPhone).FirstOrDefaultAsync(); if (dockerInfo != null) { result.DoctorId = dockerInfo.Id; result.ReviewStatus = dockerInfo.ReviewStatus; } result.Token = _tokenService.GetToken(IRaCISClaims.Create(new UserBasicInfo())); } } return result; } /// ///site 调研 发送验证码 /// /// /// [AllowAnonymous] public async Task SendVerifyCode(SiteSurveySendVerifyCode userInfo) { //检查手机或者邮箱是否有效 if (!Regex.IsMatch(userInfo.Email, @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")) { //---请输入正确的邮箱地址。 throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_InvalidEmail"]); } //邮箱 //验证码 6位 int verificationCode = new Random().Next(100000, 1000000); var trialInfo = await _repository.FirstOrDefaultAsync(t => t.Id == userInfo.TrialId); await _mailVerificationService.AnolymousSendEmail(trialInfo.ResearchProgramNo, userInfo.Email, verificationCode); return ResponseOutput.Ok(); } /// /// 验证后 如果数据库该项目不存在该邮箱 那么就插入记录 存在 /// /// /// /// /// [HttpPost] [UnitOfWork] [AllowAnonymous] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task VerifySendCode(LoginDto userInfo, [FromServices] ITokenService _tokenService) { #region 20230804 修改调研表逻辑 var verifyRecord = await _repository.FirstOrDefaultAsync(t => (t.EmailOrPhone == userInfo.EmailOrPhone) && t.Code == userInfo.verificationCode && t.CodeType == userInfo.verificationType); //检查数据库是否存在该验证码 if (verifyRecord == null) { //---验证码错误。 return ResponseOutput.NotOk(_localizer["TrialSiteSurvey_WrongVerificationCode"]); } else if (verifyRecord.ExpirationTime < DateTime.Now) { return ResponseOutput.NotOk(_localizer["TrialSiteSurvey_WrongVerificationCode"]); } else { //验证码正确 不处理 } TrialSiteSurvey? currentEntity = null; var userList = await _trialSiteUserRepository.Where(t => t.TrialId == userInfo.TrialId && t.TrialSiteId == userInfo.TrialSiteId, false, true).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); //普通登录 if (userInfo.IsUpdate == false) { var dbEntityList = await _trialSiteSurveyRepository.Where(t => t.TrialId == userInfo.TrialId && t.TrialSiteId == userInfo.TrialSiteId).ToListAsync(); //没有记录 new一份 if (dbEntityList.Count == 0) { var addSurvey = _mapper.Map(userInfo); //从项目site 中找到已存在的 加到历史人员中 addSurvey.TrialSiteUserSurveyList = userList; currentEntity = await _repository.AddAsync(addSurvey); } else { //找到当前最新的调研表 var currentLatest = dbEntityList.OrderByDescending(t => t.CreateTime).FirstOrDefault(); if (currentLatest!.Email != userInfo.EmailOrPhone) { //---该中心下已经有其他用户已填写的调研表,您不被允许继续填写 return ResponseOutput.NotOk(_localizer["TrialSiteSurvey_AlreadyFilledByOtherUsers"]); } currentEntity = currentLatest; if (currentEntity.State != TrialSiteSurveyEnum.PMCreatedAndLock) { await UnlockSyncSiteUserAsync(userInfo.TrialId, userInfo.TrialSiteId, currentEntity.Id, userList); } } } //更新调研表 else { //找到最新的调研表 var currentLatest = await _trialSiteSurveyRepository.Where(t => t.TrialId == userInfo.TrialId && t.TrialSiteId == userInfo.TrialSiteId, true) .Include(u => u.TrialSiteEquipmentSurveyList).Include(u => u.TrialSiteUserSurveyList).OrderByDescending(t => t.CreateTime).FirstOrDefaultAsync(); if (currentLatest == null) { return ResponseOutput.NotOk(_localizer["TrialSite_NoSurveyToUpdate"]); } if (currentLatest.Email != userInfo.ReplaceUserEmailOrPhone) { //---该中心不存在该交接人的中心调研记录表,不允许选择更新。 return ResponseOutput.NotOk(_localizer["TrialSiteSurvey_NoRecordToUpdate"]); } //未锁定的状态 就改为废除 if (currentLatest.State != TrialSiteSurveyEnum.PMCreatedAndLock) { currentLatest.IsDeleted = true; } //锁定的 需要改状态么? else { } var copy = currentLatest.Clone(); copy.State = TrialSiteSurveyEnum.ToSubmit; copy.IsDeleted = false; copy.Phone = string.Empty; copy.UserName = string.Empty; copy.Email = userInfo.EmailOrPhone; copy.Id = Guid.Empty; copy.CreateTime = DateAndTime.Now; if (userInfo.ReplaceUserEmailOrPhone != userInfo.EmailOrPhone) { copy.UserName = String.Empty; copy.Phone = String.Empty; } copy.TrialSiteEquipmentSurveyList = currentLatest.TrialSiteEquipmentSurveyList.Clone(); copy.TrialSiteEquipmentSurveyList.ForEach(t => { t.Id = Guid.Empty; t.CreateTime = DateTime.Now; }); //锁定了的话,就不拷贝 if (currentLatest.State != TrialSiteSurveyEnum.PMCreatedAndLock) { copy.TrialSiteUserSurveyList = currentLatest.TrialSiteUserSurveyList.Clone().Where(t => t.IsHistoryUser == false).ToList(); copy.TrialSiteUserSurveyList.ForEach(t => { t.Id = Guid.Empty; t.IsGenerateSuccess = false; t.CreateTime = DateTime.Now; }); } //从项目site 中找到已存在的 加到历史人员中 copy.TrialSiteUserSurveyList.AddRange(userList); currentEntity = await _trialSiteSurveyRepository.AddAsync(copy); } //删除验证码历史记录 await _repository.BatchDeleteAsync(t => t.EmailOrPhone == userInfo.EmailOrPhone && t.Code == userInfo.verificationCode && t.CodeType == userInfo.verificationType); await _trialSiteSurveyRepository.SaveChangesAsync(); return ResponseOutput.Ok(new { TrialSiteSurveyId = currentEntity!.Id, Token = _tokenService.GetToken(IRaCISClaims.Create(new UserBasicInfo() { Id = Guid.NewGuid(), IsReviewer = false, IsAdmin = false, RealName = "SiteSurvey", UserName = "SiteSurvey", Sex = 0, //UserType = "ShareType", UserTypeEnum = UserTypeEnum.Undefined, Code = "SiteSurvey", })) }); #endregion } private async Task UnlockSyncSiteUserAsync(Guid trialId, Guid siteId, Guid trialSiteSurveyId, List userList) { var existList = await _trialSiteUserSurveyRepository.Where(t => t.IsHistoryUser && t.TrialSiteSurvey.TrialId == trialId && t.TrialSiteSurvey.TrialSiteId == siteId, true).ToListAsync(); foreach (var item in userList) { var find = existList.FirstOrDefault(t => t.SystemUserId == item.SystemUserId); //不存在就加入 if (find == null) { item.TrialSiteSurveyId = trialSiteSurveyId; await _trialSiteUserSurveyRepository.AddAsync(item); } else { find.IsHistoryUserOriginDeleted = item.IsHistoryUserOriginDeleted; } } await _trialSiteUserSurveyRepository.SaveChangesAsync(); } /// /// 直接查询相关所有数据 /// /// [HttpGet("{trialId:guid}/{trialSiteSurveyId:guid}")] public async Task GetSiteSurveyInfo(Guid trialSiteSurveyId, Guid trialId) { //有可能填表人提交了,但是此时PM手动对人员信息进行了更改,此时需要将数据同步下(选择在这里同步是因为 不想改动 中心人员哪里的两个接口的逻辑) var find = await _trialSiteSurveyRepository.FirstOrDefaultAsync(t => t.Id == trialSiteSurveyId, true); if (find.State != TrialSiteSurveyEnum.PMCreatedAndLock && find.IsDeleted != true) { var userList = await _trialSiteUserRepository.Where(t => t.TrialId == find.TrialId && t.TrialSiteId == find.TrialSiteId, false, true).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); await UnlockSyncSiteUserAsync(find.TrialId, find.TrialSiteId, find.Id, userList); } var result = await _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId && t.TrialId == trialId).IgnoreQueryFilters() .ProjectTo(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync().IfNullThrowException(); var siteSurveryConfig = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId).Select(t => t.Trial.SiteSurveyConfigJsonStr).FirstOrDefault()??string.Empty; result.SiteSurveyFiledConfig = JsonConvert.DeserializeObject(siteSurveryConfig) ?? new SiteSurveyFiledConfig(); return result; } /// /// 实际这里只会是更新 添加在login的时候做了 /// /// /// [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task AddOrUpdateTrialSiteSurvey(TrialSiteSurveyAddOrEdit addOrEditTrialSiteSurvey) { if (addOrEditTrialSiteSurvey.Id != null) { if (await _trialSiteSurveyRepository.AnyAsync(t => t.Id == addOrEditTrialSiteSurvey.Id && t.State == TrialSiteSurveyEnum.PMCreatedAndLock)) { //---中心调研已锁定,不允许操作。 return ResponseOutput.NotOk(_localizer["TrialSiteSurvey_Locked"]); } } if (addOrEditTrialSiteSurvey.Id == null) { var entity = _mapper.Map(addOrEditTrialSiteSurvey); await _trialSiteSurveyRepository.AddAsync(entity, true); return ResponseOutput.Ok(entity.Id.ToString()); } else { var entity = await _trialSiteSurveyRepository.Where(t => t.Id == addOrEditTrialSiteSurvey.Id, true).Include(x => x.ReviewerUser).Include(x => x.PreliminaryUser).FirstOrDefaultAsync(); _mapper.Map(addOrEditTrialSiteSurvey, entity); await _trialSiteSurveyRepository.SaveChangesAsync(); } return ResponseOutput.Ok(true); } /// /// 删除调研表 /// /// /// [HttpDelete("{trialSiteSurveyId:guid}/{trialId:guid}")] public async Task DeleteTrialSiteSurvey(Guid trialSiteSurveyId) { if (await _trialSiteSurveyRepository.AnyAsync(t => t.Id == trialSiteSurveyId && t.State == TrialSiteSurveyEnum.PMCreatedAndLock)) { //---中心调研已锁定,不允许操作。 return ResponseOutput.NotOk(_localizer["TrialSiteSurvey_Locked"]); } var success = await _trialSiteSurveyRepository.BatchDeleteNoTrackingAsync(t => t.Id == trialSiteSurveyId); return ResponseOutput.Result(success); } /// /// 获取 项目 site的调研记录 New /// /// [HttpPost] public async Task> GetTrialSiteSurveyList(TrialSiteSurveyQueryDTO surveyQueryDTO) { var trialSiteSurveyQueryable = _trialSiteSurveyRepository.Where(t => t.TrialId == surveyQueryDTO.TrialId).IgnoreQueryFilters() .WhereIf(surveyQueryDTO.TrialSiteId != null, t => t.TrialSiteId == surveyQueryDTO.TrialSiteId) .WhereIf(surveyQueryDTO.IsDeleted != null, t => t.IsDeleted == surveyQueryDTO.IsDeleted) .WhereIf(!string.IsNullOrWhiteSpace(surveyQueryDTO.UserKeyInfo), t => t.UserName.Contains(surveyQueryDTO.UserKeyInfo) || t.Phone.Contains(surveyQueryDTO.UserKeyInfo) || t.Email.Contains(surveyQueryDTO.UserKeyInfo)) .WhereIf(surveyQueryDTO.State != null, t => t.State == surveyQueryDTO.State) .WhereIf(surveyQueryDTO.UpdateTimeBegin != null, t => t.UpdateTime >= surveyQueryDTO.UpdateTimeBegin) .WhereIf(surveyQueryDTO.UpdateTimeEnd != null, t => t.UpdateTime <= surveyQueryDTO.UpdateTimeEnd) .ProjectTo(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }) .WhereIf(!string.IsNullOrWhiteSpace(surveyQueryDTO.PreliminaryUserName), t => t.PreliminaryUser.RealName.Contains(surveyQueryDTO.PreliminaryUserName)) .WhereIf(!string.IsNullOrWhiteSpace(surveyQueryDTO.ReviewerUserName), t => t.ReviewerUser.RealName.Contains(surveyQueryDTO.ReviewerUserName)) ; return await trialSiteSurveyQueryable.ToPagedListAsync(surveyQueryDTO.PageIndex, surveyQueryDTO.PageSize, surveyQueryDTO.SortField, surveyQueryDTO.Asc); } [HttpPost] public async Task> GetTrialSiteSurveySelectList(TrialSiteSurveySelectquery inQuery) { var trialSiteSurveyQueryable = _trialSiteSurveyRepository .Where(t => t.Id != inQuery.TrialSiteSurveyId) .Where(t => t.TrialId == inQuery.TrialId && t.TrialSiteId == inQuery.TrialSiteId).IgnoreQueryFilters() .ProjectTo(_mapper.ConfigurationProvider); return await trialSiteSurveyQueryable.ToListAsync(); } /// /// 项目Site调研用户列表 所有site的调研用户 最新的调研表的记录的用户 new /// /// public async Task> TrialSiteSurveyUserList(TrialSiteUserSurveyAllQuery queryParam) { var groupSelectIdQuery = _trialSiteSurveyRepository.Where(t => t.TrialId == queryParam.TrialId) .WhereIf(queryParam.TrialSiteId != null, t => t.TrialSiteId == queryParam.TrialSiteId) .WhereIf(!string.IsNullOrEmpty(queryParam.FormWriterKeyInfo), t => (t.UserName).Contains(queryParam.FormWriterKeyInfo) || t.Email.Contains(queryParam.FormWriterKeyInfo) || t.Phone.Contains(queryParam.FormWriterKeyInfo)) .GroupBy(t => t.TrialSiteId) .Select(g => g.OrderByDescending(u => u.CreateTime).Select(t => t.Id).First()); var query = _trialSiteUserSurveyRepository .Where(t => groupSelectIdQuery.Contains(t.TrialSiteSurveyId)) .WhereIf(queryParam.TrialRoleCode != null, t => t.TrialRoleCode == queryParam.TrialRoleCode) .WhereIf(queryParam.UserTypeId != null, t => t.UserTypeId == queryParam.UserTypeId) .WhereIf(queryParam.IsGenerateAccount != null, t => t.IsGenerateAccount == queryParam.IsGenerateAccount) .WhereIf(queryParam.State != null && queryParam.State != TrialSiteUserStateEnum.OverTime, t => t.InviteState == queryParam.State) .WhereIf(!string.IsNullOrEmpty(queryParam.UserName), t => (t.LastName + " / " + t.FirstName).Contains(queryParam.UserName)) .WhereIf(!string.IsNullOrEmpty(queryParam.OrganizationName), t => t.OrganizationName.Contains(queryParam.OrganizationName)) .ProjectTo(_mapper.ConfigurationProvider); return await query.ToPagedListAsync(queryParam.PageIndex, queryParam.PageSize, queryParam.SortField, queryParam.Asc); //return await query.ToPagedListAsync(queryParam.PageIndex, queryParam.PageSize, queryParam.SortField, queryParam.Asc); } /// /// 初始登陆界面 项目基本信息+下拉框数据 /// /// /// [AllowAnonymous] [HttpGet("{trialId:guid}")] public async Task GetTrialSurveyInitInfo(Guid trialId) { var info = await _repository.Where(t => t.Id == trialId).IgnoreQueryFilters().ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException(); return info; } /// /// 驳回 New /// /// [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task SubmissionRejection(TrialSiteSubmitBackCommand trialSiteSubmitBackCommand, [FromServices] IMailVerificationService _IMailVerificationService) { var trialSiteSurveyId = trialSiteSubmitBackCommand.TrialSiteSurveyId; var survey = await _trialSiteSurveyRepository.FirstOrDefaultAsync(t => t.Id == trialSiteSurveyId); survey.LatestBackReason = trialSiteSubmitBackCommand.LatestBackReason; User? user = null; var messageToSend = new MimeMessage(); if (await _repository.AnyAsync(t => t.State == TrialSiteSurveyEnum.PMCreatedAndLock && t.Id == trialSiteSurveyId)) { //---中心调研已锁定,不允许操作。 return ResponseOutput.NotOk(_localizer["TrialSiteSurvey_Locked"]); } if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM) { //SPM 给填表人发 messageToSend.To.Add(new MailboxAddress(String.Empty, survey.Email)); survey.State = TrialSiteSurveyEnum.ToSubmit; } else if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.APM) { var hasSPMOrCPM = await _trialSiteSurveyRepository.AnyAsync(t => t.TrialId == trialSiteSubmitBackCommand.TrialId && t.Trial.TrialUserList.Any(u => u.User.UserTypeEnum == UserTypeEnum.SPM || u.User.UserTypeEnum == UserTypeEnum.CPM)); if (hasSPMOrCPM) { //PM 给SPM发 (初审人) user = await _userRepository.FirstOrDefaultAsync(t => t.Id == survey.PreliminaryUserId); messageToSend.To.Add(new MailboxAddress(String.Empty, survey.PreliminaryUserId == null ? survey.Email : user.EMail)); survey.State = TrialSiteSurveyEnum.CRCSubmitted; survey.ReviewerUserId = null; survey.ReviewerTime = null; } else { //没有SPM 给填表人发 messageToSend.To.Add(new MailboxAddress(String.Empty, survey.Email)); survey.State = TrialSiteSurveyEnum.ToSubmit; survey.PreliminaryUserId = null; survey.ReviewerUserId = null; survey.PreliminaryTime = null; survey.ReviewerTime = null; } } var builder = new BodyBuilder(); var trialInfo = await _repository.FirstOrDefaultAsync(t => t.Id == trialSiteSubmitBackCommand.TrialId); var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialSiteSubmitBackCommand.TrialId && t.Id == survey.TrialSiteId, true); //主题 // $"[来自展影IRC] [{trialInfo.ResearchProgramNo}] 关于中心调研审批的提醒"; messageToSend.Subject = _localizer["TrialSiteSurvey_IRCNotification", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN, trialInfo.ResearchProgramNo]; var pathToFile = _hostEnvironment.WebRootPath + Path.DirectorySeparatorChar.ToString() + "EmailTemplate" + Path.DirectorySeparatorChar.ToString() + (_userInfo.IsEn_Us ? "TrialSiteSurveyReject_US.html" : "TrialSiteSurveyReject.html"); using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile)) { var templateInfo = SourceReader.ReadToEnd(); templateInfo = templateInfo.Replace("{company}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyName : _systemEmailConfig.CompanyNameCN) .Replace("{company abbreviation}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN); builder.HtmlBody = string.Format(templateInfo, (user == null ? survey.UserName : user.LastName + "/ " + user.FirstName), trialInfo.TrialCode, trialInfo.ResearchProgramNo, trialInfo.ExperimentName, siteInfo.TrialSiteCode, siteInfo.TrialSiteAliasName, survey.LatestBackReason, trialSiteSubmitBackCommand.RouteUrl, (survey.State == TrialSiteSurveyEnum.ToSubmit ? "inline - block" : "none") ); } messageToSend.Body = builder.ToMessageBody(); await _IMailVerificationService.SiteSurveyRejectEmail(messageToSend); await _trialSiteSurveyRepository.SaveChangesAsync(); return ResponseOutput.Ok(); } [HttpPut("{trialId:guid}/{trialSiteSurveyId:guid}")] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task AbandonSiteSurvey(Guid trialSiteSurveyId) { var survey = (await _trialSiteSurveyRepository.FirstOrDefaultAsync(t => t.Id == trialSiteSurveyId, true)).IfNullThrowException(); if (survey.State != TrialSiteSurveyEnum.ToSubmit) { //---只允许废除未提交的记录。 return ResponseOutput.NotOk(_localizer["TrialSiteSurvey_CancelUnsubmittedRecord"]); } survey.IsDeleted = true; await _repository.SaveChangesAsync(); return ResponseOutput.Ok(); } /// /// 提交 后台自动识别是谁提交 /// /// /// [HttpPost] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] [UnitOfWork] public async Task TrialSurveySubmit(TrialSiteSurvyeSubmitDTO siteSurvyeSubmit) { var trialId = siteSurvyeSubmit.TrialId; var trialSiteSurveyId = siteSurvyeSubmit.TrialSiteSurveyId; var trialSiteSurvey = (await _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId, false, true).FirstOrDefaultAsync()).IfNullThrowException(); if (trialSiteSurvey.IsDeleted == true || trialSiteSurvey.State == TrialSiteSurveyEnum.PMCreatedAndLock) { throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_Invalid"]); } var siteUserList = await _trialSiteUserSurveyRepository.Where(t => t.TrialSiteSurveyId == trialSiteSurveyId) .Where(t => !(t.IsHistoryUser && t.IsHistoryUserDeleted == true)) .Select(t => new { t.TrialSiteSurveyId, t.IsGenerateAccount, t.IsGenerateSuccess, t.UserTypeId, UserTypeEnum = (UserTypeEnum?)t.UserTypeRole.UserTypeEnum, t.TrialRoleCode, t.Email, }).ToListAsync(); //var currentUserList = siteUserList.Where(t => t.TrialSiteSurveyId == trialSiteSurveyId).ToList(); if (!siteUserList.Any(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || t.UserTypeEnum == UserTypeEnum.CRA)) { throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_MissingAccount"]); } if (siteUserList.Where(t => t.IsGenerateAccount && t.UserTypeId != null).GroupBy(t => new { t.UserTypeId, t.Email }) .Any(g => g.Count() > 1)) { throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_DuplicateEmail"]); } if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.Undefined) { var hasSPMOrCPM = await _trialSiteSurveyRepository.AnyAsync(t => t.TrialId == trialId && t.Trial.TrialUserList.Any(u => u.User.UserTypeEnum == UserTypeEnum.SPM || u.User.UserTypeEnum == UserTypeEnum.CPM)); if (hasSPMOrCPM) { await _trialSiteSurveyRepository.UpdatePartialFromQueryAsync(t => t.Id == trialSiteSurveyId && t.State == TrialSiteSurveyEnum.ToSubmit, u => new TrialSiteSurvey() { State = TrialSiteSurveyEnum.CRCSubmitted }); } else { await _trialSiteSurveyRepository.UpdatePartialFromQueryAsync(t => t.Id == trialSiteSurveyId && t.State == TrialSiteSurveyEnum.ToSubmit, u => new TrialSiteSurvey() { State = TrialSiteSurveyEnum.SPMApproved }); } } else if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM) { await _trialSiteSurveyRepository.UpdatePartialFromQueryAsync(t => t.Id == trialSiteSurveyId && t.State == TrialSiteSurveyEnum.CRCSubmitted, u => new TrialSiteSurvey() { State = TrialSiteSurveyEnum.SPMApproved, PreliminaryUserId = _userInfo.Id, PreliminaryTime = DateTime.Now }); } else if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.APM) { var allUserList = _trialSiteUserSurveyRepository.Where(t => t.TrialSiteSurveyId == trialSiteSurveyId).ProjectTo(_mapper.ConfigurationProvider).ToList(); //已生成的不管 管的只需要是 生成失败的并且需要生成账号的 var needGenerateList = allUserList.Where(t => t.IsHistoryUser == false && t.IsGenerateAccount && t.IsJoin != true).ToList(); await GenerateAccountAsync(needGenerateList, trialId); //新加入的 或者历史人员退出改为加入的 var needSendEmailList = allUserList.Where(t => (t.IsHistoryUser == false && t.IsGenerateAccount && t.IsJoin != true) || (t.IsHistoryUser == true && t.IsHistoryUserOriginDeleted == true && t.IsHistoryUserDeleted == false)).ToList(); await SendSiteSurveyUserJoinEmail(new TrialSiteUserSurveyJoinCommand() { TrialId = trialId, TrialSiteSurveyId = trialSiteSurveyId, RouteUrl = siteSurvyeSubmit.RouteUrl, BaseUrl = siteSurvyeSubmit.BaseUrl, UserList = needSendEmailList }); var needQuitUserList = allUserList.Where(t => t.IsHistoryUser && t.IsHistoryUserOriginDeleted == false && t.IsHistoryUserDeleted == true).ToList(); await DealSiteUserQuitSiteAsync(trialId, trialSiteSurvey.TrialSiteId, needQuitUserList); //将历史锁定的调研表废弃 await _trialSiteSurveyRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialId && t.TrialSiteId == trialSiteSurvey.TrialSiteId && t.State == TrialSiteSurveyEnum.PMCreatedAndLock && t.Id != trialSiteSurveyId, z => new TrialSiteSurvey() { IsDeleted = true }); } await _trialSiteSurveyRepository.SaveChangesAsync(); return ResponseOutput.Ok(); } private async Task GenerateAccountAsync(List needGenerateList, Guid trialId) { var trialType = _repository.Where(t => t.Id == trialId).Select(t => t.TrialType).FirstOrDefault(); foreach (var item in needGenerateList) { //找下系统中是否存在该用户类型的 并且邮箱 或者手机的账户 var sysUserInfo = await _userRepository.Where(t => t.UserTypeId == item.UserTypeId && t.EMail == item.Email).Include(t => t.UserTypeRole).FirstOrDefaultAsync(); if (sysUserInfo == null) { var @lock = _distributedLockProvider.CreateLock($"UserCode"); using (await @lock.AcquireAsync()) { var saveItem = _mapper.Map(item); if (trialType == TrialType.NoneOfficial) { saveItem.IsTestUser = true; } // 中心调研生成账号 都是外部的 saveItem.IsZhiZhun = false; saveItem.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1; saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User)); saveItem.UserName = saveItem.UserCode; saveItem.UserTypeEnum = _repository.Where(t => t.Id == saveItem.UserTypeId).Select(t => t.UserTypeEnum).First(); var newUser = _userRepository.AddAsync(saveItem).Result; _ = _userRepository.SaveChangesAsync().Result; sysUserInfo = newUser; } await _trialSiteUserSurveyRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new TrialSiteUserSurvey() { IsGenerateSuccess = true, SystemUserId = sysUserInfo.Id }); } //发送邮件的时候需要用到该字段 item.SystemUserId = sysUserInfo.Id; } await _trialSiteUserSurveyRepository.SaveChangesAsync(); } private async Task SendSiteSurveyUserJoinEmail(TrialSiteUserSurveyJoinCommand joinCommand) { var trialSiteSurvey = await _trialSiteSurveyRepository.FirstAsync(t => t.Id == joinCommand.TrialSiteSurveyId); foreach (var userInfo in joinCommand.UserList) { if (userInfo.SystemUserId == null) { //---生成账户Id 未取到值,请排查 throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_FailedToGenerateAccountId"]); } var trialId = joinCommand.TrialId; var userId = (Guid)userInfo.SystemUserId; var trialSiteId = trialSiteSurvey.TrialSiteId; //判断TrialUser中是否存在 不存在就插入 var findTrialUser = await _trialUserRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.UserId == userId, true); if (findTrialUser == null) { await _repository.AddAsync(new TrialUser() { TrialId = trialId, UserId = userId, JoinTime = DateTime.Now }); await _mailVerificationService.SiteSurveyUserJoinEmail(trialId, userId, joinCommand.BaseUrl, joinCommand.RouteUrl); } else if (findTrialUser.IsDeleted == true) { await _trialUserRepository.UpdatePartialFromQueryAsync(t => t.TrialId == trialId && t.UserId == userId, c => new TrialUser() { IsDeleted = false, DeletedTime = null, JoinTime = DateTime.Now, }); await _mailVerificationService.SiteSurveyUserJoinEmail(trialId, userId, joinCommand.BaseUrl, joinCommand.RouteUrl); } var findTrialSiteUser = await _trialSiteUserRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.UserId == userId && t.TrialSiteId == trialSiteId, true); if (findTrialSiteUser == null) { await _repository.AddAsync(new TrialSiteUser() { TrialId = trialId, TrialSiteId = trialSiteId, UserId = userId }); } else { findTrialSiteUser.IsDeleted = false; findTrialSiteUser.DeletedTime = null; } await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == userId, u => new User() { Status = UserStateEnum.Enable }); await _trialSiteUserSurveyRepository.UpdatePartialFromQueryAsync(t => t.Id == userInfo.Id, u => new TrialSiteUserSurvey() { IsJoin = true }); } await _trialSiteSurveyRepository.UpdatePartialFromQueryAsync(t => t.Id == trialSiteSurvey.Id && t.State == TrialSiteSurveyEnum.SPMApproved, u => new TrialSiteSurvey() { State = TrialSiteSurveyEnum.PMCreatedAndLock, ReviewerUserId = _userInfo.Id, ReviewerTime = DateTime.Now }); await _userRepository.SaveChangesAsync(); return ResponseOutput.Ok(); } private async Task DealSiteUserQuitSiteAsync(Guid trialId, Guid siteId, List list) { var userIdList = list.Select(t => t.SystemUserId).ToList(); await _trialSiteUserRepository.UpdatePartialFromQueryAsync(t => t.TrialId == trialId && t.TrialSiteId == siteId && userIdList.Contains(t.UserId), c => new TrialSiteUser() { IsDeleted = true, DeletedTime = DateTime.Now, }); await _repository.SaveChangesAsync(); } public async Task ImportGenerateAccountAndJoinTrialAsync(Guid trialId, string baseUrl, string routeUrl, List list) { var trialType = _repository.Where(t => t.Id == trialId).Select(t => t.TrialType).FirstOrDefault(); //判断是否有系统账号 foreach (var item in list) { //找下系统中是否存在该用户类型的 并且邮箱 或者手机的账户 var sysUserInfo = await _userRepository.Where(t => t.UserTypeId == item.UserTypeId && t.EMail == item.Email).Include(t => t.UserTypeRole).FirstOrDefaultAsync(); if (sysUserInfo == null) { var @lock = _distributedLockProvider.CreateLock($"UserCode"); using (await @lock.AcquireAsync()) { var saveItem = _mapper.Map(item); if (trialType == TrialType.NoneOfficial) { saveItem.IsTestUser = true; } // 中心调研生成账号 都是外部的 saveItem.IsZhiZhun = false; saveItem.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1; saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User)); saveItem.UserName = saveItem.UserCode; var newUser = _userRepository.AddAsync(saveItem).Result; _ = _userRepository.SaveChangesAsync().Result; sysUserInfo = newUser; } item.IsGeneratedAccount = true; } var userId = sysUserInfo.Id; var trialSiteId = item.TrialSiteId; //判断是否加入到项目 var findTrialUser = await _trialUserRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.UserId == userId, true); if (findTrialUser == null) { await _repository.AddAsync(new TrialUser() { TrialId = trialId, UserId = userId, JoinTime = DateTime.Now }); await _mailVerificationService.SiteSurveyUserJoinEmail(trialId, userId, baseUrl, routeUrl); } else if (findTrialUser.IsDeleted == true) { await _trialUserRepository.UpdatePartialFromQueryAsync(t => t.TrialId == trialId && t.UserId == userId, c => new TrialUser() { IsDeleted = false, DeletedTime = null, JoinTime = DateTime.Now, }); await _mailVerificationService.SiteSurveyUserJoinEmail(trialId, userId, baseUrl, routeUrl); } var findTrialSiteUser = await _trialSiteUserRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.UserId == userId && t.TrialSiteId == trialSiteId, true); if (findTrialSiteUser == null) { await _repository.AddAsync(new TrialSiteUser() { TrialId = trialId, TrialSiteId = trialSiteId, UserId = userId }); } else { findTrialSiteUser.IsDeleted = false; findTrialSiteUser.DeletedTime = null; } await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == userId, u => new User() { Status = UserStateEnum.Enable }); await _trialSiteUserRepository.SaveChangesAsync(); } } } }