医生发送邮件
parent
e92979388c
commit
7de33670c9
|
@ -115,12 +115,18 @@
|
|||
<Content Update="wwwroot\EmailTemplate\TrialSiteSurveyReject.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialDoctorExistJoin.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialUserExistJoin.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\AdminAddUser.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialDoctorFirstJoin.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\UserOptCommon.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗作为 [{1} (实验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC阅片相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
<div>
|
||||
项目编号: {3}
|
||||
</div>
|
||||
<div>
|
||||
试验方案号: {2}
|
||||
</div>
|
||||
<div>
|
||||
试验名称: {1}
|
||||
</div>
|
||||
<div>
|
||||
用户名: {4}
|
||||
</div>
|
||||
<div>
|
||||
角色: {5}
|
||||
</div>
|
||||
<div>
|
||||
系统登录地址:{6}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>祝您顺利!/Best Regards</div>
|
||||
<div style="font-size: 14px;">上海展影医疗科技有限公司</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗作为 [{1} (实验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC阅片相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
<div>
|
||||
项目编号: {3}
|
||||
</div>
|
||||
<div>
|
||||
试验方案号: {2}
|
||||
</div>
|
||||
<div>
|
||||
试验名称: {1}
|
||||
</div>
|
||||
<div>
|
||||
用户名: {4}
|
||||
</div>
|
||||
<div>
|
||||
角色: {5}
|
||||
</div>
|
||||
<div>
|
||||
首次登陆前,请通过该链接修改您的账户信息:
|
||||
<a href='{6}' style='margin-left:30px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
初始化账号信息
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>祝您顺利!/Best Regards</div>
|
||||
<div style="font-size: 14px;">上海展影医疗科技有限公司</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -3485,7 +3485,7 @@
|
|||
入组流程-CRO确定医生名单 [ Approve]
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Application.Services.EnrollService.ConfirmReviewer(System.Guid,System.Guid[],System.Int32)">
|
||||
<member name="M:IRaCIS.Application.Services.EnrollService.ConfirmReviewer(IRaCIS.Core.Application.Service.WorkLoad.DTO.ConfirmReviewerCommand)">
|
||||
<summary>
|
||||
入组流程-后台确认医生入组[Confirm]
|
||||
</summary>
|
||||
|
|
|
@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Hosting;
|
|||
using IRaCIS.Core.Application.Auth;
|
||||
using AutoMapper;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using Nito.AsyncEx;
|
||||
|
||||
namespace IRaCIS.Application.Services
|
||||
{
|
||||
|
@ -26,6 +27,8 @@ namespace IRaCIS.Application.Services
|
|||
|
||||
Task ExternalUserJoinEmail(Guid trialId, Guid userId, string baseUrl, string rootUrl);
|
||||
|
||||
Task DoctorJoinTrialEmail(Guid trialId, Guid doctorId, string baseUrl, string rootUrl);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -43,6 +46,12 @@ namespace IRaCIS.Application.Services
|
|||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly IRepository<UserType> _userTypeRepository;
|
||||
|
||||
private readonly IRepository<Doctor> _doctorTypeRepository;
|
||||
|
||||
private readonly AsyncLock _mutex = new AsyncLock();
|
||||
|
||||
|
||||
|
||||
public MailVerificationService(IRepository<VerificationCode> verificationCodeRepository,
|
||||
|
@ -51,6 +60,8 @@ namespace IRaCIS.Application.Services
|
|||
IRepository<User> userRepository,
|
||||
ITokenService tokenService,
|
||||
IRepository<Trial> trialRepository,
|
||||
IRepository<UserType> userTypeRepository,
|
||||
IRepository<Doctor> doctorTypeRepository,
|
||||
IMapper mapper)
|
||||
{
|
||||
_verificationCodeRepository = verificationCodeRepository;
|
||||
|
@ -64,6 +75,9 @@ namespace IRaCIS.Application.Services
|
|||
_userRepository = userRepository;
|
||||
_trialRepository = trialRepository;
|
||||
|
||||
_userTypeRepository = userTypeRepository;
|
||||
_doctorTypeRepository = doctorTypeRepository;
|
||||
|
||||
}
|
||||
|
||||
//重置邮箱
|
||||
|
@ -128,7 +142,6 @@ namespace IRaCIS.Application.Services
|
|||
|
||||
|
||||
|
||||
|
||||
//不登录 通过邮箱重置密码
|
||||
public async Task AnolymousSendEmailForResetAccount(string emailAddress, int verificationCode)
|
||||
{
|
||||
|
@ -354,7 +367,7 @@ namespace IRaCIS.Application.Services
|
|||
}
|
||||
|
||||
|
||||
|
||||
//Site调研 用户加入项目
|
||||
public async Task SiteSurveyUserJoinEmail(Guid trialId, Guid userId, string baseUrl, string rootUrl)
|
||||
{
|
||||
var sysUserInfo = (await _userRepository.Where(t => t.Id == userId).Include(t => t.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();
|
||||
|
@ -416,6 +429,7 @@ namespace IRaCIS.Application.Services
|
|||
|
||||
}
|
||||
|
||||
//外部用户 加入项目
|
||||
public async Task ExternalUserJoinEmail(Guid trialId, Guid userId, string baseUrl, string rootUrl)
|
||||
{
|
||||
var trialInfo = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId)).IfNullThrowException();
|
||||
|
@ -480,6 +494,100 @@ namespace IRaCIS.Application.Services
|
|||
|
||||
|
||||
|
||||
public async Task DoctorJoinTrialEmail(Guid trialId, Guid doctorId, string baseUrl, string rootUrl)
|
||||
{
|
||||
var doctor = await _doctorTypeRepository.FindAsync(doctorId);
|
||||
User sysUserInfo = null;
|
||||
|
||||
|
||||
using (await _mutex.LockAsync())
|
||||
{
|
||||
var isDoctorHaveAccount = await _userRepository.AnyAsync(t => t.DoctorId == doctorId);
|
||||
|
||||
|
||||
if (!isDoctorHaveAccount)
|
||||
{
|
||||
|
||||
var saveItem = new User() { FirstName = doctor.FirstName, LastName = doctor.LastName, EMail = doctor.EMail };
|
||||
|
||||
saveItem.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1;
|
||||
|
||||
saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User));
|
||||
|
||||
saveItem.UserName = saveItem.UserCode;
|
||||
|
||||
saveItem.UserTypeEnum = UserTypeEnum.IndependentReviewer;
|
||||
|
||||
saveItem.DoctorId = doctorId;
|
||||
|
||||
sysUserInfo = await _userRepository.AddAsync(saveItem);
|
||||
|
||||
await _userRepository.SaveChangesAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
sysUserInfo = (await _userRepository.Where(t => t.DoctorId == doctorId).Include(t => t.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();
|
||||
}
|
||||
}
|
||||
|
||||
var userType= await _userTypeRepository.FirstAsync(t => t.UserTypeEnum== UserTypeEnum.IndependentReviewer);
|
||||
|
||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
||||
|
||||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress("GRR", "iracis_grr@163.com"));
|
||||
//收件地址
|
||||
messageToSend.To.Add(new MailboxAddress(doctor.FullName, doctor.EMail));
|
||||
//主题
|
||||
messageToSend.Subject = $"[来自展影IRC] [{ trialInfo.ResearchProgramNo}]邀请信";
|
||||
|
||||
|
||||
var builder = new BodyBuilder();
|
||||
|
||||
|
||||
var token = _tokenService.GetToken(IRaCISClaims.Create(_mapper.Map<UserBasicInfo>(sysUserInfo)));
|
||||
|
||||
if (sysUserInfo.IsFirstAdd)
|
||||
{
|
||||
await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
|
||||
}
|
||||
|
||||
|
||||
var pathToFile = _hostEnvironment.WebRootPath
|
||||
+ Path.DirectorySeparatorChar.ToString()
|
||||
+ "EmailTemplate"
|
||||
+ Path.DirectorySeparatorChar.ToString()
|
||||
+ (sysUserInfo.IsFirstAdd ? "TrialDoctorFirstJoin.html" : "TrialDoctorExistJoin.html");
|
||||
|
||||
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
|
||||
{
|
||||
var templateInfo = SourceReader.ReadToEnd();
|
||||
|
||||
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + userType.UserTypeShortName + "&access_token=" + token;
|
||||
|
||||
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
||||
|
||||
var redirectUrl = $"{domain}/api/User/UserRedirect?url={ System.Web.HttpUtility.UrlEncode(routeUrl) }";
|
||||
|
||||
builder.HtmlBody = string.Format(templateInfo,
|
||||
sysUserInfo.FullName,
|
||||
trialInfo.ExperimentName,
|
||||
trialInfo.ResearchProgramNo,
|
||||
trialInfo.TrialCode,
|
||||
sysUserInfo.UserName,
|
||||
sysUserInfo.UserTypeRole.UserTypeShortName,
|
||||
sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
|
||||
);
|
||||
}
|
||||
|
||||
messageToSend.Body = builder.ToMessageBody();
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, null);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -67,6 +67,21 @@ namespace IRaCIS.Core.Application.Service.WorkLoad.DTO
|
|||
|
||||
}
|
||||
|
||||
public class ConfirmReviewerCommand
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid[] DoctorIdArray { get; set; } = new Guid [0];
|
||||
|
||||
public int ConfirmState { get; set; }
|
||||
|
||||
public string BaseUrl { get; set; } = string.Empty;
|
||||
|
||||
public string RouteUrl { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
public class EnrollCommand
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace IRaCIS.Application.Services
|
|||
private readonly IRepository<Doctor> _doctorRepository;
|
||||
private readonly IRepository<EnrollDetail> _enrollDetailRepository;
|
||||
private readonly IRepository<Workload> _workloadRepository;
|
||||
private readonly IMailVerificationService _mailVerificationService;
|
||||
|
||||
|
||||
public EnrollService(IRepository<Trial> clinicalTrialProjectRepository,
|
||||
|
@ -27,7 +28,9 @@ namespace IRaCIS.Application.Services
|
|||
IRepository<Enroll> intoGroupRepository,
|
||||
IRepository<Doctor> doctorRepository,
|
||||
IRepository<TrialPaymentPrice> TrialPaymentPriceRepository,
|
||||
IRepository<EnrollDetail> intoGroupDetailRepository, IRepository<Workload> workloadRepository)
|
||||
IRepository<EnrollDetail> intoGroupDetailRepository,
|
||||
IRepository<Workload> workloadRepository,
|
||||
IMailVerificationService mailVerificationService)
|
||||
{
|
||||
_trialRepository = clinicalTrialProjectRepository;
|
||||
_TrialPaymentPriceRepository = TrialPaymentPriceRepository;
|
||||
|
@ -38,6 +41,8 @@ namespace IRaCIS.Application.Services
|
|||
_enrollDetailRepository = intoGroupDetailRepository;
|
||||
_workloadRepository = workloadRepository;
|
||||
|
||||
_mailVerificationService = mailVerificationService;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -344,10 +349,11 @@ namespace IRaCIS.Application.Services
|
|||
/// 入组流程-后台确认医生入组[Confirm]
|
||||
/// </summary>
|
||||
|
||||
[HttpPost("{trialId:guid}/{confirmState:int}")]
|
||||
[HttpPost]
|
||||
[TypeFilter(typeof(TrialResourceFilter))]
|
||||
[Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)]
|
||||
public async Task<IResponseOutput> ConfirmReviewer(Guid trialId, Guid[] doctorIdArray, int confirmState)
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> ConfirmReviewer(ConfirmReviewerCommand confirmReviewerCommand)
|
||||
{
|
||||
//var trial = _trialRepository.FirstOrDefault(t => t.Id == trialId);
|
||||
//var existItem = _trialRepository.FindSingleOrDefault(u => u.Id == trialId && u.TrialStatus >= (int)TrialEnrollStatus.HasConfirmedDoctorNames);
|
||||
|
@ -356,6 +362,8 @@ namespace IRaCIS.Application.Services
|
|||
////trial.TrialStatus = (int)TrialStatus.HasConfirmedDoctorNames;
|
||||
//_trialRepository.Update(trial);
|
||||
|
||||
var trialId = confirmReviewerCommand.TrialId;
|
||||
|
||||
var trial = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
||||
|
||||
if (trial == null) return Null404NotFound(trial);
|
||||
|
@ -364,16 +372,16 @@ namespace IRaCIS.Application.Services
|
|||
//更新入组表
|
||||
var intoGroupList = await _enrollRepository.Where(t => t.TrialId == trialId,true).ToListAsync();
|
||||
|
||||
if (confirmState == 1) //确认入组
|
||||
if (confirmReviewerCommand.ConfirmState == 1) //确认入组
|
||||
{
|
||||
foreach (var intoGroupItem in intoGroupList)
|
||||
{
|
||||
if (doctorIdArray.Contains(intoGroupItem.DoctorId))
|
||||
if (confirmReviewerCommand.DoctorIdArray.Contains(intoGroupItem.DoctorId))
|
||||
{
|
||||
intoGroupItem.EnrollStatus = (int)EnrollStatus.ConfirmIntoGroup;
|
||||
intoGroupItem.EnrollTime = DateTime.Now;
|
||||
|
||||
|
||||
await _mailVerificationService.DoctorJoinTrialEmail(trialId, intoGroupItem.DoctorId, confirmReviewerCommand.BaseUrl, confirmReviewerCommand.RouteUrl);
|
||||
await _enrollDetailRepository.AddAsync(new EnrollDetail()
|
||||
{
|
||||
DoctorId = intoGroupItem.DoctorId,
|
||||
|
@ -385,11 +393,11 @@ namespace IRaCIS.Application.Services
|
|||
}
|
||||
|
||||
}
|
||||
else if (confirmState == 0)//回退上一步
|
||||
else if (confirmReviewerCommand.ConfirmState == 0)//回退上一步
|
||||
{
|
||||
foreach (var intoGroupItem in intoGroupList)
|
||||
{
|
||||
if (doctorIdArray.Contains(intoGroupItem.DoctorId))
|
||||
if (confirmReviewerCommand.DoctorIdArray.Contains(intoGroupItem.DoctorId))
|
||||
{
|
||||
intoGroupItem.EnrollStatus = (int)EnrollStatus.InviteIntoGroup;
|
||||
intoGroupItem.EnrollTime = null;
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace IRaCIS.Application.Services
|
|||
{
|
||||
Task<IResponseOutput> AddOrUpdateEnroll(EnrollCommand addOrUpdateModel);
|
||||
Task<IResponseOutput> ApproveReviewer(Guid trialId, Guid[] doctorIdArray, int auditState);
|
||||
Task<IResponseOutput> ConfirmReviewer(Guid trialId, Guid[] doctorIdArray, int confirmState);
|
||||
//Task<IResponseOutput> ConfirmReviewer(Guid trialId, Guid[] doctorIdArray, int confirmState);
|
||||
Task<IResponseOutput> EnrollBackOrOut(Guid trialId, Guid doctorId, int optType, DateTime? outEnrollTime);
|
||||
Task<PageOutput<EnrollViewModel>> GetTrialDoctorList(EnrollGetQuery challengeQuery);
|
||||
Task<IResponseOutput> SelectReviewers(Guid trialId, Guid[] doctorIdArray);
|
||||
|
|
|
@ -4,19 +4,22 @@ namespace IRaCIS.Core.Domain.Share
|
|||
{
|
||||
public enum ReadingCategory
|
||||
{
|
||||
|
||||
//访视
|
||||
Visit=1,
|
||||
|
||||
//阅片周期
|
||||
ReadingPeriod=2,
|
||||
|
||||
//全局
|
||||
Global=3
|
||||
}
|
||||
|
||||
public enum TaskState
|
||||
{
|
||||
|
||||
//未分配
|
||||
NotAllocate = 0,
|
||||
|
||||
//已分配
|
||||
Allocated = 2,
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,9 @@ namespace IRaCIS.Core.Domain.Models
|
|||
|
||||
public string EmailToken { get; set; } = string.Empty;
|
||||
|
||||
//医生生成账号后,会有值
|
||||
public Guid? DoctorId { get; set; }
|
||||
|
||||
[Projectable] public string FullName => LastName + " / " + FirstName;
|
||||
|
||||
//[Projectable] public string FullName => $"{LastName} / {FirstName}";
|
||||
|
|
Loading…
Reference in New Issue