using IRaCIS.Application.Contracts; using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Contracts.DTO; using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Domain.Share; using Microsoft.AspNetCore.Mvc; namespace IRaCIS.Core.Application.Services { [ApiExplorerSettings(GroupName = "Trial")] public class TrialMaintenanceService(IRepository _trialSiteRepository, IRepository _trialSiteUserRepository, IRepository _siteRepository, IRepository _subjectRepository, IRepository _visitTaskRepository, IRepository _trialRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ITrialSiteService { /// Pannel 进去 SiteTab [HttpPost] public async Task> GetSiteCRCList(SiteCrcQueryDTO inQuery) { var siteStatQuery = _trialSiteRepository.Where(t => t.TrialId == inQuery.TrialId, ignoreQueryFilters: true) .WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SiteName), t => t.TrialSiteName.Contains(inQuery.SiteName)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteAliasName), t => t.TrialSiteAliasName.Contains(inQuery.TrialSiteAliasName)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteCode), t => t.TrialSiteCode.Contains(inQuery.TrialSiteCode)) .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.CRCUserList.Any(k => k.UserId == _userInfo.UserRoleId)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.UserKeyInfo), t => t.CRCUserList.Any(k => (k.User.FullName).Contains(inQuery.UserKeyInfo) || k.User.UserName.Contains(inQuery.UserKeyInfo) || k.User.EMail.Contains(inQuery.UserKeyInfo))) .ProjectTo(_mapper.ConfigurationProvider); return await siteStatQuery.ToPagedListAsync(inQuery); } /// [new] setting页面Site列表,和getSiteCRCList对比 没有统计数据,增加了一些site信息 [HttpPost] public async Task> GetSiteCRCSimpleList(SiteCrcQueryDTO inQuery) { var siteStatQuery = _trialSiteRepository.Where(t => t.TrialId == inQuery.TrialId).IgnoreQueryFilters() .WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SiteName), t => t.TrialSiteName.Contains(inQuery.SiteName) || t.TrialSiteAliasName.Contains(inQuery.TrialSiteAliasName)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteAliasName), t => t.TrialSiteAliasName.Contains(inQuery.TrialSiteAliasName)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteCode), t => t.TrialSiteCode.Contains(inQuery.TrialSiteCode)) .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.CRCUserList.Any(k => k.UserId == _userInfo.UserRoleId)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.UserKeyInfo), t => t.CRCUserList.Any(k => (k.User.FullName).Contains(inQuery.UserKeyInfo) || k.User.UserName.Contains(inQuery.UserKeyInfo) || k.User.EMail.Contains(inQuery.UserKeyInfo))) .ProjectTo(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }); var result = await siteStatQuery.ToPagedListAsync(inQuery); return result; } /// 获取某一Site下面的负责的CRC列表 [HttpGet, Route("{trialId:guid}/{siteId:guid}")] public async Task> GetTrialSiteCRCList(Guid trialId, Guid siteId) { var query = _trialSiteUserRepository.Where(t => t.TrialId == trialId && t.TrialSiteId == siteId).IgnoreQueryFilters() .ProjectTo(_mapper.ConfigurationProvider); return await query.ToListAsync(); } /// [new] Setting页面 Site勾选列表( [HttpPost] public async Task> GetTrialSiteScreeningList(TrialSiteQuery inQuery) { // 之前选择了的不能再次出现在列表,做的时候我就不建议这样搞,搞好了 现在又要改回去。。。 瞎折腾。。。。 var siteQueryable = _siteRepository.AsQueryable(true) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SiteName), t => t.SiteName.Contains(inQuery.SiteName) || t.SiteNameCN.Contains(inQuery.SiteName) || t.AliasName.Contains(inQuery.SiteName)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.AliasName), t => t.AliasName.Contains(inQuery.AliasName)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.City), t => t.City.Contains(inQuery.City)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Country), t => t.Country.Contains(inQuery.Country)) .ProjectTo(_mapper.ConfigurationProvider, new { trialId = inQuery.TrialId, isEn_Us = _userInfo.IsEn_Us }); return await siteQueryable.ToPagedListAsync(inQuery); } public async Task> GetTrialSiteSelectList(string? siteName) { var list = _siteRepository .WhereIf(!string.IsNullOrWhiteSpace(siteName), t => t.SiteName.Contains(siteName) || t.SiteNameCN.Contains(siteName) || t.AliasName.Contains(siteName)) .Select(t => new TrialSiteSelect() { SiteId = t.Id, SiteName = _userInfo.IsEn_Us ? t.SiteName : t.SiteNameCN, AliasName = t.AliasName }).ToList(); return list; } /// Setting页面 Site批量添加 [HttpPost] [UnitOfWork] //[Authorize(Policy = IRaCISPolicy.PM_APM)] [TrialGlobalLimit( "AfterStopCannNotOpt" )] public async Task AddTrialSites(List trialSites) { var addArray = _mapper.Map>(trialSites); foreach (var item in addArray) { if (item.IsDeleted == false) { item.EnabledTime = DateTime.Now; } } await _trialSiteRepository.AddRangeAsync(addArray); return ResponseOutput.Result(await _trialSiteRepository.SaveChangesAsync()); } /// /// 项目site 编辑接口 New 可以设置为启用不启用 不启用 不会验证Code 重复 /// /// /// [HttpPut] //[Authorize(Policy = IRaCISPolicy.PM_APM)] public async Task EditTrialSite(EditTrialSiteCommand editTrialSiteCommand) { var dbEntity = await _trialSiteRepository.FirstOrDefaultAsync(t => t.Id == editTrialSiteCommand.Id, true); if (dbEntity == null) return Null404NotFound(dbEntity); var trialId = dbEntity.TrialId; var trialSiteId = dbEntity.Id; if (editTrialSiteCommand.IsDeleted) { if (await _trialSiteUserRepository.AnyAsync(t => t.TrialId == trialId && t.TrialSiteId == trialSiteId)) { //---The site has been associated with CRC, and couldn't be deleted. return ResponseOutput.NotOk(_localizer["TrialSite_CannotDeleteAssociatedCRC"]); } if (await _subjectRepository.AnyAsync(t => t.TrialSiteId == trialSiteId && t.TrialId == trialId)) { //---The subjects has been added to this site, and couldn't be disable. return ResponseOutput.NotOk(_localizer["TrialSite_ParticipantJoined"]); } } else { if (await _trialSiteRepository.AnyAsync(t => t.Id != editTrialSiteCommand.Id && t.TrialSiteCode == editTrialSiteCommand.TrialSiteCode && t.TrialId == editTrialSiteCommand.TrialId)) { //---Code is not allowed to be repeated return ResponseOutput.NotOk(_localizer["TrialSite_CodeDuplicate"]); } if (!string.IsNullOrEmpty(editTrialSiteCommand.TrialSiteCode) && await _trialRepository.AnyAsync(t => t.Id == trialId && t.VitrualSiteCode == editTrialSiteCommand.TrialSiteCode, true)) { return ResponseOutput.NotOk(_localizer["TrialSite_CodeDuplicate2"]); } } _mapper.Map(editTrialSiteCommand, dbEntity); if (editTrialSiteCommand.IsDeleted) { dbEntity.EnabledTime = null; } else if (editTrialSiteCommand.IsDeleted == false && dbEntity.EnabledTime == null) { dbEntity.EnabledTime = DateTime.Now; } await _trialSiteRepository.SaveChangesAsync(); return ResponseOutput.Ok(); } /// 批量添加Site下 CRC的负责人 [HttpPost] [TrialGlobalLimit( "AfterStopCannNotOpt" )] //[Authorize(Policy = IRaCISPolicy.PM_APM)] public async Task AssignSiteCRC(List trialSiteCRCList) { var addArray = _mapper.Map>(trialSiteCRCList); await _trialSiteUserRepository.AddRangeAsync(addArray); await _trialSiteUserRepository.SaveChangesAsync(); return ResponseOutput.Result(true); } /// 删除CRC人员 [HttpDelete, Route("{id:guid}/{trialId:guid}/{isDelete:bool}")] [TrialGlobalLimit( "AfterStopCannNotOpt" )] //[Authorize(Policy = IRaCISPolicy.PM_APM)] public async Task DeleteSiteCRC(Guid id, bool isDelete) { await _trialSiteUserRepository.UpdatePartialFromQueryAsync(t => t.Id == id, u => new TrialSiteUser() { IsDeleted = isDelete, DeletedTime = isDelete ? DateTime.Now : null }, true, true); //删除又启用改授权时间 if (isDelete == false) { await _trialSiteUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, u => new TrialSiteUser() { CreateTime = DateTime.Now }); } ////不跟踪 //await _trialSiteUserRepository.ExecuteUpdateAsync(t => t.Id == id, s=>s.SetProperty(t=>t.IsDeleted,u=>isDelete) // .SetProperty(t=>t.DeletedTime,u=> isDelete ? DateTime.Now : null) // .SetProperty(t=>t.CreateTime,u=>isDelete?u.CreateTime:DateTime.Now)); return ResponseOutput.Ok(); } /// /// 获取项目下的 site 下拉框数据 CRC只看到他负责的 /// /// /// [HttpGet("{trialId:guid}")] public async Task> GetTrialSiteSelect(Guid trialId) { //CRC只看到他负责的 var list = await _trialSiteRepository.Where(t => t.TrialId == trialId) .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.CRCUserList.Any(t => t.UserId == _userInfo.UserRoleId)) .ProjectTo(_mapper.ConfigurationProvider).OrderBy(t => t.TrialSiteCode).ToListAsync(); return list; } public async Task> GetTrialSiteCodeSelect(Guid trialId, bool isIncludeVirtualSite = true) { //CRC只看到他负责的 var list = await _trialSiteRepository.Where(t => t.TrialId == trialId) .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.CRCUserList.Any(t => t.UserId == _userInfo.UserRoleId)) .Select(t => t.TrialSiteCode).ToListAsync(); var virtualList = await _visitTaskRepository.Where(t => t.IsSelfAnalysis == true && t.TrialId == trialId).Select(t => t.BlindTrialSiteCode).Distinct().ToListAsync(); return isIncludeVirtualSite ? list.Concat(virtualList) : list; } /// 删除 项目 下某一site [HttpDelete("{id:guid}/{trialId:guid}")] [TrialGlobalLimit( "AfterStopCannNotOpt" )] [Obsolete] public async Task DeleteTrialSite(Guid id) { var relation = await _trialSiteRepository.FirstOrDefaultAsync(t => t.Id == id); if (relation == null) return Null404NotFound(relation); var trialId = relation.TrialId; var trialSiteId = relation.Id; if (await _trialSiteUserRepository.AnyAsync(t => t.TrialId == trialId && t.TrialSiteId == trialSiteId)) { //---The site has been associated with CRC, and couldn't be deleted. return ResponseOutput.NotOk(_localizer["TrialSite_CannotDeleteAssociatedCRC"]); } if (await _subjectRepository.AnyAsync(t => t.TrialSiteId == trialSiteId && t.TrialId == trialId)) { //---The subjects has been added to this site, and couldn't be deleted. return ResponseOutput.NotOk(_localizer["TrialSite_CannotDeleteAssociatedSubject"]); } await _trialSiteRepository.DeleteAsync(relation); return ResponseOutput.Result(await _trialSiteUserRepository.SaveChangesAsync()); } } }