using IRaCIS.Application.Interfaces; using IRaCIS.Application.Contracts; using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infrastructure; using Microsoft.AspNetCore.Mvc; using System.Linq.Expressions; namespace IRaCIS.Application.Services { [ApiExplorerSettings(GroupName = "Reviewer")] public class DoctorService : BaseService, IDoctorService { private readonly IRepository _doctorRepository; private readonly IRepository _messageRepository; private readonly IRepository _enrollRepository; private readonly IRepository _doctorDictionaryRepository; private readonly IRepository _attachmentRepository; private readonly IRepository _userDoctorRepository; private readonly IRepository _trialRepository; private readonly IRepository _trialExtRepository; private readonly IRepository _vacationRepository; public DoctorService(IRepository doctorInfoRepository, IRepository dictionaryRepository, IRepository sysMessageRepository, IRepository intoGroupRepository, IRepository doctorDictionaryRepository, IRepository attachmentRepository, IRepository userDoctorRepository, IRepository trialRepository, IRepository trialExtRepository, IRepository vacationRepository) { _doctorRepository = doctorInfoRepository; _messageRepository = sysMessageRepository; _enrollRepository = intoGroupRepository; _doctorDictionaryRepository = doctorDictionaryRepository; _attachmentRepository = attachmentRepository; _userDoctorRepository = userDoctorRepository; _trialRepository = trialRepository; _trialExtRepository = trialExtRepository; _vacationRepository = vacationRepository; } #region 医生基本信息--查询、新增、更新 /// /// 添加/更新 医生基本信息 BasicInfo /// [HttpPost] public async Task> AddOrUpdateDoctorBasicInfo(DoctorBasicInfoCommand basicInfoModel) { Expression> verifyExp = t => t.Phone == basicInfoModel.Phone || t.EMail == basicInfoModel.EMail; var verifyPair = new KeyValuePair>, string>(verifyExp, "current phone or email number already existed"); if (basicInfoModel.Id == Guid.Empty || basicInfoModel.Id == null) { var doctor = _mapper.Map(basicInfoModel); //验证用户手机号 if (await _doctorRepository.AnyAsync(t => t.Phone == doctor.Phone)) { return ResponseOutput.NotOk("The current phone number already existed!", new DoctorBasicInfoCommand()); } if (await _doctorRepository.AnyAsync(t => t.EMail == doctor.EMail)) { return ResponseOutput.NotOk("The current email already existed!", new DoctorBasicInfoCommand()); } doctor.Code = (await _doctorRepository.MaxAsync(t => t.Code)) + 1; doctor.ReviewerCode = AppSettings.CodePrefix + doctor.Code.ToString("D4"); doctor.Password = MD5Helper.Md5(doctor.Phone); //插入中间表 basicInfoModel.TitleIds.ForEach(titleId => doctor.DoctorDicRelationList.Add(new DoctorDictionary() { DoctorId = doctor.Id, KeyName = StaticData.Title, DictionaryId = titleId })); await _doctorRepository.AddAsync(doctor); //_doctorRepository.Add(doctor); await _repository.AddAsync(new UserDoctor() { DoctorId = doctor.Id, UserId = _userInfo.Id }); //_userDoctorRepository.Add(new UserDoctor() { DoctorId = doctor.Id, UserId = _userInfo.Id }); var success = await _repository.SaveChangesAsync(); return ResponseOutput.Result(success, _mapper.Map(doctor)); } else { var updateModel = basicInfoModel; var phone = updateModel.Phone.Trim(); if ((await _doctorRepository.FirstOrDefaultAsync(t => t.Phone == phone && t.Id != updateModel.Id) )!= null) { return ResponseOutput.NotOk("The current phone number already existed!", new DoctorBasicInfoCommand()); } var email = updateModel.EMail.Trim(); if (await _doctorRepository.AnyAsync(t => t.EMail == email && t.Id != updateModel.Id)) { return ResponseOutput.NotOk("The current email already existed!", new DoctorBasicInfoCommand()); } var doctor = await _doctorRepository.FirstOrDefaultAsync(t => t.Id == updateModel.Id).IfNullThrowException(); //删除中间表 Title对应的记录 await _repository.BatchDeleteAsync(t => t.DoctorId == updateModel.Id && t.KeyName == StaticData.Title); var adddata=new List(); //重新插入新的 Title记录 updateModel.TitleIds.ForEach(titleId => adddata.Add(new DoctorDictionary() { DoctorId = updateModel.Id.Value, KeyName = StaticData.Title, DictionaryId = titleId })); await _repository.AddRangeAsync(adddata); _mapper.Map(basicInfoModel, doctor); var success = await _repository.SaveChangesAsync(); return ResponseOutput.Result(success, basicInfoModel); } } /// ///详情、编辑-获取 医生基本信息 BasicInfo /// /// ReviewerID /// [HttpGet("{doctorId:guid}")] public async Task GetBasicInfo(Guid doctorId) { #region 用导航属性直接查询 //SELECT[t].[Id], [t].[Code], [t].[ChineseName], [t].[EMail], [t].[FirstName], [t].[Introduction], [t].[LastName], [t].[Phone], [t].[Sex], [t].[WeChat], [t].[Nation], [t0].[Title], [t0].[TitleCN], [t0].[TitleId], [t0].[ShowOrder], [t0].[Id], [t0].[Id0] //FROM( // SELECT TOP(1)[d].[Id], [d].[Code], [d].[ChineseName], [d].[EMail], [d].[FirstName], [d].[Introduction], [d].[LastName], [d].[Phone], [d].[Sex], [d].[WeChat], [d].[Nation] // FROM[Doctor] AS[d] WITH(NOLOCK) // WHERE[d].[Id] = @__doctorId_0 //) AS[t] //LEFT JOIN( // SELECT[d1].[Value] AS[Title], [d1].[ValueCN] AS[TitleCN], [d0].[DictionaryId] AS[TitleId], [d1].[ShowOrder], [d0].[Id], [d1].[Id] AS[Id0], [d0].[DoctorId] // FROM [DoctorDictionary] AS [d0] WITH (NOLOCK) // INNER JOIN[Dictionary] AS [d1] WITH (NOLOCK) ON [d0].[DictionaryId] = [d1].[Id] // WHERE[d0].[KeyName] = N'Title' //) AS[t0] ON[t].[Id] = [t0].[DoctorId] //ORDER BY[t].[Id], [t0].[ShowOrder], [t0].[Id] //var doctorQueryable = _doctorRepository // .Find(t => t.Id == doctorId) // .Select(doctor => new DoctorBasicInfoDTO() // { // Id = doctor.Id, // Code = doctor.Code, // ChineseName = doctor.ChineseName, // EMail = doctor.EMail, // FirstName = doctor.FirstName, // Introduction = doctor.Introduction, // LastName = doctor.LastName, // Phone = doctor.Phone, // Sex = doctor.Sex, // WeChat = doctor.WeChat, // Nation = doctor.Nation, // //不要分三个属性查询,会做三次左连接,这样 只会一个左连接 // TempObjList = doctor.DoctorDicList.Where(t => t.KeyName == StaticData.Title) // .Select(t => new TempObj { Title = t.Dictionary.Value, TitleCN = t.Dictionary.ValueCN, TitleId = t.DictionaryId, ShowOrder = t.Dictionary.ShowOrder }).OrderBy(k => k.ShowOrder).ToList(), // }); //var doctorBasicInfo = doctorQueryable.FirstOrDefault(); #endregion var doctorBasicInfo = (await _doctorRepository.Where(t => t.Id == doctorId) .ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException(); return doctorBasicInfo; } #endregion #region Employment信息--查询和更新 /// /// 详情、编辑-获取医生工作信息 Employment /// [HttpGet("{doctorId:Guid}")] public async Task GetEmploymentInfo(Guid doctorId) { #region init EF select 废弃 //var dic = GetDictionary(); //var employmentQueryable = from doctorItem in _doctorRepository // .Where(t => t.Id == doctorId) // join hospitalItem in _hospitalRepository.AsQueryable() on doctorItem.HospitalId equals hospitalItem.Id into g // from hospital in g.DefaultIfEmpty() // select new EmploymentDTO() // { // Id = doctorItem.Id, // //部门 // DepartmentId = doctorItem.DepartmentId, // DepartmentOther = doctorItem.DepartmentOther, // DepartmentOtherCN = doctorItem.DepartmentOtherCN, // //医院 // HospitalId = doctorItem.HospitalId, // PositionId = doctorItem.PositionId, // PositionOther = doctorItem.PositionOther, // PositionOtherCN = doctorItem.PositionOtherCN, // RankId = doctorItem.RankId, // RankOther = doctorItem.RankOther, // RankOtherCN = doctorItem.RankOtherCN, // City = hospital.City, // Country = hospital.Country, // UniversityAffiliated = hospital.UniversityAffiliated, // HospitalName = hospital.HospitalName, // Province = hospital.Province, // CityCN = hospital.CityCN, // CountryCN = hospital.CountryCN, // UniversityAffiliatedCN = hospital.UniversityAffiliatedCN, // HospitalNameCN = hospital.HospitalNameCN, // ProvinceCN = hospital.ProvinceCN // }; //var employmentInfo = employmentQueryable.FirstOrDefault(); //if (employmentInfo != null) //{ // //医院信息设置 // if (employmentInfo.HospitalId == Guid.Empty) // { // employmentInfo.City = string.Empty; // employmentInfo.Country = string.Empty; // employmentInfo.UniversityAffiliated = string.Empty; // employmentInfo.HospitalName = string.Empty; // employmentInfo.Province = string.Empty; // } // employmentInfo.Department = employmentInfo.DepartmentId == Guid.Empty ? employmentInfo.DepartmentOther : dic.FirstOrDefault(o => o.Id == employmentInfo.DepartmentId)?.Value ?? ""; // employmentInfo.Rank = employmentInfo.RankId == Guid.Empty ? employmentInfo.RankOther : dic.FirstOrDefault(o => o.Id == employmentInfo.RankId)?.Value ?? ""; // employmentInfo.Position = employmentInfo.PositionId == Guid.Empty ? employmentInfo.PositionOther : dic.FirstOrDefault(o => o.Id == employmentInfo.PositionId)?.Value ?? ""; // employmentInfo.DepartmentCN = employmentInfo.DepartmentId == Guid.Empty ? employmentInfo.DepartmentOther : dic.FirstOrDefault(o => o.Id == employmentInfo.DepartmentId)?.ValueCN ?? ""; // employmentInfo.RankCN = employmentInfo.RankId == Guid.Empty ? employmentInfo.RankOther : dic.FirstOrDefault(o => o.Id == employmentInfo.RankId)?.ValueCN ?? ""; // employmentInfo.PositionCN = employmentInfo.PositionId == Guid.Empty ? employmentInfo.PositionOther : dic.FirstOrDefault(o => o.Id == employmentInfo.PositionId)?.ValueCN ?? ""; //} #endregion var query = _doctorRepository.Where(t => t.Id == doctorId) .ProjectTo(_mapper.ConfigurationProvider); var employmentInfo = (await query.FirstOrDefaultAsync()).IfNullThrowException(); return employmentInfo; } [HttpPost] public async Task UpdateEmploymentInfo(EmploymentCommand doctorWorkInfoModel) { #region 废弃 //var success = _doctorRepository.Update(d => d.Id == doctorWorkInfoModel.Id, u => new Doctor() //{ // DepartmentId = doctorWorkInfoModel.DepartmentId, // DepartmentOther = doctorWorkInfoModel.DepartmentOther, // DepartmentOtherCN = doctorWorkInfoModel.DepartmentOtherCN, // SpecialityId = doctorWorkInfoModel.DepartmentId, // SpecialityOther = doctorWorkInfoModel.DepartmentOther, // SpecialityOtherCN = doctorWorkInfoModel.DepartmentOtherCN, // RankId = doctorWorkInfoModel.RankId, // RankOther = doctorWorkInfoModel.RankOther, // RankOtherCN = doctorWorkInfoModel.RankOtherCN, // PositionId = doctorWorkInfoModel.PositionId, // PositionOther = doctorWorkInfoModel.PositionOther, // PositionOtherCN = doctorWorkInfoModel.PositionOtherCN, // HospitalId = doctorWorkInfoModel.HospitalId, // UpdateTime = DateTime.Now //}); //var doctor = _doctorRepository.FirstOrDefault(d => d.Id == doctorWorkInfoModel.Id); //_mapper.Map(doctorWorkInfoModel, doctor); //var success = _doctorRepository.SaveChanges(); #endregion var entity = await _repository.InsertOrUpdateAsync(doctorWorkInfoModel, true); //_doctorRepository.UseMapper(_mapper).InsertOrUpdate(doctorWorkInfoModel, autoSave: true); return ResponseOutput.Ok(); } #endregion #region 医生技能信息 查询和 更新 [HttpGet, Route("{doctorId:Guid}")] public async Task GetSpecialtyInfo(Guid doctorId) { #region 利用导航属性直接查询出来 生成的sql ok 废弃 //var specialtyQueryable = _doctorRepository // .Where(t => t.Id == doctorId).Include(u => u.DoctorDicRelationList) // .Select(specialty => new SpecialtyDTO() // { // Id = specialty.Id, // ReadingTypeOther = specialty.ReadingTypeOther, // ReadingTypeOtherCN = specialty.ReadingTypeOtherCN, // SubspecialityOther = specialty.SubspecialityOther, // SubspecialityOtherCN = specialty.SubspecialityOtherCN, // DictionaryList = specialty.DoctorDicRelationList.Where(t => t.KeyName == StaticData.ReadingType || t.KeyName == StaticData.Subspeciality) // .Select(t => new SpecialtyDTO.DoctorDictionaryView() { DictionaryId = t.DictionaryId, Value = t.Dictionary.Value, ValueCN = t.Dictionary.ValueCN, ShowOrder = t.Dictionary.ShowOrder, KeyName = t.Dictionary.KeyName }) // .OrderBy(t => t.ShowOrder).ToList(), // SpecialityId = specialty.SpecialityId, // Speciality = specialty.Speciality.Value, // SpecialityCN = specialty.Speciality.ValueCN, // SpecialityOther = specialty.SpecialityOther, // SpecialityOtherCN = specialty.SpecialityOtherCN // }); //var specialtyInfo = specialtyQueryable.FirstOrDefault(); //return specialtyInfo; #endregion var test = await (_doctorRepository.Where(t => t.Id == doctorId) .ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException(); return test; } [HttpPost] public async Task UpdateSpecialtyInfo(SpecialtyCommand specialtyUpdateModel) { var doctor = await _doctorRepository.FirstOrDefaultAsync(t => t.Id == specialtyUpdateModel.Id); if (doctor == null) return Null404NotFound(doctor); ////删除中间表 //_doctorDictionaryRepository.Delete(t => // t.DoctorId == specialtyUpdateModel.Id && t.KeyName == StaticData.Subspeciality); //_doctorDictionaryRepository.Delete(t => // t.DoctorId == specialtyUpdateModel.Id && t.KeyName == StaticData.ReadingType); await _repository.BatchDeleteAsync(t => t.DoctorId == specialtyUpdateModel.Id && (t.KeyName == StaticData.Subspeciality || t.KeyName == StaticData.ReadingType)); //重新插入新的 var adddata = new List(); specialtyUpdateModel.ReadingTypeIds.ForEach(readingTypeId => adddata.Add( new DoctorDictionary() { DoctorId = specialtyUpdateModel.Id, KeyName = StaticData.ReadingType, DictionaryId = readingTypeId })); specialtyUpdateModel.SubspecialityIds.ForEach(subspecialityId => adddata.Add( new DoctorDictionary() { DoctorId = specialtyUpdateModel.Id, KeyName = StaticData.Subspeciality, DictionaryId = subspecialityId })); await _repository.AddRangeAsync(adddata); _mapper.Map(specialtyUpdateModel, doctor); var success = await _repository.SaveChangesAsync(); return ResponseOutput.Result(success); } #endregion #region 简历审核 [HttpPost] public async Task UpdateAuditResume(ResumeConfirmCommand auditResumeParam) { var userId = _userInfo.Id; //判断 合作协议、正式简历 是否有。如果没有,显示提示信息,并且不能保存 var attachmentList = await _attachmentRepository.Where(u => u.DoctorId == auditResumeParam.Id) .Select(u => u.Type).ToListAsync(); if (auditResumeParam.ResumeStatus == ResumeStatusEnum.Pass && ((!attachmentList.Contains("Resume")) || (!attachmentList.Contains("Consultant Agreement")))) { return ResponseOutput.NotOk("Resume & Consultant Agreement must be upload "); } var success = await _doctorRepository.BatchUpdateAsync(o => o.Id == auditResumeParam.Id, u => new Doctor() { CooperateStatus = auditResumeParam.CooperateStatus, ResumeStatus = auditResumeParam.ResumeStatus, AdminComment = auditResumeParam.AdminComment, ReviewStatus = auditResumeParam.ReviewStatus, AcceptingNewTrial = auditResumeParam.AcceptingNewTrial, ActivelyReading = auditResumeParam.ActivelyReading, AuditTime = DateTime.Now, AuditUserId = userId }); if (success) { if (!string.IsNullOrWhiteSpace(auditResumeParam.MessageContent)) { var message = new Message { FromUserId = userId, ToDoctorId = auditResumeParam.Id, Title = "Resume review results", Content = auditResumeParam.MessageContent, HasRead = false, MessageTime = DateTime.Now }; await _repository.AddAsync(message); success = await _repository.SaveChangesAsync(); } } return ResponseOutput.Result(success); } [HttpGet("{doctorId:guid}")] public async Task GetAuditState(Guid doctorId) { var doctor = (await _doctorRepository .ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync(t => t.Id == doctorId)).IfNullThrowException(); doctor.InHoliday = (await _repository.CountAsync(x=>x.DoctorId==doctorId&&x.EndDate<=DateTime.Now&&x.StartDate<=DateTime.Now)) > 0; return doctor; } /// /// 获取医生入组信息 正在提交的数量 已同意入组项目个数 正在读的 /// [HttpPost, Route("{doctorId:guid}")] public DoctorEnrollInfoDTO GetDoctorIntoGroupInfo(Guid doctorId) { var doctorQueryable = from doctor in _doctorRepository.Where(t => t.Id == doctorId) join intoGroupItem in _enrollRepository.AsQueryable() on doctor.Id equals intoGroupItem.DoctorId into t from intoGroupItem in t.DefaultIfEmpty() group intoGroupItem by intoGroupItem.DoctorId into g select new DoctorEnrollInfoDTO { DoctorId = g.Key, //Submitted = g.Sum(t => // t.EnrollStatus == (int)EnrollStatus.HasCommittedToCRO ? 1 : 0), //Approved = g.Sum(t => // t.EnrollStatus == (int)EnrollStatus.InviteIntoGroup ? 1 : 0), //Reading = g.Sum(t => // t.EnrollStatus == (int)EnrollStatus.DoctorReading ? 1 : 0) Submitted = g.Count(t => t.EnrollStatus == (int)EnrollStatus.HasCommittedToCRO), Approved = g.Count(t => t.EnrollStatus == (int)EnrollStatus.InviteIntoGroup), Reading = g.Count(t => t.EnrollStatus == (int)EnrollStatus.DoctorReading) }; return doctorQueryable.FirstOrDefault().IfNullThrowException(); } /// /// Get Statement of Work list.[New] /// [HttpGet("{doctorId:guid}")] public List GetDoctorSowList(Guid doctorId) { var query = from enroll in _enrollRepository.Where(u => u.DoctorId == doctorId && u.EnrollStatus >= 10) join trialExt in _trialExtRepository.AsQueryable() on enroll.TrialId equals trialExt.TrialId join trial in _trialRepository.AsQueryable() on enroll.TrialId equals trial.Id select new SowDTO { FileName = trialExt.SowName, FilePath = trialExt.SowPath, TrialCode = trial.TrialCode, CreateTime = trialExt.CreateTime }; return query.ToList().Where(u => !string.IsNullOrWhiteSpace(u.FileName)).ToList(); } /// /// Get Ack Statement of Work[New] /// [HttpGet("{doctorId:guid}")] public List GetDoctorAckSowList(Guid doctorId) { var query = from enroll in _enrollRepository.Where(u => u.DoctorId == doctorId) join attachment in _attachmentRepository.Where(u => u.DoctorId == doctorId) on enroll.AttachmentId equals attachment.Id join trial in _trialRepository.AsQueryable() on enroll.TrialId equals trial.Id select new SowDTO { FileName = attachment.FileName, FilePath = attachment.Path, TrialCode = trial.TrialCode, CreateTime = attachment.CreateTime }; return query.ToList(); } #endregion } }