历史邮件整理
parent
05693d090d
commit
652cad9726
|
@ -8,6 +8,7 @@ using MassTransit;
|
||||||
using MassTransit.Mediator;
|
using MassTransit.Mediator;
|
||||||
using MassTransit.Scheduling;
|
using MassTransit.Scheduling;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service.BackGroundJob
|
namespace IRaCIS.Core.Application.Service.BackGroundJob
|
||||||
{
|
{
|
||||||
|
@ -18,9 +19,7 @@ namespace IRaCIS.Core.Application.Service.BackGroundJob
|
||||||
|
|
||||||
}
|
}
|
||||||
public class IRaCISCHangfireJob(ILogger<IRaCISCHangfireJob> _logger,
|
public class IRaCISCHangfireJob(ILogger<IRaCISCHangfireJob> _logger,
|
||||||
IRepository<Internationalization> _internationalizationRepository,
|
|
||||||
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository,
|
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository,
|
||||||
IMessageScheduler _iMessageScheduler,
|
|
||||||
IBus _bus
|
IBus _bus
|
||||||
) : IIRaCISHangfireJob
|
) : IIRaCISHangfireJob
|
||||||
{
|
{
|
||||||
|
@ -32,7 +31,6 @@ namespace IRaCIS.Core.Application.Service.BackGroundJob
|
||||||
_logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~");
|
_logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//创建邮件定时任务
|
//创建邮件定时任务
|
||||||
await InitSysAndTrialCronJobAsync();
|
await InitSysAndTrialCronJobAsync();
|
||||||
|
|
||||||
|
@ -44,41 +42,37 @@ namespace IRaCIS.Core.Application.Service.BackGroundJob
|
||||||
|
|
||||||
public async Task InitSysAndTrialCronJobAsync()
|
public async Task InitSysAndTrialCronJobAsync()
|
||||||
{
|
{
|
||||||
|
//项目定时任务都在default 队列
|
||||||
|
var dbJobIdList = JobStorage.Current.GetConnection().GetRecurringJobs().Where(t => t.Queue == "default").Select(t => t.Id).ToList();
|
||||||
|
|
||||||
|
foreach (var jobId in dbJobIdList)
|
||||||
|
{
|
||||||
|
HangfireJobHelper.RemoveCronJob(jobId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var taskInfoList = await _trialEmailNoticeConfigRepository.Where(t => t.Trial.TrialStatusStr == StaticData.TrialState.TrialOngoing && t.EmailCron != string.Empty && t.IsAutoSend)
|
var taskInfoList = await _trialEmailNoticeConfigRepository.Where(t => t.Trial.TrialStatusStr == StaticData.TrialState.TrialOngoing && t.EmailCron != string.Empty && t.IsAutoSend)
|
||||||
.Select(t => new { t.Id, t.Code, t.EmailCron, t.BusinessScenarioEnum, t.TrialId })
|
.Select(t => new { t.Id, t.Code, TrialCode=t.Trial.TrialCode, t.EmailCron, t.BusinessScenarioEnum, t.TrialId })
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
foreach (var task in taskInfoList)
|
foreach (var task in taskInfoList)
|
||||||
{
|
{
|
||||||
//利用主键作为任务Id
|
//利用主键作为任务Id
|
||||||
var jobId = $"{task.TrialId}_{task.Id}";
|
var jobId = $"{task.TrialId}({task.TrialCode})_{task.Id}({task.BusinessScenarioEnum})";
|
||||||
|
|
||||||
switch (task.BusinessScenarioEnum)
|
var trialId = task.TrialId;
|
||||||
{
|
|
||||||
|
|
||||||
case EmailBusinessScenario.QCTask:
|
HangfireJobHelper.AddOrUpdateTrialCronJob(jobId, trialId, task.BusinessScenarioEnum, task.EmailCron);
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EmailBusinessScenario.CRCToQCQuestion:
|
|
||||||
|
|
||||||
break;
|
|
||||||
case EmailBusinessScenario.QCToCRCImageQuestion:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//var schedulerEndpoint = await _bus.GetSendEndpoint(new Uri("queue:hangfire"));
|
|
||||||
//await schedulerEndpoint.ScheduleRecurringSend<QCImageQuestionSchedule>(new Uri("queue:mt-message-queue"), new QCImageQuestionSchedule() { ScheduleId = jobId, CronExpression = "0 0/1 * 1/1 * ? *" }, new PollExternalSystem { });
|
|
||||||
//await schedulerEndpoint.ScheduleRecurringSend<QCImageQuestionSchedule>(new Uri("queue:hangfire"), new QCImageQuestionSchedule() { ScheduleId = jobId + jobId, CronExpression = "0 0/1 * 1/1 * ? *" }, new PollExternalSystem { });
|
|
||||||
|
|
||||||
|
|
||||||
HangfireJobHelper.AddOrUpdateTrialCronJob(jobId, task.TrialId, task.BusinessScenarioEnum, task.EmailCron);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//var schedulerEndpoint = await _bus.GetSendEndpoint(new Uri("queue:sys_init"));
|
||||||
|
//await schedulerEndpoint.ScheduleRecurringSend<QCImageQuestionSchedule>(new Uri("queue:mt-message-queue"), new QCImageQuestionSchedule() { ScheduleId = jobId, CronExpression = "0 0/1 * 1/1 * ? *" }, new PollExternalSystem { });
|
||||||
|
//await schedulerEndpoint.ScheduleRecurringSend<QCImageQuestionSchedule>(new Uri("queue:sys_init"), new QCImageQuestionSchedule() { ScheduleId = jobId + jobId, CronExpression = "0 0/1 * 1/1 * ? *" }, new PollExternalSystem { });
|
||||||
|
|
||||||
|
//HangfireJobHelper.AddOrUpdateCronJob<IMediator>("test-MasstransiTestCommand", t => t.Send(new MasstransiTestCommand { value = "message at " + DateTime.Now.ToString() }, default), "0/3 * * * * ? ");
|
||||||
|
|
||||||
|
//await _bus.ScheduleRecurringSend<QCImageQuestionSchedule>(new Uri("queue:mt-message-queue"), new QCImageQuestionSchedule() { ScheduleId = jobId, CronExpression = "0 0/1 * 1/1 * ? *" }, new QCImageQuestionSchedule { });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PollExternalSystem { }
|
public class PollExternalSystem { }
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using Hangfire;
|
using Hangfire;
|
||||||
|
using IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using MassTransit.Mediator;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper
|
namespace IRaCIS.Core.Application.Helper
|
||||||
{
|
{
|
||||||
|
@ -62,15 +64,15 @@ namespace IRaCIS.Core.Application.Helper
|
||||||
{
|
{
|
||||||
|
|
||||||
case EmailBusinessScenario.QCTask:
|
case EmailBusinessScenario.QCTask:
|
||||||
HangfireJobHelper.AddOrUpdateCronJob<IEmailSendService>(jobId, t => t.SendTrialImageQCTaskEmailAsync(trialId), emailCron);
|
|
||||||
|
HangfireJobHelper.AddOrUpdateCronJob<IMediator>(jobId, t => t.Send(new ImageQCRecurringEvent() { TrialId = trialId }, default), emailCron);
|
||||||
break;
|
break;
|
||||||
case EmailBusinessScenario.CRCToQCQuestion:
|
case EmailBusinessScenario.CRCToQCQuestion:
|
||||||
HangfireJobHelper.AddOrUpdateCronJob<IEmailSendService>(jobId, t => t.SendTrialQCQuestionEmailAsync(trialId), emailCron);
|
HangfireJobHelper.AddOrUpdateCronJob<IMediator>(jobId, t => t.Send(new CRCImageQuestionRecurringEvent() { TrialId = trialId }, default), emailCron);
|
||||||
break;
|
break;
|
||||||
case EmailBusinessScenario.QCToCRCImageQuestion:
|
case EmailBusinessScenario.QCToCRCImageQuestion:
|
||||||
HangfireJobHelper.AddOrUpdateCronJob<IEmailSendService>(jobId, t => t.SendTrialImageQuestionAsync(trialId), emailCron);
|
HangfireJobHelper.AddOrUpdateCronJob<IMediator>(jobId, t => t.Send(new QCImageQuestionRecurringEvent() { TrialId = trialId }, default), emailCron);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13011,6 +13011,51 @@
|
||||||
参考链接:https://github.com/MassTransit/MassTransit/discussions/2498
|
参考链接:https://github.com/MassTransit/MassTransit/discussions/2498
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.QCImageQuestionRecurringEventConsumer">
|
||||||
|
<summary>
|
||||||
|
QC 影像质疑
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.QCImageQuestionRecurringEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSiteUser},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
|
||||||
|
<summary>
|
||||||
|
QC 影像质疑
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.CRCImageQuestionRecurringEventConsumer">
|
||||||
|
<summary>
|
||||||
|
CRC 影像质疑
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CRCImageQuestionRecurringEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSiteUser},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
|
||||||
|
<summary>
|
||||||
|
CRC 影像质疑
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.ImageQCRecurringEventConsumer">
|
||||||
|
<summary>
|
||||||
|
影像质控 发送给QC的
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ImageQCRecurringEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSiteUser},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
|
||||||
|
<summary>
|
||||||
|
影像质控 发送给QC的
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.QCImageQuestionRecurringEvent">
|
||||||
|
<summary>
|
||||||
|
QC 影像质疑待处理
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.CRCImageQuestionRecurringEvent">
|
||||||
|
<summary>
|
||||||
|
CRC 影像质疑
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.ImageQCRecurringEvent">
|
||||||
|
<summary>
|
||||||
|
影像质控
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.QCImageQuestionSchedule">
|
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.QCImageQuestionSchedule">
|
||||||
<summary>
|
<summary>
|
||||||
QC 影像质疑待处理
|
QC 影像质疑待处理
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
using Amazon.Runtime.Internal.Util;
|
||||||
|
using DocumentFormat.OpenXml;
|
||||||
|
using IRaCIS.Core.Application.Helper;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using IRaCIS.Core.Infrastructure;
|
||||||
|
using MimeKit;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
|
|
||||||
|
public static class OldRecurringEmailHelper
|
||||||
|
{
|
||||||
|
public static string EmailNamePlaceholder => StaticData.EmailSend.EmailNamePlaceholder;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static async Task SendTrialEmailAsync(
|
||||||
|
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository,
|
||||||
|
IRepository<Trial> _trialRepository,
|
||||||
|
IRepository<TrialUser> _trialUserRepository,
|
||||||
|
IRepository<VisitTask> _visitTaskRepository,
|
||||||
|
IRepository<TrialSiteUser> _trialSiteUserRepository,
|
||||||
|
|
||||||
|
Guid trialId, EmailBusinessScenario businessScenario,
|
||||||
|
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc,
|
||||||
|
Guid? trialSiteId = null, Guid? trialReadingCriterionId = null)
|
||||||
|
{
|
||||||
|
//找到配置
|
||||||
|
var trialEmailConfig = await _trialEmailNoticeConfigRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionId && t.BusinessScenarioEnum == businessScenario, ignoreQueryFilters: true)
|
||||||
|
.Include(t => t.TrialEmailNoticeUserList).Include(t => t.TrialEmailBlackUserList).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
|
||||||
|
if (trialEmailConfig == null || trialEmailConfig.IsAutoSend == false || trialEmailConfig.IsEnable == false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var sendEmailConfig = new SMTPEmailConfig();
|
||||||
|
|
||||||
|
var (topicStr, htmlBodyStr, isEn_us, onlyToUserId) = topicAndHtmlFunc(trialEmailConfig);
|
||||||
|
|
||||||
|
|
||||||
|
sendEmailConfig.TopicDescription = topicStr;
|
||||||
|
sendEmailConfig.HtmlBodyStr = htmlBodyStr;
|
||||||
|
|
||||||
|
|
||||||
|
var blackUserIdList = trialEmailConfig.TrialEmailBlackUserList.Select(t => t.UserId).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
var toUserTypeEnumList = trialEmailConfig.TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.To).Select(c => c.UserType).ToList();
|
||||||
|
|
||||||
|
var copyUserTypeEnumList = trialEmailConfig.TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.Copy).Select(c => c.UserType).ToList();
|
||||||
|
|
||||||
|
var allUserTypeEnumList = toUserTypeEnumList.Union(copyUserTypeEnumList).Distinct().ToList();
|
||||||
|
|
||||||
|
var allUserList = await _trialUserRepository.Where(t => t.TrialId == trialId && allUserTypeEnumList.Contains(t.User.UserTypeEnum)).Select(t => new { t.UserId, t.User.EMail, t.User.FullName, t.User.UserTypeEnum }).ToListAsync();
|
||||||
|
|
||||||
|
|
||||||
|
var toUserList = allUserList.Where(t => toUserTypeEnumList.Contains(t.UserTypeEnum))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
//收件人 有CRC CRA , CRC CRA的账户要按照中心发送
|
||||||
|
if (trialSiteId == null && toUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA) && onlyToUserId == null)
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException("当前场景收件人包含CRC CRA,但是没有siteId,请联系后端开发");
|
||||||
|
}
|
||||||
|
if (trialSiteId != null && toUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA))
|
||||||
|
{
|
||||||
|
var curentSiteUserIdList = _trialSiteUserRepository.Where(t => t.TrialId == trialId && t.TrialSiteId == trialSiteId).Select(t => t.UserId).ToList();
|
||||||
|
|
||||||
|
toUserList = toUserList.Where(t => (t.UserTypeEnum != UserTypeEnum.CRA && t.UserTypeEnum != UserTypeEnum.ClinicalResearchCoordinator) || curentSiteUserIdList.Contains(t.UserId)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//去除黑名单
|
||||||
|
toUserList = toUserList.Where(t => !blackUserIdList.Contains(t.UserId)).ToList();
|
||||||
|
|
||||||
|
var copyUserList = allUserList.Where(t => copyUserTypeEnumList.Contains(t.UserTypeEnum))
|
||||||
|
.Where(t => !blackUserIdList.Contains(t.UserId)).ToList();
|
||||||
|
|
||||||
|
if (trialSiteId != null && copyUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA))
|
||||||
|
{
|
||||||
|
var curentSiteUserIdList = _trialSiteUserRepository.Where(t => t.TrialId == trialId && t.TrialSiteId == trialSiteId).Select(t => t.UserId).ToList();
|
||||||
|
|
||||||
|
copyUserList = copyUserList.Where(t => (t.UserTypeEnum != UserTypeEnum.CRA && t.UserTypeEnum != UserTypeEnum.ClinicalResearchCoordinator) || curentSiteUserIdList.Contains(t.UserId)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onlyToUserId != null)
|
||||||
|
{
|
||||||
|
toUserList = toUserList.Where(t => t.UserId == onlyToUserId).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendEmailConfig.HtmlBodyStr = htmlBodyStr.Replace(EmailNamePlaceholder, string.Join(isEn_us ? ", " : "、", toUserList.Select(t => t.FullName).ToList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toUserList.Count == 0)
|
||||||
|
{
|
||||||
|
//---没有收件人,无法发送邮件
|
||||||
|
throw new BusinessValidationFailedException(I18n.T("TrialEmailN_NoRecipient"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (trialEmailConfig.FromEmail.Contains("@") && !string.IsNullOrEmpty(trialEmailConfig.FromEmail))
|
||||||
|
{
|
||||||
|
|
||||||
|
sendEmailConfig.FromEmailAddress = new MimeKit.MailboxAddress(trialEmailConfig.FromName, trialEmailConfig.FromEmail);
|
||||||
|
sendEmailConfig.AuthorizationCode = trialEmailConfig.AuthorizationCode;
|
||||||
|
sendEmailConfig.UserName = trialEmailConfig.FromEmail;
|
||||||
|
|
||||||
|
sendEmailConfig.Host = trialEmailConfig.SMTPServerAddress;
|
||||||
|
sendEmailConfig.Port = trialEmailConfig.SMTPServerPort;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//---项目发件邮箱配置有误,请核实
|
||||||
|
throw new BusinessValidationFailedException(I18n.T("TrialEmailN_InvalidEmailConfig"));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in toUserList)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (item.EMail.Contains("@") && !string.IsNullOrEmpty(item.EMail))
|
||||||
|
{
|
||||||
|
|
||||||
|
sendEmailConfig.ToMailAddressList.Add(new MimeKit.MailboxAddress(item.FullName, item.EMail));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var item in copyUserList)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (item.EMail.Contains("@") && !string.IsNullOrEmpty(item.EMail))
|
||||||
|
{
|
||||||
|
|
||||||
|
sendEmailConfig.CopyToMailAddressList.Add(new MimeKit.MailboxAddress(item.FullName, item.EMail));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//邮件附件 这里是原格式发送,不是PDF
|
||||||
|
|
||||||
|
//if (trialEmailConfig.AttachCNPath != string.Empty && trialEmailConfig.AttachPath != string.Empty)
|
||||||
|
//{
|
||||||
|
// var phyPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, isEn_us? trialEmailConfig.AttachName: trialEmailConfig.AttachNameCN);
|
||||||
|
|
||||||
|
// //先预先生成了邮件,发送预先生成的邮件
|
||||||
|
// sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig()
|
||||||
|
// {
|
||||||
|
// FileName = $"{attachPrefix}_{Path.GetFileName(_userInfo.IsEn_Us ? trialEmailConfig.AttachName : trialEmailConfig.AttachNameCN)}",
|
||||||
|
|
||||||
|
// FileStream = File.OpenRead(phyPath),
|
||||||
|
// });
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (sendEmailConfig != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
await SendEmailHelper.SendEmailAsync(sendEmailConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
using IRaCIS.Core.Application.MassTransit.Command;
|
||||||
|
using IRaCIS.Core.Domain.BaseModel;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using MassTransit;
|
||||||
|
using MassTransit.Scheduling;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// QC 影像质疑
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
public class QCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRepository,
|
||||||
|
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository,
|
||||||
|
IRepository<TrialUser> _trialUserRepository,
|
||||||
|
IRepository<VisitTask> _visitTaskRepository,
|
||||||
|
IRepository<TrialSiteUser> _trialSiteUserRepository,
|
||||||
|
IOptionsMonitor<SystemEmailSendConfig> _SystemEmailSendConfig) : IConsumer<QCImageQuestionRecurringEvent>
|
||||||
|
{
|
||||||
|
public async Task Consume(ConsumeContext<QCImageQuestionRecurringEvent> context)
|
||||||
|
{
|
||||||
|
var trialId = context.Message.TrialId;
|
||||||
|
|
||||||
|
var isEn_us = false;
|
||||||
|
|
||||||
|
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync();
|
||||||
|
|
||||||
|
//找到 该项目的CRC 用户Id
|
||||||
|
var userList = await _trialUserRepository.Where(t => t.TrialId == trialId).Where(t => t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { t.UserId, t.User.FullName }).ToListAsync();
|
||||||
|
|
||||||
|
//判断是否任务可以领取 ,可以的话 发送邮件
|
||||||
|
|
||||||
|
foreach (var user in userList)
|
||||||
|
{
|
||||||
|
var userId = user.UserId;
|
||||||
|
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
||||||
|
var query = _trialRepository.Where(t => t.Id == trialId)
|
||||||
|
|
||||||
|
.Select(t => new
|
||||||
|
{
|
||||||
|
//质疑待处理
|
||||||
|
ToBeDealedCount = t.SubjectVisitList.Where(t => t.TrialSite.CRCUserList.Any(t => t.UserId == userId)).SelectMany(c => c.QCChallengeList)
|
||||||
|
.Where(u => u.IsClosed == false && (u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IQC || u.LatestReplyUserId == null)).Count(),
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var sendStat = await query.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
//当前人
|
||||||
|
if (sendStat != null && (sendStat.ToBeDealedCount > 0))
|
||||||
|
{
|
||||||
|
|
||||||
|
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
||||||
|
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
|
||||||
|
user.FullName, DateTime.Now, sendStat.ToBeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr, isEn_us, userId);
|
||||||
|
};
|
||||||
|
|
||||||
|
await OldRecurringEmailHelper.SendTrialEmailAsync(
|
||||||
|
_trialEmailNoticeConfigRepository,
|
||||||
|
_trialRepository,
|
||||||
|
_trialUserRepository,
|
||||||
|
_visitTaskRepository,
|
||||||
|
_trialSiteUserRepository,
|
||||||
|
trialId, EmailBusinessScenario.QCToCRCImageQuestion, topicAndHtmlFunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CRC 影像质疑
|
||||||
|
/// </summary>
|
||||||
|
public class CRCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRepository,
|
||||||
|
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository,
|
||||||
|
IRepository<TrialUser> _trialUserRepository,
|
||||||
|
IRepository<VisitTask> _visitTaskRepository,
|
||||||
|
IRepository<TrialSiteUser> _trialSiteUserRepository,
|
||||||
|
IOptionsMonitor<SystemEmailSendConfig> _SystemEmailSendConfig) : IConsumer<CRCImageQuestionRecurringEvent>
|
||||||
|
{
|
||||||
|
public async Task Consume(ConsumeContext<CRCImageQuestionRecurringEvent> context)
|
||||||
|
{
|
||||||
|
var trialId = context.Message.TrialId;
|
||||||
|
|
||||||
|
var isEn_us = false;
|
||||||
|
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr, t.DeclarationTypeEnumList }).FirstNotNullAsync();
|
||||||
|
|
||||||
|
//找到 该项目的IQC 用户Id
|
||||||
|
var userList = await _trialUserRepository.Where(t => t.TrialId == trialId).Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.User.FullName }).ToListAsync();
|
||||||
|
|
||||||
|
//判断是否任务可以领取 ,可以的话 发送邮件
|
||||||
|
|
||||||
|
foreach (var user in userList)
|
||||||
|
{
|
||||||
|
var userId = user.UserId;
|
||||||
|
|
||||||
|
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
||||||
|
var query = _trialRepository
|
||||||
|
.Where(t => t.Id == trialId)
|
||||||
|
.Select(t => new
|
||||||
|
{
|
||||||
|
ReUploadTobeDealedCount = t.SubjectVisitList.SelectMany(c => c.QCChallengeList)
|
||||||
|
.Where(u => u.CreateUserId == userId && u.IsClosed == false && u.LatestReplyUser.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && u.ReuploadEnum == QCChanllengeReuploadEnum.CRCRequestReupload).Count(),
|
||||||
|
|
||||||
|
//质疑待处理 发送邮件的时候 需要减去ReUploadTobeDealedCount
|
||||||
|
ToBeDealedCount = t.SubjectVisitList.SelectMany(c => c.QCChallengeList)
|
||||||
|
.Where(u => u.CreateUserId == userId && u.IsClosed == false && u.LatestReplyUser.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Count(),
|
||||||
|
});
|
||||||
|
|
||||||
|
var sendStat = await query.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
//当前人
|
||||||
|
if (sendStat != null && (sendStat.ToBeDealedCount > 0 || sendStat.ReUploadTobeDealedCount > 0))
|
||||||
|
{
|
||||||
|
|
||||||
|
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
||||||
|
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
|
||||||
|
|
||||||
|
user.FullName, DateTime.Now, sendStat.ToBeDealedCount - sendStat.ReUploadTobeDealedCount, sendStat.ReUploadTobeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||||
|
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr, false, userId);
|
||||||
|
};
|
||||||
|
|
||||||
|
await OldRecurringEmailHelper.SendTrialEmailAsync(_trialEmailNoticeConfigRepository,
|
||||||
|
_trialRepository,
|
||||||
|
_trialUserRepository,
|
||||||
|
_visitTaskRepository,
|
||||||
|
_trialSiteUserRepository,
|
||||||
|
trialId, EmailBusinessScenario.CRCToQCQuestion, topicAndHtmlFunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 影像质控 发送给QC的
|
||||||
|
/// </summary>
|
||||||
|
public class ImageQCRecurringEventConsumer(IRepository<Trial> _trialRepository,
|
||||||
|
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository,
|
||||||
|
IRepository<TrialUser> _trialUserRepository,
|
||||||
|
IRepository<VisitTask> _visitTaskRepository,
|
||||||
|
IRepository<TrialSiteUser> _trialSiteUserRepository,
|
||||||
|
IOptionsMonitor<SystemEmailSendConfig> _SystemEmailSendConfig) : IConsumer<ImageQCRecurringEvent>
|
||||||
|
{
|
||||||
|
public async Task Consume(ConsumeContext<ImageQCRecurringEvent> context)
|
||||||
|
{
|
||||||
|
var trialId=context.Message.TrialId;
|
||||||
|
|
||||||
|
var isEn_us = false;
|
||||||
|
|
||||||
|
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync();
|
||||||
|
|
||||||
|
//找到 该项目的IQC 用户Id
|
||||||
|
var userList = await _trialUserRepository.Where(t => t.TrialId == trialId).Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.User.FullName }).ToListAsync();
|
||||||
|
|
||||||
|
//判断是否任务可以领取 ,可以的话 发送邮件
|
||||||
|
var userIdList = userList.Select(t => t.UserId).ToList();
|
||||||
|
|
||||||
|
foreach (var user in userList)
|
||||||
|
{
|
||||||
|
var userId = user.UserId;
|
||||||
|
|
||||||
|
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
||||||
|
var query = _trialRepository.Where(t => t.Id == trialId)
|
||||||
|
.Where(t => t.QCProcessEnum != TrialQCProcess.NotAudit)
|
||||||
|
.Select(t => new
|
||||||
|
{
|
||||||
|
//待领取量
|
||||||
|
ToBeClaimedCount = t.SubjectVisitList.Where(u => u.SubmitState == SubmitStateEnum.Submitted && u.CurrentActionUserId == null && (u.PreliminaryAuditUserId == null || (u.PreliminaryAuditUserId != userId && u.ReviewAuditUserId == null))).Count(),
|
||||||
|
|
||||||
|
//待审核通过,统计从已领取到QC提交之间的 已领取 待审核 审核中 (审核完成 领取人就会清理 所以只用查询当前领取人是自己的就好了)
|
||||||
|
ToBeReviewedCount = t.SubjectVisitList.Where(u => u.CurrentActionUserId == userId).Count()
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var sendStat = await query.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
//当前人 有待领取的或者有待审核的才发邮件
|
||||||
|
if (sendStat != null && (sendStat.ToBeClaimedCount > 0 || sendStat.ToBeReviewedCount > 0))
|
||||||
|
{
|
||||||
|
|
||||||
|
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
||||||
|
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
|
||||||
|
user.FullName, DateTime.Now, sendStat.ToBeClaimedCount, sendStat.ToBeReviewedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr, false, userId);
|
||||||
|
};
|
||||||
|
|
||||||
|
await OldRecurringEmailHelper.SendTrialEmailAsync(
|
||||||
|
_trialEmailNoticeConfigRepository,
|
||||||
|
_trialRepository,
|
||||||
|
_trialUserRepository,
|
||||||
|
_visitTaskRepository,
|
||||||
|
_trialSiteUserRepository,
|
||||||
|
trialId, EmailBusinessScenario.QCTask, topicAndHtmlFunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,50 +8,7 @@ using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
public abstract class IRCRecurringSchedule :
|
|
||||||
RecurringSchedule
|
|
||||||
{
|
|
||||||
protected IRCRecurringSchedule()
|
|
||||||
{
|
|
||||||
ScheduleGroup = GetType().Name;
|
|
||||||
|
|
||||||
TimeZoneId = TimeZoneInfo.Local.Id;
|
|
||||||
StartTime = DateTime.Now;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MissedEventPolicy MisfirePolicy { get; protected set; }
|
|
||||||
public string TimeZoneId { get; protected set; }
|
|
||||||
public DateTimeOffset StartTime { get; protected set; }
|
|
||||||
public DateTimeOffset? EndTime { get; protected set; }
|
|
||||||
public string ScheduleId { get; set; }
|
|
||||||
public string ScheduleGroup { get; private set; }
|
|
||||||
public string CronExpression { get; set; }
|
|
||||||
public string Description { get; protected set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// QC 影像质疑待处理
|
|
||||||
/// </summary>
|
|
||||||
public class QCImageQuestionSchedule : IRCRecurringSchedule
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// CRC 影像质疑
|
|
||||||
/// </summary>
|
|
||||||
public class CRCImageQuestionSchedule : IRCRecurringSchedule
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 影像质控
|
|
||||||
/// </summary>
|
|
||||||
public class ImageQCSchedule : IRCRecurringSchedule
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class QCImageQuestionScheduleConsumer : IConsumer<QCImageQuestionSchedule>
|
public class QCImageQuestionScheduleConsumer : IConsumer<QCImageQuestionSchedule>
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
using IRaCIS.Core.Domain.BaseModel;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// QC 影像质疑待处理
|
||||||
|
/// </summary>
|
||||||
|
public class QCImageQuestionRecurringEvent :DomainEvent
|
||||||
|
{
|
||||||
|
public Guid TrialId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CRC 影像质疑
|
||||||
|
/// </summary>
|
||||||
|
public class CRCImageQuestionRecurringEvent : DomainEvent
|
||||||
|
{
|
||||||
|
public Guid TrialId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 影像质控
|
||||||
|
/// </summary>
|
||||||
|
public class ImageQCRecurringEvent : DomainEvent
|
||||||
|
{
|
||||||
|
public Guid TrialId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestEvent
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
using IRaCIS.Core.Application.MassTransit.Command;
|
||||||
|
using MassTransit;
|
||||||
|
using MassTransit.Scheduling;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
|
public abstract class IRCRecurringSchedule :
|
||||||
|
RecurringSchedule
|
||||||
|
{
|
||||||
|
protected IRCRecurringSchedule()
|
||||||
|
{
|
||||||
|
ScheduleGroup = GetType().Name;
|
||||||
|
|
||||||
|
TimeZoneId = TimeZoneInfo.Local.Id;
|
||||||
|
StartTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MissedEventPolicy MisfirePolicy { get; protected set; }
|
||||||
|
public string TimeZoneId { get; protected set; }
|
||||||
|
public DateTimeOffset StartTime { get; protected set; }
|
||||||
|
public DateTimeOffset? EndTime { get; protected set; }
|
||||||
|
public string ScheduleId { get; set; }
|
||||||
|
public string ScheduleGroup { get; private set; }
|
||||||
|
public string CronExpression { get; set; }
|
||||||
|
public string Description { get; protected set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// QC 影像质疑待处理
|
||||||
|
/// </summary>
|
||||||
|
public class QCImageQuestionSchedule : IRCRecurringSchedule
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CRC 影像质疑
|
||||||
|
/// </summary>
|
||||||
|
public class CRCImageQuestionSchedule : IRCRecurringSchedule
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 影像质控
|
||||||
|
/// </summary>
|
||||||
|
public class ImageQCSchedule : IRCRecurringSchedule
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,6 @@ namespace IRaCIS.Core.Application.Service
|
||||||
public interface IEmailSendService
|
public interface IEmailSendService
|
||||||
{
|
{
|
||||||
Task SendEnrollOrPdEmail(Guid visitTaskId, bool? isEnrollment, bool? isPDConfirm);
|
Task SendEnrollOrPdEmail(Guid visitTaskId, bool? isEnrollment, bool? isPDConfirm);
|
||||||
Task SendTrialImageQCTaskEmailAsync(Guid trialId);
|
|
||||||
|
|
||||||
Task SendTrialQCQuestionEmailAsync(Guid trialId);
|
|
||||||
Task SendTrialImageQuestionAsync(Guid trialId);
|
|
||||||
|
|
||||||
Task<(TrialEmailNoticeConfig?, SMTPEmailConfig?)> BuildEmailConfig(Guid trialId, EmailBusinessScenario businessScenario, Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc, Guid? siteId = null, Guid? trialReadingCriterionId = null);
|
Task<(TrialEmailNoticeConfig?, SMTPEmailConfig?)> BuildEmailConfig(Guid trialId, EmailBusinessScenario businessScenario, Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc, Guid? siteId = null, Guid? trialReadingCriterionId = null);
|
||||||
}
|
}
|
||||||
|
@ -101,162 +97,6 @@ namespace IRaCIS.Core.Application.Service
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 影像质控
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="trialId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task SendTrialImageQCTaskEmailAsync(Guid trialId)
|
|
||||||
{
|
|
||||||
var isEn_us = false;
|
|
||||||
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync();
|
|
||||||
|
|
||||||
//找到 该项目的IQC 用户Id
|
|
||||||
var userList = await _trialUserRepository.Where(t => t.TrialId == trialId).Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.User.FullName }).ToListAsync();
|
|
||||||
|
|
||||||
//判断是否任务可以领取 ,可以的话 发送邮件
|
|
||||||
var userIdList = userList.Select(t => t.UserId).ToList();
|
|
||||||
|
|
||||||
foreach (var user in userList)
|
|
||||||
{
|
|
||||||
var userId = user.UserId;
|
|
||||||
|
|
||||||
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
|
||||||
var query = _trialRepository.Where(t => t.Id == trialId)
|
|
||||||
.Where(t => t.QCProcessEnum != TrialQCProcess.NotAudit)
|
|
||||||
.Select(t => new
|
|
||||||
{
|
|
||||||
//待领取量
|
|
||||||
ToBeClaimedCount = t.SubjectVisitList.Where(u => u.SubmitState == SubmitStateEnum.Submitted && u.CurrentActionUserId == null && (u.PreliminaryAuditUserId == null || (u.PreliminaryAuditUserId != userId && u.ReviewAuditUserId == null))).Count(),
|
|
||||||
|
|
||||||
//待审核通过,统计从已领取到QC提交之间的 已领取 待审核 审核中 (审核完成 领取人就会清理 所以只用查询当前领取人是自己的就好了)
|
|
||||||
ToBeReviewedCount = t.SubjectVisitList.Where(u => u.CurrentActionUserId == userId).Count()
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var sendStat = await query.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
//当前人 有待领取的或者有待审核的才发邮件
|
|
||||||
if (sendStat != null && (sendStat.ToBeClaimedCount > 0 || sendStat.ToBeReviewedCount > 0))
|
|
||||||
{
|
|
||||||
|
|
||||||
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
|
||||||
{
|
|
||||||
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
|
||||||
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
|
|
||||||
user.FullName, DateTime.Now, sendStat.ToBeClaimedCount, sendStat.ToBeReviewedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr, false, userId);
|
|
||||||
};
|
|
||||||
|
|
||||||
await SendTrialEmailAsync(trialId, EmailBusinessScenario.QCTask, topicAndHtmlFunc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// QC质疑
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="trialId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task SendTrialQCQuestionEmailAsync(Guid trialId)
|
|
||||||
{
|
|
||||||
var isEn_us = false;
|
|
||||||
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr, t.DeclarationTypeEnumList }).FirstNotNullAsync();
|
|
||||||
|
|
||||||
//找到 该项目的IQC 用户Id
|
|
||||||
var userList = await _trialUserRepository.Where(t => t.TrialId == trialId).Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.User.FullName }).ToListAsync();
|
|
||||||
|
|
||||||
//判断是否任务可以领取 ,可以的话 发送邮件
|
|
||||||
|
|
||||||
foreach (var user in userList)
|
|
||||||
{
|
|
||||||
var userId = user.UserId;
|
|
||||||
|
|
||||||
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
|
||||||
var query = _trialRepository
|
|
||||||
.Where(t => t.Id == trialId)
|
|
||||||
.Select(t => new
|
|
||||||
{
|
|
||||||
ReUploadTobeDealedCount = t.SubjectVisitList.SelectMany(c => c.QCChallengeList)
|
|
||||||
.Where(u => u.CreateUserId == userId && u.IsClosed == false && u.LatestReplyUser.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && u.ReuploadEnum == QCChanllengeReuploadEnum.CRCRequestReupload).Count(),
|
|
||||||
|
|
||||||
//质疑待处理 发送邮件的时候 需要减去ReUploadTobeDealedCount
|
|
||||||
ToBeDealedCount = t.SubjectVisitList.SelectMany(c => c.QCChallengeList)
|
|
||||||
.Where(u => u.CreateUserId == userId && u.IsClosed == false && u.LatestReplyUser.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Count(),
|
|
||||||
});
|
|
||||||
|
|
||||||
var sendStat = await query.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
//当前人
|
|
||||||
if (sendStat != null && (sendStat.ToBeDealedCount > 0 || sendStat.ReUploadTobeDealedCount > 0))
|
|
||||||
{
|
|
||||||
|
|
||||||
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
|
||||||
{
|
|
||||||
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
|
||||||
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
|
|
||||||
|
|
||||||
user.FullName, DateTime.Now, sendStat.ToBeDealedCount - sendStat.ReUploadTobeDealedCount, sendStat.ReUploadTobeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
|
||||||
|
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr, false, userId);
|
|
||||||
};
|
|
||||||
|
|
||||||
await SendTrialEmailAsync(trialId, EmailBusinessScenario.CRCToQCQuestion, topicAndHtmlFunc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 影像质疑
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="trialId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task SendTrialImageQuestionAsync(Guid trialId)
|
|
||||||
{
|
|
||||||
var isEn_us = false;
|
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync();
|
|
||||||
|
|
||||||
//找到 该项目的CRC 用户Id
|
|
||||||
var userList = await _trialUserRepository.Where(t => t.TrialId == trialId).Where(t => t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { t.UserId, t.User.FullName }).ToListAsync();
|
|
||||||
|
|
||||||
//判断是否任务可以领取 ,可以的话 发送邮件
|
|
||||||
|
|
||||||
foreach (var user in userList)
|
|
||||||
{
|
|
||||||
var userId = user.UserId;
|
|
||||||
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
|
||||||
var query = _trialRepository.Where(t => t.Id == trialId)
|
|
||||||
|
|
||||||
.Select(t => new
|
|
||||||
{
|
|
||||||
//质疑待处理
|
|
||||||
ToBeDealedCount = t.SubjectVisitList.Where(t => t.TrialSite.CRCUserList.Any(t => t.UserId == userId)).SelectMany(c => c.QCChallengeList)
|
|
||||||
.Where(u => u.IsClosed == false && (u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IQC || u.LatestReplyUserId == null)).Count(),
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var sendStat = await query.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
//当前人
|
|
||||||
if (sendStat != null && (sendStat.ToBeDealedCount > 0))
|
|
||||||
{
|
|
||||||
|
|
||||||
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
|
||||||
{
|
|
||||||
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
|
||||||
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
|
|
||||||
user.FullName, DateTime.Now, sendStat.ToBeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr, isEn_us, userId);
|
|
||||||
};
|
|
||||||
|
|
||||||
await SendTrialEmailAsync(trialId, EmailBusinessScenario.QCToCRCImageQuestion, topicAndHtmlFunc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
17863
IRaCIS.Core.Infra.EFCore/Migrations/20241017065221_EmailModify.Designer.cs
generated
Normal file
17863
IRaCIS.Core.Infra.EFCore/Migrations/20241017065221_EmailModify.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,40 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Infra.EFCore.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class EmailModify : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "EmailDelaySeconds",
|
||||||
|
table: "TrialEmailNoticeConfig",
|
||||||
|
type: "int",
|
||||||
|
nullable: true,
|
||||||
|
comment: "邮件延时秒数,比如一个事件触发,延迟多少s后才发邮件");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "EmailDelaySeconds",
|
||||||
|
table: "EmailNoticeConfig",
|
||||||
|
type: "int",
|
||||||
|
nullable: true,
|
||||||
|
comment: "邮件延时秒数,比如一个事件触发,延迟多少s后才发邮件");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "EmailDelaySeconds",
|
||||||
|
table: "TrialEmailNoticeConfig");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "EmailDelaySeconds",
|
||||||
|
table: "EmailNoticeConfig");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1817,6 +1817,10 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
|
||||||
.HasColumnType("nvarchar(400)")
|
.HasColumnType("nvarchar(400)")
|
||||||
.HasComment("发送周期");
|
.HasComment("发送周期");
|
||||||
|
|
||||||
|
b.Property<int?>("EmailDelaySeconds")
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasComment("邮件延时秒数,比如一个事件触发,延迟多少s后才发邮件");
|
||||||
|
|
||||||
b.Property<string>("EmailHtmlContent")
|
b.Property<string>("EmailHtmlContent")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
|
@ -11028,6 +11032,10 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
|
||||||
.HasMaxLength(400)
|
.HasMaxLength(400)
|
||||||
.HasColumnType("nvarchar(400)");
|
.HasColumnType("nvarchar(400)");
|
||||||
|
|
||||||
|
b.Property<int?>("EmailDelaySeconds")
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasComment("邮件延时秒数,比如一个事件触发,延迟多少s后才发邮件");
|
||||||
|
|
||||||
b.Property<string>("EmailHtmlContent")
|
b.Property<string>("EmailHtmlContent")
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue