Compare commits

...

382 Commits

Author SHA1 Message Date
hang a47ac76729 复核指派bug修改
continuous-integration/drone/push Build is passing
2025-07-22 15:29:09 +08:00
hang f86a88332c 复核稽查修改016
continuous-integration/drone/push Build is passing
2025-07-18 13:15:23 +08:00
hang f6be5e4355 复核稽查修改015
continuous-integration/drone/push Build is failing
2025-07-18 13:04:58 +08:00
hang 8deeb0290a 复核稽查修改014
continuous-integration/drone/push Build is failing
2025-07-18 12:17:55 +08:00
hang fb6231373b 复核稽查修改013
continuous-integration/drone/push Build is passing
2025-07-18 11:34:13 +08:00
hang a407313a95 复核稽查修改012
continuous-integration/drone/push Build is passing
2025-07-18 09:25:56 +08:00
hang b1806d2eff 复核稽查修改011
continuous-integration/drone/push Build is passing
2025-07-17 17:25:45 +08:00
hang 19351f34e1 复核稽查修改010
continuous-integration/drone/push Build is passing
2025-07-17 17:10:06 +08:00
hang e0f708082d 复核稽查修改009
continuous-integration/drone/push Build is passing
2025-07-17 16:49:20 +08:00
hang 44464a809d 复核稽查修改008
continuous-integration/drone/push Build is passing
2025-07-17 15:26:28 +08:00
hang c7c01b7ba3 复核稽查修改007
continuous-integration/drone/push Build is passing
2025-07-17 15:08:11 +08:00
hang 38b71d5267 复核稽查修改006
continuous-integration/drone/push Build is passing
2025-07-17 14:00:03 +08:00
hang 3950a3453a 复核稽查修改005
continuous-integration/drone/push Build is passing
2025-07-17 13:26:44 +08:00
hang 7aa59da586 复核稽查修改004
continuous-integration/drone/push Build is passing
2025-07-17 11:51:41 +08:00
hang 9b2fbdb13f 复核稽查修改003
continuous-integration/drone/push Build is passing
2025-07-17 11:28:47 +08:00
hang c98b9e1bd4 复核稽查修改002
continuous-integration/drone/push Build is passing
2025-07-17 11:08:02 +08:00
hang 9522461508 复核稽查修改
continuous-integration/drone/push Build is passing
2025-07-17 10:34:15 +08:00
hang 5bb99180b6 修改复核-退回-003
continuous-integration/drone/push Build is passing
2025-07-16 17:59:42 +08:00
hang 62ec1e4955 修改复核查询接口-002
continuous-integration/drone/push Build is passing
2025-07-16 17:34:09 +08:00
hang 58e1af24c9 修改复核查询接口-001
continuous-integration/drone/push Build is passing
2025-07-16 16:30:03 +08:00
hang a7394e7119 指派其他质控-uat-13
continuous-integration/drone/push Build is passing
2025-07-16 10:30:55 +08:00
hang a93d81de0d 指派其他质控-uat-12 2025-07-16 10:30:51 +08:00
hang 6aafe02c6c 指派其他质控-uat-11 2025-07-16 10:30:48 +08:00
hang 1511ef1608 修改QC复核 -二次提交-uat-10 2025-07-16 10:30:43 +08:00
hang 1141439c8e 修改QC复核 -二次提交-uat-9 2025-07-16 10:30:32 +08:00
hang 559663082b 修改QC复核 -二次提交-uat-8 2025-07-16 10:26:30 +08:00
hang 3a298518f9 修改QC复核 -二次提交-uat-7 2025-07-16 10:26:25 +08:00
hang 7f20232401 修改QC复核 -二次提交-uat-6 2025-07-16 10:26:21 +08:00
hang 20b0849b40 修改QC复核 -二次提交-uat-5 2025-07-16 10:26:16 +08:00
hang db951e9195 修改QC复核 -二次提交-uat-4 2025-07-16 10:26:13 +08:00
hang d5d78a99d2 QC复核 -二次提交-uat-3 2025-07-16 10:26:08 +08:00
hang 1609a7a88a QC复核 -二次提交-uat-3 2025-07-16 10:26:03 +08:00
hang 289831fce8 QC复核 -二次提交-uat-2 2025-07-16 10:25:59 +08:00
hang dde058be18 QC 审核提交--迁移uat 2025-07-16 10:25:26 +08:00
hang be8b730ee4 返回文件大小
continuous-integration/drone/push Build is passing
2025-07-14 15:00:36 +08:00
hang 28360861aa 修改subject 随机阅片下载影像重阅bug
continuous-integration/drone/push Build is passing
2025-07-14 13:36:27 +08:00
hang 3e097fa42b uat 序列获取Instance 增加文件大小 2025-07-14 13:32:21 +08:00
hang b8a7cd6ebc 修改非dicom 设置删除,检查上的数量不变更 2025-07-14 13:32:16 +08:00
hang a9aefaf240 修改预览看到阅片影像 修改后受试者随机bug修改 4 2025-07-14 13:32:10 +08:00
hang 266a0c5dd5 修改后受试者随机bug修改 3 2025-07-14 13:32:05 +08:00
hang 54822ae038 修改后受试者随机bug修改 2 2025-07-14 13:31:07 +08:00
hang 05203d6716 受试者随机bug修改 2025-07-14 13:31:00 +08:00
hang 2ce8edde80 uat升级excel 组件测试
continuous-integration/drone/push Build is passing
2025-07-05 13:34:09 +08:00
hang 3c30f5dc14 完全随机跟下载关联
continuous-integration/drone/push Build is passing
2025-07-03 14:54:23 +08:00
hang e4ad1c0653 增加失访可读配置-uat
continuous-integration/drone/push Build is passing
2025-06-25 15:31:59 +08:00
he 84df49ca07 单位修改2
continuous-integration/drone/push Build is passing
2025-06-24 14:58:39 +08:00
he 400edd0b70 修改单位1 2025-06-24 14:58:37 +08:00
he c4add1ecc8 修改单位 2025-06-24 14:58:35 +08:00
he d5879e28d7 修改OCT计算触发逻辑
continuous-integration/drone/push Build is passing
2025-06-24 14:07:31 +08:00
he 37e083face 阅片标准默认值修改 2025-06-24 14:07:28 +08:00
he 290506a060 保存测量值
continuous-integration/drone/push Build is passing
2025-06-24 09:28:27 +08:00
he 1b4bc3690a 稽查保存Ivus和Oct 2025-06-24 09:28:25 +08:00
he 6374781d26 修改阅片期计划的排序
continuous-integration/drone/push Build is failing
2025-06-20 17:33:23 +08:00
he b28013a02f 阅片期计划可以选择基线 2025-06-20 17:32:07 +08:00
he fe429d2bdc 修改受试者内随机
continuous-integration/drone/push Build is passing
2025-06-20 09:37:48 +08:00
he d63af2ed20 修改稽查的单位翻译
continuous-integration/drone/push Build is passing
2025-06-19 17:16:42 +08:00
hang cebf9875b1 禁用人员系统查看文档
continuous-integration/drone/push Build is passing
2025-06-19 10:31:24 +08:00
hang 131681a0b3 完全随机触发系统盲态名称 2025-06-19 10:22:06 +08:00
hang f833adc710 修改有序阅片生成任务bug 2025-06-19 10:21:59 +08:00
hang df80d1e551 修改影像下载bug
continuous-integration/drone/push Build is passing
2025-06-18 10:36:26 +08:00
he 82dc092247 修改阅片期计划生成裁判的逻辑
continuous-integration/drone/push Build is passing
2025-06-17 16:42:47 +08:00
he 44894fcaa9 生成阅片期计划的时候 产生裁判
continuous-integration/drone/push Build is passing
2025-06-17 16:24:00 +08:00
hang 083bebdc03 真实随机阅片导表-1
continuous-integration/drone/push Build is passing
2025-06-17 10:06:41 +08:00
hang e808764dd6 随机阅片排序-5 2025-06-17 10:06:33 +08:00
hang 77d198cb09 随机阅片-NextTask-5 2025-06-17 10:05:55 +08:00
hang 180b02b28c 随机阅片NextTask-4 2025-06-17 10:04:26 +08:00
hang c49a74d742 Merge branch 'Uat_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Uat_IRC_Net8
continuous-integration/drone/push Build is passing
2025-06-17 10:02:34 +08:00
he c76fc8f052 修改阅片期选择访视下拉框的数据
continuous-integration/drone/push Build is running
2025-06-17 10:02:04 +08:00
he 14875dfacc 生成了裁判任务 阅片期不让删除和修改 2025-06-17 10:02:02 +08:00
hang 0a68788c0f 随机阅片序号3 2025-06-17 10:00:39 +08:00
hang b17e5d9ff3 随机阅片序号2 2025-06-17 10:00:34 +08:00
hang 05ce4b7155 随机阅片随机序号 2025-06-17 10:00:28 +08:00
he c8bbb3da48 Merge branch 'Uat_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Uat_IRC_Net8
continuous-integration/drone/push Build is passing
2025-06-16 15:16:20 +08:00
he 65de108ecd 添加阅片期 产生裁判 2025-06-16 15:16:19 +08:00
hang d20c306219 末次访视的展示+ 展示基线选择阅片期
continuous-integration/drone/push Build is passing
2025-06-16 14:50:23 +08:00
hang e69991ae37 修改重置阅片稽查3
continuous-integration/drone/push Build is passing
2025-06-13 09:57:33 +08:00
hang e1e2544ee3 修改阅片重置稽查 2025-06-13 09:57:30 +08:00
hang 318333bae4 修改重置阅片稽查 2025-06-13 09:57:26 +08:00
hang d569de4dfe 确认浏览临床数据
continuous-integration/drone/push Build is passing
2025-06-12 10:52:46 +08:00
hang 05627ff126 肿瘤学稽查修改
continuous-integration/drone/push Build is passing
2025-06-11 10:03:01 +08:00
hang 627618c854 增加进入阅片中稽查 2025-06-11 10:02:57 +08:00
hang 2711c5eb04 稽查 申请PM 重阅,有SPM 判断 2025-06-11 10:00:57 +08:00
hang a6982f79c3 稽查修改,区分标识 2025-06-11 10:00:53 +08:00
hang 2a542949cd 增加稽查标识 2025-06-11 10:00:49 +08:00
he a8ccbce76f 稽查添加
continuous-integration/drone/push Build is passing
2025-06-05 16:46:06 +08:00
he df7cf30aed 测量值可以为空
continuous-integration/drone/push Build is passing
2025-06-04 14:25:57 +08:00
he 0664fbdfb7 验证修改
continuous-integration/drone/push Build is passing
2025-06-04 09:57:08 +08:00
he 0a6ee05417 Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-22 18:01:11 +08:00
hang 8325ccad72 返回系统简称配置
continuous-integration/drone/push Build is passing
2025-05-22 17:40:30 +08:00
hang c27c4ce617 生产删除影像
continuous-integration/drone/push Build is passing
2025-05-22 17:16:35 +08:00
hang b9ecabf915 稽查退回修改
continuous-integration/drone/push Build is passing
2025-05-22 16:36:12 +08:00
hang 4f13a98eff 修改退回
continuous-integration/drone/push Build is passing
2025-05-22 15:45:26 +08:00
hang 2a4e4e66fa 阅片跟踪页面,返回该任务退回原因字
continuous-integration/drone/push Build is passing
2025-05-22 15:23:59 +08:00
hang b72cc5cbc0 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-22 15:19:30 +08:00
hang 04f91560b8 pm设置回退原因 2025-05-22 15:19:27 +08:00
he 87af2edf17 修改领取
continuous-integration/drone/push Build is passing
2025-05-22 13:41:38 +08:00
he 856977612d Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-22 11:07:00 +08:00
he d1ac17cee1 修改退回的时候不让领取 2025-05-22 11:06:59 +08:00
hang 9748e70cdf 申请退回领取限制
continuous-integration/drone/push Build is passing
2025-05-22 11:02:05 +08:00
hang f9bd8c3f5c Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-21 15:16:26 +08:00
hang 5ba0a9bbd0 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-21 15:15:23 +08:00
hang d8ea1e8f94 修改IR 申请,PM 同意发送邮件 2025-05-21 15:15:21 +08:00
he cb83c2a737 Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-21 14:05:30 +08:00
he 806d663cfb Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-21 14:05:17 +08:00
he 7ab1728bc7 修改关键序列排序 2025-05-21 14:05:16 +08:00
he fdd9afd4f0 Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-20 15:46:24 +08:00
hang 32e64eaeff MR MRI 统一,认为是一致的
continuous-integration/drone/push Build is passing
2025-05-20 15:24:20 +08:00
he 7b6efd52bb 修改国际化
continuous-integration/drone/push Build is passing
2025-05-20 14:30:19 +08:00
he 53d26c0445 Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-20 10:55:36 +08:00
he 7467f2ae11 修改
continuous-integration/drone/push Build is passing
2025-05-20 10:28:42 +08:00
he c498ffb21b 修改
continuous-integration/drone/push Build is passing
2025-05-19 17:15:15 +08:00
he 1dadf7b8b6 修改
continuous-integration/drone/push Build is passing
2025-05-19 16:42:33 +08:00
he 793cf1b570 修改
continuous-integration/drone/push Build is passing
2025-05-19 16:22:43 +08:00
he 5a8f564b74 修改
continuous-integration/drone/push Build is passing
2025-05-19 15:58:27 +08:00
he e24c9e6ac2 代码修改
continuous-integration/drone/push Build is passing
2025-05-19 13:54:29 +08:00
he 814f6fd83c 修改发送邮件逻辑
continuous-integration/drone/push Build is passing
2025-05-19 13:47:17 +08:00
he 40d035e7a7 解决合并的冲突
continuous-integration/drone/push Build is passing
2025-05-15 09:33:17 +08:00
he a13807ae5f 合并冲突修改
continuous-integration/drone/push Build is failing
2025-05-15 09:29:41 +08:00
he 9d5aaf1e26 Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is failing
2025-05-15 09:20:22 +08:00
he c347d08e2b 合并
continuous-integration/drone/push Build is failing
2025-05-15 09:14:10 +08:00
hang d34be9b07d 修改获取授权
continuous-integration/drone/push Build is passing
2025-05-09 09:28:53 +08:00
hang e205ea0018 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-09 09:09:11 +08:00
hang ba9d3a30b9 增加老的获取token的接口 2025-05-09 09:09:10 +08:00
he 10cf908775 修改
continuous-integration/drone/push Build is passing
2025-05-08 14:49:57 +08:00
he ee9ad472f0 修改
continuous-integration/drone/push Build is passing
2025-05-08 13:57:16 +08:00
he 1cdfc5f2b5 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-08 13:41:47 +08:00
he 9e9f07e4fd 修改 2025-05-08 13:41:46 +08:00
hang a0294e6bd6 修改触发逻辑
continuous-integration/drone/push Build is passing
2025-05-08 13:16:43 +08:00
hang 55fdf431e0 修改触发邮件逻辑
continuous-integration/drone/push Build is passing
2025-05-08 13:12:39 +08:00
hang 9f1110f91a Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-08 11:44:42 +08:00
hang d76b24bc25 驳回修改 2025-05-08 11:44:35 +08:00
he 0787875b3b 修改
continuous-integration/drone/push Build is passing
2025-05-08 09:50:03 +08:00
he b33aca3230 合并
continuous-integration/drone/push Build is passing
2025-05-07 15:47:09 +08:00
he 0b291e8b21 修改邮件 2025-05-07 15:46:32 +08:00
hang 0cf7e5fddd 增加备注
continuous-integration/drone/push Build is passing
2025-05-07 15:25:56 +08:00
hang 95f708da58 修改邮件配置
continuous-integration/drone/push Build is passing
2025-05-07 14:53:49 +08:00
hang ce47776f19 统一修改邮件配置
continuous-integration/drone/push Build is passing
2025-05-07 14:47:22 +08:00
hang 7fff48b07a 修改邮件配置
continuous-integration/drone/push Build is passing
2025-05-07 14:17:16 +08:00
hang 4688cb388e 修改触发
continuous-integration/drone/push Build is passing
2025-05-07 13:51:32 +08:00
he 21e1a7ab01 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is failing
2025-05-07 13:39:52 +08:00
he 5952af85f1 修改 2025-05-07 13:39:51 +08:00
hang 5e193db33b 修改中心调研邮件
continuous-integration/drone/push Build is running
2025-05-07 13:38:52 +08:00
he 30bcfcc675 修改
continuous-integration/drone/push Build is passing
2025-05-07 13:34:49 +08:00
he 514764ee6e 邮件修改
continuous-integration/drone/push Build is passing
2025-05-07 13:16:35 +08:00
he 685269eebf 修改
continuous-integration/drone/push Build is passing
2025-05-07 10:25:56 +08:00
he 276ad83080 修改
continuous-integration/drone/push Build is passing
2025-05-07 10:21:30 +08:00
he 7a318eae45 代码修改
continuous-integration/drone/push Build is passing
2025-05-06 17:08:04 +08:00
hang 0769f8fe05 增加额外参数
continuous-integration/drone/push Build is passing
2025-05-06 16:35:05 +08:00
hang 03ac25835e 修改增加TrialId
continuous-integration/drone/push Build is running
2025-05-06 16:33:41 +08:00
he 29c3888108 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-06 15:34:22 +08:00
he 91951be107 邮件发送修改 2025-05-06 15:34:20 +08:00
hang 935e46a8f1 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-06 14:19:08 +08:00
hang 1345808019 修改过滤项目参与人员 2025-05-06 14:19:07 +08:00
he 400d0d3336 修改
continuous-integration/drone/push Build is passing
2025-05-06 14:12:57 +08:00
he ca0fd77176 邮件修改
continuous-integration/drone/push Build is passing
2025-05-06 13:57:31 +08:00
he f7cf6d9669 邮件修改
continuous-integration/drone/push Build is passing
2025-05-06 13:39:49 +08:00
he 7f19944005 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-05-06 10:49:43 +08:00
he e8aec5f04c 添加邮件枚举 2025-05-06 10:49:42 +08:00
hang 0afbd24923 增加备注
continuous-integration/drone/push Build is passing
2025-05-06 10:30:48 +08:00
hang 932772f8c8 修改阅片人筛选事件触发
continuous-integration/drone/push Build is passing
2025-05-06 10:26:39 +08:00
he b7a803678c Revert "修改稽查"
continuous-integration/drone/push Build is passing
This reverts commit 5064630d1f.
2025-04-30 09:57:13 +08:00
he e99360bf5b Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-29 17:56:16 +08:00
he 5064630d1f 修改稽查 2025-04-29 17:56:14 +08:00
hang 4034da47f2 测量数据里面带任务Id 需要替换
continuous-integration/drone/push Build is passing
2025-04-28 18:03:18 +08:00
hang 381b1965cf Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-27 16:24:26 +08:00
hang d5e747becd 修改导出 2025-04-27 16:24:24 +08:00
he 758273d362 修改
continuous-integration/drone/push Build is passing
2025-04-27 13:08:22 +08:00
he 1560a0278e 修改
continuous-integration/drone/push Build is passing
2025-04-27 13:05:31 +08:00
he 64c275a91c 修改
continuous-integration/drone/push Build is passing
2025-04-27 10:18:31 +08:00
he 05189b4e5a 修改稽查
continuous-integration/drone/push Build is passing
2025-04-25 17:19:12 +08:00
hang 80aaac997d 没有收件人,默认不发送
continuous-integration/drone/push Build is passing
2025-04-25 10:01:32 +08:00
hang c560921092 修改配置
continuous-integration/drone/push Build is passing
2025-04-25 09:46:41 +08:00
hang 81cd9aa6b7 修改邮件自动发送配置
continuous-integration/drone/push Build is passing
2025-04-25 09:20:06 +08:00
hang 4bfc6dd295 调研表发送邮件修改
continuous-integration/drone/push Build is passing
2025-04-24 17:29:22 +08:00
hang a8464364c1 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-24 17:22:54 +08:00
hang e333368528 修改邮件发送配置 2025-04-24 17:22:52 +08:00
he 58c1c25fc2 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-24 15:53:26 +08:00
he 3045b0ec48 修改 2025-04-24 15:53:22 +08:00
hang 2d50037c03 外部人员 不能看未签名的文档
continuous-integration/drone/push Build is passing
2025-04-24 15:18:55 +08:00
he 6a1cd07951 修改
continuous-integration/drone/push Build is passing
2025-04-24 14:55:50 +08:00
he c7103654e3 修改
continuous-integration/drone/push Build is passing
2025-04-24 10:02:39 +08:00
he 4e03071c4c 修改
continuous-integration/drone/push Build is passing
2025-04-24 09:55:49 +08:00
he bf9e8a6758 修改
continuous-integration/drone/push Build is passing
2025-04-24 09:36:57 +08:00
he 00c6705161 修改
continuous-integration/drone/push Build is passing
2025-04-24 09:31:56 +08:00
he 209d932757 修改
continuous-integration/drone/push Build is passing
2025-04-23 16:25:00 +08:00
he e954ea8538 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-23 13:56:38 +08:00
he f79a8b4cfb 复制修改 2025-04-23 13:56:36 +08:00
hang 8fc01e2509 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-23 13:30:14 +08:00
hang 232e607b8c 增加系统文档导出 2025-04-23 13:30:09 +08:00
he bdeb7c464e 修改
continuous-integration/drone/push Build is passing
2025-04-23 10:55:08 +08:00
he 3668079479 修改
continuous-integration/drone/push Build is passing
2025-04-23 10:48:16 +08:00
he c115e9453b 修改
continuous-integration/drone/push Build is passing
2025-04-23 10:03:24 +08:00
he f157a0f473 登录修改
continuous-integration/drone/push Build is passing
2025-04-23 09:54:00 +08:00
he c2252b4e9f 修改
continuous-integration/drone/push Build is passing
2025-04-22 17:53:55 +08:00
he b0554119f1 修改
continuous-integration/drone/push Build is passing
2025-04-22 13:56:05 +08:00
he 37387692dd 修改
continuous-integration/drone/push Build is passing
2025-04-22 13:20:02 +08:00
he 970c41a064 修改
continuous-integration/drone/push Build is passing
2025-04-22 11:41:24 +08:00
he 67a3fe0f1b 修改
continuous-integration/drone/push Build is running
2025-04-22 11:40:28 +08:00
he 15108156c2 拷贝问题修改
continuous-integration/drone/push Build is passing
2025-04-22 11:33:38 +08:00
he 1a2c51da12 修改
continuous-integration/drone/push Build is passing
2025-04-22 09:40:16 +08:00
he 3d10482da8 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-22 09:29:36 +08:00
he 3abc8787c6 修改 2025-04-22 09:29:32 +08:00
hang df346d31e6 编译错误
continuous-integration/drone/push Build is passing
2025-04-22 09:24:30 +08:00
hang a8babb53f2 修改时区测试
continuous-integration/drone/push Build is passing
2025-04-22 09:20:49 +08:00
hang 3c1cc92e1b Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-21 17:00:28 +08:00
hang 99ee8c4757 增加邮件事件 2025-04-21 17:00:26 +08:00
he fc81d6da22 修改
continuous-integration/drone/push Build is passing
2025-04-21 14:50:58 +08:00
he 47edcbd761 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-21 14:26:24 +08:00
he a499971e91 修改 2025-04-21 14:26:23 +08:00
he afd34c7c9b 修改
continuous-integration/drone/push Build is running
2025-04-21 14:15:21 +08:00
hang 529c646277 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-21 14:15:20 +08:00
hang b8f03153ca 修改反了 2025-04-21 14:15:19 +08:00
he a14df73879 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-21 14:05:51 +08:00
he cb9141c1ce 修改 2025-04-21 14:05:50 +08:00
hang ff2461dafc 查询启用的角色
continuous-integration/drone/push Build is passing
2025-04-21 14:02:39 +08:00
he 779af013e6 修改
continuous-integration/drone/push Build is passing
2025-04-21 13:37:50 +08:00
he 75fb357cc5 修改
continuous-integration/drone/push Build is passing
2025-04-21 13:24:24 +08:00
he 89eb1032cf 修改
continuous-integration/drone/push Build is passing
2025-04-21 11:28:45 +08:00
he eca9c36110 修改
continuous-integration/drone/push Build is passing
2025-04-21 11:09:38 +08:00
he 2430651ed4 修改
continuous-integration/drone/push Build is passing
2025-04-18 14:13:12 +08:00
he 87d658031b 修改
continuous-integration/drone/push Build is passing
2025-04-18 14:10:46 +08:00
he 34b90538ab 修改
continuous-integration/drone/push Build is passing
2025-04-18 13:36:53 +08:00
he d2571d5f79 修改
continuous-integration/drone/push Build is passing
2025-04-18 11:41:47 +08:00
he 1688d7c934 修改
continuous-integration/drone/push Build is passing
2025-04-18 10:24:38 +08:00
he 9ab5dc7d02 修改
continuous-integration/drone/push Build is passing
2025-04-17 17:24:15 +08:00
he 97cdec61be 修改
continuous-integration/drone/push Build is passing
2025-04-17 17:21:23 +08:00
he c0d6eb3203 修改
continuous-integration/drone/push Build is passing
2025-04-17 15:33:44 +08:00
he d125ff6324 x修改
continuous-integration/drone/push Build is passing
2025-04-16 13:28:00 +08:00
he 1b830b386e 修改
continuous-integration/drone/push Build is passing
2025-04-16 11:30:27 +08:00
he ee83909123 修改
continuous-integration/drone/push Build is passing
2025-04-16 10:26:10 +08:00
he 844e27e94e 修改
continuous-integration/drone/push Build is passing
2025-04-15 17:55:16 +08:00
he 6fded9f028 修改
continuous-integration/drone/push Build is passing
2025-04-15 17:23:45 +08:00
he b5103f1940 修改
continuous-integration/drone/push Build is passing
2025-04-15 16:54:38 +08:00
he 8bf54dfc1b 修改
continuous-integration/drone/push Build is running
2025-04-15 16:54:24 +08:00
he 1069292c54 修改
continuous-integration/drone/push Build is passing
2025-04-15 15:39:59 +08:00
he 88c6f574ec 修改
continuous-integration/drone/push Build is passing
2025-04-15 15:36:23 +08:00
he f5f6d3b6ac Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-15 15:16:11 +08:00
he 38f937ea9e 查询修改 2025-04-15 15:16:08 +08:00
hang 2913eb67f4 修改删除的文件统计数字
continuous-integration/drone/push Build is running
2025-04-15 15:14:37 +08:00
hang a0ceec28e7 修改删除统计文件数字
continuous-integration/drone/push Build is passing
2025-04-15 14:54:32 +08:00
hang b77a50caf6 非dicom 删除上传
continuous-integration/drone/push Build is passing
2025-04-15 14:33:03 +08:00
hang 87f2d0e429 非dicom 删除上传
continuous-integration/drone/push Build is passing
2025-04-15 13:27:33 +08:00
hang e17fc6bce9 修改删除
continuous-integration/drone/push Build is passing
2025-04-15 13:20:55 +08:00
hang 0970e2807b 修改非dicom 删除
continuous-integration/drone/push Build is passing
2025-04-15 11:37:00 +08:00
hang a64d26513a Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-15 11:33:24 +08:00
hang 73e80f2571 修改非dicom 删除 2025-04-15 11:33:23 +08:00
hang 770f361d04 修改非dicom 删除
continuous-integration/drone/push Build is passing
2025-04-15 11:05:22 +08:00
hang 7476472071 软删除修改
continuous-integration/drone/push Build is passing
2025-04-15 10:54:28 +08:00
hang 1fff2f7256 修改删除
continuous-integration/drone/push Build is passing
2025-04-15 09:13:56 +08:00
he 1e4044488d Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-14 14:39:42 +08:00
he 1e1822151b 修改 2025-04-14 14:39:40 +08:00
hang c37b6c4c84 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-14 14:23:49 +08:00
hang 8f65b9e60e 修改检查列表查询 2025-04-14 14:23:47 +08:00
he a8a9a09f88 修改
continuous-integration/drone/push Build is passing
2025-04-14 14:11:06 +08:00
he 7526ca2905 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
2025-04-14 14:10:23 +08:00
he fd83c3e7a7 修改 2025-04-14 14:10:23 +08:00
hang a3c575857a Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-14 14:04:53 +08:00
hang c292f6ce44 修改质控删除bug 测试 2025-04-14 14:04:51 +08:00
he 84a7d75174 修改
continuous-integration/drone/push Build is running
2025-04-14 14:03:54 +08:00
he 048afdcc7b Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-14 13:56:54 +08:00
he 06e319cf09 代码修改 2025-04-14 13:56:52 +08:00
hang cee0730e03 升级nuget包
continuous-integration/drone/push Build is passing
2025-04-14 13:54:27 +08:00
he adaa672185 修改
continuous-integration/drone/push Build is passing
2025-04-14 11:20:59 +08:00
he b6b5d3e4c9 代码修改
continuous-integration/drone/push Build is passing
2025-04-14 11:03:01 +08:00
he 6ac057a0c7 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-14 10:28:33 +08:00
he 6607a0ff8f 修改复制 2025-04-14 10:28:30 +08:00
hang 0374551655 修改限制
continuous-integration/drone/push Build is passing
2025-04-11 17:43:07 +08:00
hang be9f0075e3 增加申请限制
continuous-integration/drone/push Build is passing
2025-04-11 16:57:39 +08:00
hang 2cc004746e 增加限制
continuous-integration/drone/push Build is passing
2025-04-11 16:32:00 +08:00
hang b1a7ac1d28 修改映射字段
continuous-integration/drone/push Build is passing
2025-04-11 15:05:18 +08:00
hang 5a31e16c65 修改限制
continuous-integration/drone/push Build is passing
2025-04-11 14:06:53 +08:00
hang 0b56836097 升级普通组件包
continuous-integration/drone/push Build is passing
2025-04-11 13:40:07 +08:00
hang a4a11aaaec 修改查询条件
continuous-integration/drone/push Build is passing
2025-04-11 11:36:29 +08:00
hang ae1b2523b1 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-11 10:21:45 +08:00
hang 87f9d08c74 添加冗余字段 2025-04-11 10:21:42 +08:00
he 81abd9622f 修改病灶验证
continuous-integration/drone/push Build is passing
2025-04-11 10:10:46 +08:00
he faf87f5b86 修改记录
continuous-integration/drone/push Build is passing
2025-04-10 17:30:09 +08:00
he 66dc231850 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-10 14:01:07 +08:00
he 34ff47bc1c 修改 2025-04-10 14:01:06 +08:00
hang 842b7117a2 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-10 11:50:23 +08:00
hang 6543aba53f 文档签署 2025-04-10 11:50:20 +08:00
he 06cee8926e 修改
continuous-integration/drone/push Build is passing
2025-04-10 11:18:36 +08:00
he a35fe11f5b 修改
continuous-integration/drone/push Build is passing
2025-04-10 11:14:00 +08:00
he cc13544968 修改
continuous-integration/drone/push Build is passing
2025-04-10 10:40:05 +08:00
he 19ee511d8d Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-10 10:32:18 +08:00
he 0b47d6ca09 新增文件夹 2025-04-10 10:32:15 +08:00
hang 00193bb4bc 修改统计数字
continuous-integration/drone/push Build is passing
2025-04-10 10:05:15 +08:00
hang 4379fcbdb3 增加字段
continuous-integration/drone/push Build is passing
2025-04-10 09:49:38 +08:00
hang 8464625bbf 修改统计数字
continuous-integration/drone/push Build is passing
2025-04-10 09:31:36 +08:00
hang e88f949cb7 增加新的提示
continuous-integration/drone/push Build is passing
2025-04-09 17:46:23 +08:00
hang 4fdb0737fc 修改查询条件
continuous-integration/drone/push Build is passing
2025-04-09 17:07:18 +08:00
hang 04be8cf642 修改访视查询下拉框
continuous-integration/drone/push Build is passing
2025-04-09 17:03:17 +08:00
hang 089ecbf144 增加访视提交时间
continuous-integration/drone/push Build is passing
2025-04-09 16:48:22 +08:00
hang b95e97a5df 增加用户列表接口
continuous-integration/drone/push Build is passing
2025-04-09 16:45:52 +08:00
hang e84710c4aa 修改查询
continuous-integration/drone/push Build is passing
2025-04-09 15:20:40 +08:00
hang f549d1fca9 删除部分迁移文件
continuous-integration/drone/push Build is passing
2025-04-09 15:15:26 +08:00
hang 2c72dc000f Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-09 15:09:54 +08:00
hang 2ceddc1340 修改统计 2025-04-09 15:09:53 +08:00
he f118c48d0e Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-09 15:03:58 +08:00
he a3a1236d5b 修改 2025-04-09 15:03:57 +08:00
hang a7848727ee Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-09 11:27:21 +08:00
hang 5787c36687 修改验证 2025-04-09 11:27:17 +08:00
he 89d009fcbf Revert "修改"
continuous-integration/drone/push Build is passing
This reverts commit 7d65cf5051.
2025-04-09 11:00:45 +08:00
he 4e66ea43d7 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-09 10:59:42 +08:00
he 68d69181a9 修改 2025-04-09 10:59:39 +08:00
he 7d65cf5051 修改
continuous-integration/drone/push Build is passing
2025-04-09 09:45:49 +08:00
hang b879b3f2c7 国际化修改
continuous-integration/drone/push Build is passing
2025-04-08 15:20:09 +08:00
hang 4fd77ce70d 影像回退逻辑增加
continuous-integration/drone/push Build is passing
2025-04-08 14:50:45 +08:00
he e74427c45c 解决冲突
continuous-integration/drone/push Build is passing
2025-04-08 11:05:31 +08:00
he e8825c7efa 修改查询 2025-04-08 11:04:52 +08:00
he 8213c6d10f 测试肿瘤学评估
continuous-integration/drone/push Build is passing
2025-04-08 09:31:36 +08:00
he b79b4567b4 修改稽查文档
continuous-integration/drone/push Build is passing
2025-04-07 17:42:58 +08:00
he 8c5b759a92 同步修改
continuous-integration/drone/push Build is passing
2025-04-07 17:25:37 +08:00
he ab1e33a799 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-07 16:29:32 +08:00
he 824b65d5ee 同步系统标准修改 2025-04-07 16:29:31 +08:00
hang c68004b804 维护用户登录区域
continuous-integration/drone/push Build is passing
2025-04-07 15:45:43 +08:00
hang d5cd8dc338 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-07 15:24:08 +08:00
hang 1fef5509d1 修改解析IP区域位置的库 以及异地登录判断 2025-04-07 15:24:05 +08:00
he 06d12ce709 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-07 15:12:49 +08:00
he ad7ac80444 复制稽查文档 2025-04-07 15:11:49 +08:00
hang 29d0ebdb7c 账户日志的操作类型支持多选
continuous-integration/drone/push Build is passing
2025-04-07 14:31:06 +08:00
hang 9bcaa07c1a 测试新的解析IP的库
continuous-integration/drone/push Build is passing
2025-04-07 14:08:30 +08:00
he bf5f56f5f2 修改查询
continuous-integration/drone/push Build is passing
2025-04-07 11:06:11 +08:00
he c1c2b59641 修改
continuous-integration/drone/push Build is passing
2025-04-03 17:31:51 +08:00
he 33820c2acb 修改
continuous-integration/drone/push Build is passing
2025-04-03 17:26:19 +08:00
he 9814f63246 修改
continuous-integration/drone/push Build is passing
2025-04-03 16:27:06 +08:00
he 5e6c018199 修改
continuous-integration/drone/push Build is passing
2025-04-03 16:10:11 +08:00
he b24751287c 修改
continuous-integration/drone/push Build is running
2025-04-03 16:07:48 +08:00
he 759cc6c1be 修改
continuous-integration/drone/push Build is passing
2025-04-03 15:29:22 +08:00
he 1a929ce2ca 修改
continuous-integration/drone/push Build is passing
2025-04-03 15:10:04 +08:00
he 1e4571a814 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-04-03 14:31:25 +08:00
he 848670d128 修改 2025-04-03 14:31:23 +08:00
hang 6d9b5fdb2d 测试项目降级为8版本
continuous-integration/drone/push Build is passing
2025-04-03 14:26:11 +08:00
hang ab00d64725 移除之前的废弃包换用微软新包
continuous-integration/drone/push Build is running
2025-04-03 14:23:42 +08:00
hang 5e36054ee9 删除logdashboard 升级下fo-dicom 常见包
continuous-integration/drone/push Build is passing
2025-04-03 14:17:24 +08:00
hang 2b11042f35 升级fo-dicom
continuous-integration/drone/push Build is passing
2025-04-03 14:04:28 +08:00
hang e9e5075c1c 验证环境生成缩略图测试ok提交
continuous-integration/drone/push Build is passing
2025-04-03 13:56:54 +08:00
hang 628e0ad034 修改异地登录bug 设置最后一次登录的iP
continuous-integration/drone/push Build is passing
2025-04-03 13:55:04 +08:00
hang 2f3f639918 修改异地登录ip逻辑 2025-04-03 13:55:00 +08:00
hang 87caf24dd1 验证环境生成缩略图测试ok提交
continuous-integration/drone/push Build is passing
2025-04-03 13:49:34 +08:00
hang 9149dd6cf6 Merge branch 'Uat_IRC_Net8' into Test_IRC_Net8 2025-04-03 11:30:53 +08:00
hang 24bfb4920c IQC回退到CRC 上传修改
continuous-integration/drone/push Build is passing
2025-04-03 11:29:13 +08:00
he 553ad4760c 修改
continuous-integration/drone/push Build is passing
2025-04-02 15:55:12 +08:00
he 5acd56689b 修改
continuous-integration/drone/push Build is running
2025-04-02 15:52:07 +08:00
hang 5f0643d4d4 修改swagger 展示 2025-04-02 14:03:36 +08:00
he 17e4ed38be 修改
continuous-integration/drone/push Build is passing
2025-04-02 13:46:08 +08:00
he c49f16b055 修改
continuous-integration/drone/push Build is passing
2025-04-02 13:44:36 +08:00
he aa42d64cac 修改
continuous-integration/drone/push Build is passing
2025-04-01 18:05:58 +08:00
he 8f0ef86ab9 修改
continuous-integration/drone/push Build is passing
2025-04-01 17:55:48 +08:00
he c17b2f6bac 修改
continuous-integration/drone/push Build is running
2025-04-01 17:53:13 +08:00
he be498f2329 修改
continuous-integration/drone/push Build is passing
2025-04-01 16:54:23 +08:00
he fea3d8d415 修改
continuous-integration/drone/push Build is passing
2025-04-01 16:39:28 +08:00
he bffc8626c7 修改
continuous-integration/drone/push Build is passing
2025-04-01 16:31:47 +08:00
he 1efe1228ac 修改
continuous-integration/drone/push Build is passing
2025-04-01 16:21:50 +08:00
he f900b811c7 修改
continuous-integration/drone/push Build is passing
2025-04-01 16:18:10 +08:00
he a5f7e03f6c 修改
continuous-integration/drone/push Build is passing
2025-04-01 16:05:13 +08:00
he 7aba4adc14 修改
continuous-integration/drone/push Build is passing
2025-04-01 15:52:37 +08:00
he 12c8c641ea 查询修改
continuous-integration/drone/push Build is passing
2025-04-01 15:09:47 +08:00
he 977adf3153 修改项目下拉查询
continuous-integration/drone/push Build is passing
2025-04-01 13:10:30 +08:00
he 409b76df26 修改
continuous-integration/drone/push Build is passing
2025-03-31 17:48:30 +08:00
he 2d9ebe7094 修改
continuous-integration/drone/push Build is passing
2025-03-31 15:26:13 +08:00
he 71e797cf7d 修改
continuous-integration/drone/push Build is passing
2025-03-31 14:06:17 +08:00
he f781027388 修改 2025-03-31 14:01:29 +08:00
he 56e316e6a1 修改
continuous-integration/drone/push Build is passing
2025-03-31 11:51:19 +08:00
he edef3e1990 Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing
2025-03-31 11:09:24 +08:00
he d6d0965467 整体肿瘤评估 计算修改 2025-03-31 11:09:22 +08:00
hang 62f888710c 修改阅片人统计查询
continuous-integration/drone/push Build is passing
2025-03-28 14:55:59 +08:00
he 58e8c2392f 添加MRecisthhc
continuous-integration/drone/push Build is passing
2025-03-28 11:12:09 +08:00
he 0e1310324d 修改
continuous-integration/drone/push Build is passing
2025-03-28 09:48:46 +08:00
he efcda61104 修改
continuous-integration/drone/push Build is passing
2025-03-27 17:11:00 +08:00
he 97133a5554 文档修改
continuous-integration/drone/push Build is passing
2025-03-27 16:29:55 +08:00
he 577ed42f97 修改文件路径
continuous-integration/drone/push Build is passing
2025-03-27 16:19:08 +08:00
he 8f704c4617 修改
continuous-integration/drone/push Build is passing
2025-03-27 16:03:12 +08:00
he a03d7f55c7 稽查文档
continuous-integration/drone/push Build is passing
2025-03-27 15:48:33 +08:00
he 2bbc101f95 修改
continuous-integration/drone/push Build is passing
2025-03-27 11:17:59 +08:00
he 2b11e9165f 修改
continuous-integration/drone/push Build is passing
2025-03-27 11:08:06 +08:00
he b25dec68cb 修改项目下拉列表
continuous-integration/drone/push Build is passing
2025-03-27 10:55:45 +08:00
hang 2f57238f66 修改swagger 展示
continuous-integration/drone/push Build is passing
2025-03-26 14:22:26 +08:00
hang 8239061a84 修改异地登录bug 设置最后一次登录的iP
continuous-integration/drone/push Build is passing
2025-03-26 11:11:34 +08:00
hang a43ebc016a 修改异地登录ip逻辑
continuous-integration/drone/push Build is passing
2025-03-25 17:49:13 +08:00
hang dd6419dc44 撤回修改
continuous-integration/drone/push Build is passing
2025-03-24 17:13:21 +08:00
hang 54a9cfbb8e 修改refer
continuous-integration/drone/push Build is running
2025-03-24 17:12:04 +08:00
302 changed files with 185852 additions and 1299259 deletions
+11 -11
View File
@@ -7,28 +7,28 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.4" />
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.5" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
<PackageReference Include="AWSSDK.S3" Version="3.7.405" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.400.36" />
<PackageReference Include="DistributedLock.Core" Version="1.0.7" />
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.5" />
<PackageReference Include="fo-dicom" Version="5.1.3" />
<PackageReference Include="fo-dicom.Codecs" Version="5.15.1" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.3" />
<PackageReference Include="AWSSDK.S3" Version="3.7.416.8" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.401.81" />
<PackageReference Include="DistributedLock.Core" Version="1.0.8" />
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.6" />
<PackageReference Include="fo-dicom" Version="5.2.1" />
<PackageReference Include="fo-dicom.Codecs" Version="5.16.1" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="Minio" Version="6.0.3" />
<PackageReference Include="Minio" Version="6.0.4" />
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.1.2" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.9.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
</ItemGroup>
<ItemGroup>
+66 -1
View File
@@ -1,4 +1,5 @@
using Amazon.Auth.AccessControlPolicy;
using AlibabaCloud.SDK.Sts20150401;
using Amazon.Auth.AccessControlPolicy;
using Amazon.SecurityToken;
using AutoMapper;
using Azure.Core;
@@ -21,6 +22,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Org.BouncyCastle.Tls;
using RestSharp;
using RestSharp.Authenticators;
using System;
@@ -182,6 +184,69 @@ namespace IRaCIS.Api.Controllers
}
#region
[HttpGet("user/GenerateSTS")]
public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options)
{
var ossOptions = options.CurrentValue.AliyunOSS;
var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config()
{
AccessKeyId = ossOptions.AccessKeyId,
AccessKeySecret = ossOptions.AccessKeySecret,
Endpoint = "sts.cn-hangzhou.aliyuncs.com"
});
var assumeRoleRequest = new AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest();
// 将<YOUR_ROLE_SESSION_NAME>设置为自定义的会话名称,例如oss-role-session。
assumeRoleRequest.RoleSessionName = $"session-name-{NewId.NextGuid()}";
// 将<YOUR_ROLE_ARN>替换为拥有上传文件到指定OSS Bucket权限的RAM角色的ARN。
assumeRoleRequest.RoleArn = ossOptions.RoleArn;
//assumeRoleRequest.RoleArn = "acs:ram::1899121822495495:role/webdirect";
assumeRoleRequest.DurationSeconds = ossOptions.DurationSeconds;
var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
var response = client.AssumeRoleWithOptions(assumeRoleRequest, runtime);
var credentials = response.Body.Credentials;
var tempToken = new AliyunOSSTempToken()
{
AccessKeyId = credentials.AccessKeyId,
AccessKeySecret = credentials.AccessKeySecret,
//转为服务器时区,最后统一转为客户端时区
Expiration = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse(credentials.Expiration), TimeZoneInfo.Local),
SecurityToken = credentials.SecurityToken,
Region = ossOptions.Region,
BucketName = ossOptions.BucketName,
EndPoint = ossOptions.EndPoint,
ViewEndpoint = ossOptions.ViewEndpoint,
PreviewEndpoint = ossOptions.PreviewEndpoint
};
// 返回STS令牌信息给前端
var stsToken = new
{
AccessKeyId = credentials.AccessKeyId,
AccessKeySecret = credentials.AccessKeySecret,
SecurityToken = credentials.SecurityToken,
Expiration = credentials.Expiration,
Region = ossOptions.Region,
BucketName = ossOptions.BucketName,
ViewEndpoint = ossOptions.ViewEndpoint,
};
return ResponseOutput.Ok(stsToken);
}
#endregion
[HttpGet("User/UserRedirect")]
@@ -52,7 +52,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitOncologyReadingInfo")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> SetOncologyReadingInfo(DataInspectionDto<SubmitOncologyReadingInfoInDto> opt)
@@ -69,7 +69,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitDicomVisitTask")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> SubmitDicomVisitTask(DataInspectionDto<SubmitDicomVisitTaskInDto> opt)
@@ -88,7 +88,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitGlobalReadingInfo")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> SubmitGlobalReadingInfo(DataInspectionDto<SubmitGlobalReadingInfoInDto> opt)
@@ -107,7 +107,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/TrialReadingInfoSign")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> TrialReadingInfoSign(DataInspectionDto<TrialReadingInfoSignInDto> opt)
@@ -126,7 +126,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingMedicalReview/FinishMedicalReview")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> FinishMedicalReview(DataInspectionDto<FinishMedicalReviewInDto> opt)
@@ -143,7 +143,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingMedicineQuestion/ConfirmReadingMedicineQuestion")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> ConfirmReadingMedicineQuestion(DataInspectionDto<ConfirmReadingMedicineQuestionInDto> opt)
@@ -161,7 +161,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitVisitTaskQuestions")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> SubmitVisitTaskQuestions(DataInspectionDto<SubmitVisitTaskQuestionsInDto> opt)
@@ -179,7 +179,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/CRCSignClinicalData")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> CRCSignClinicalData(DataInspectionDto<CRCSignClinicalDataInDto> opt)
@@ -197,7 +197,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/CRCConfirmClinical")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> CRCConfirmClinical(DataInspectionDto<CRCConfirmClinicalInDto> opt)
@@ -214,7 +214,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/CRCCancelConfirmClinical")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> CRCCancelConfirmClinical(DataInspectionDto<CRCCancelConfirmClinicalInDto> opt)
@@ -232,7 +232,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/PMConfirmClinical")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> PMConfirmClinical(DataInspectionDto<CRCConfirmClinicalInDto> opt)
@@ -250,7 +250,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingClinicalData/SignConsistencyAnalysisReadingClinicalData")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(DataInspectionDto<SignConsistencyAnalysisReadingClinicalDataInDto> opt)
@@ -267,7 +267,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/SubmitClinicalFormAndSign")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> SubmitClinicalFormAndSign(DataInspectionDto<SubmitClinicalFormInDto> opt)
@@ -284,7 +284,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitJudgeVisitTaskResult")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> SubmitJudgeVisitTaskResult(DataInspectionDto<SaveJudgeVisitTaskResult> opt)
@@ -303,7 +303,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialBasicInfoConfirm")]
[UnitOfWork]
[TrialGlobalLimit( "BeforeOngoingCantOpt" )]
[TrialGlobalLimit("BeforeOngoingCantOpt")]
public async Task<IResponseOutput> ConfigTrialBasicInfoConfirm(DataInspectionDto<BasicTrialConfig> opt)
{
@@ -345,7 +345,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialUrgentInfoConfirm")]
[UnitOfWork]
[TrialGlobalLimit( "BeforeOngoingCantOpt" )]
[TrialGlobalLimit("BeforeOngoingCantOpt")]
public async Task<IResponseOutput> ConfigTrialUrgentInfoConfirm(DataInspectionDto<TrialUrgentConfig> opt)
{
opt.Data.IsTrialUrgentConfirmed = true;
@@ -358,7 +358,7 @@ namespace IRaCIS.Core.API.Controllers
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialPACSInfoConfirm")]
[UnitOfWork]
[TrialGlobalLimit( "BeforeOngoingCantOpt" )]
[TrialGlobalLimit("BeforeOngoingCantOpt")]
public async Task<IResponseOutput> ConfigTrialPACSInfoConfirm(DataInspectionDto<TrialPACSConfig> opt)
{
opt.Data.IsTrialPACSConfirmed = true;
@@ -374,7 +374,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/TrialConfigSignatureConfirm")]
[UnitOfWork]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> TrialConfigSignatureConfirm(DataInspectionDto<SignConfirmDTO> opt)
{
@@ -391,7 +391,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns>
[HttpPost, Route("Inspection/ReadingCriterion/ResetAndAsyncCriterion")]
[UnitOfWork]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> ResetAndAsyncCriterion(DataInspectionDto<ResetAndAsyncCriterionInDto> opt)
{
@@ -409,7 +409,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/QCOperation/CRCRequestToQC")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> CRCRequestToQC(DataInspectionDto<CRCRequestToQCCommand> opt)
{
@@ -424,21 +424,31 @@ namespace IRaCIS.Core.API.Controllers
/// 设置QC 通过或者不通过 7:QC failed 8QC passed
/// </summary>
[HttpPost, Route("Inspection/QCOperation/QCPassedOrFailed")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> QCPassedOrFailed(DataInspectionDto<QCPassedOrFailedDto> opt)
{
var singid = await _inspectionService.RecordSing(opt.SignInfo);
var result = await _qCOperationService.QCPassedOrFailed(opt.Data.trialId, opt.Data.subjectVisitId, opt.Data.auditState);
await _inspectionService.CompletedSign(singid, result);
return result;
if (opt.Data.IsSecondPass != null)
{
var result = await _qCOperationService.QCSecondReviewPassedOrFailed(opt.Data.trialId, opt.Data.subjectVisitId, (bool)opt.Data.IsSecondPass);
await _inspectionService.CompletedSign(singid, result);
return result;
}
else
{
var result = await _qCOperationService.QCPassedOrFailed(opt.Data.trialId, opt.Data.subjectVisitId, opt.Data.auditState);
await _inspectionService.CompletedSign(singid, result);
return result;
}
}
/// <summary>
/// 一致性核查 回退 对话记录不清除 只允许PM回退
/// </summary>
[HttpPost, Route("Inspection/QCOperation/CheckBack")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> CheckBack(DataInspectionDto<IDDto> opt)
{
@@ -455,7 +465,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/ReadClinicalData/ReadClinicalDataSign")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> ReadClinicalDataSign(DataInspectionDto<ReadingClinicalDataSignIndto> opt)
{
@@ -470,7 +480,7 @@ namespace IRaCIS.Core.API.Controllers
/// CRC 设置已经重传完成
/// </summary>
[HttpPost, Route("Inspection/QCOperation/SetReuploadFinished")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> SetReuploadFinished(DataInspectionDto<CRCReuploadFinishedCommand> opt)
{
@@ -486,7 +496,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param>
/// <returns></returns>
[HttpPost, Route("Inspection/TrialConfig/updateTrialState")]
[TrialGlobalLimit( "BeforeOngoingCantOpt")]
[TrialGlobalLimit("BeforeOngoingCantOpt")]
[UnitOfWork]
public async Task<IResponseOutput> UpdateTrialState(DataInspectionDto<UpdateTrialStateDto> opt)
{
@@ -502,7 +512,7 @@ namespace IRaCIS.Core.API.Controllers
/// </summary>
/// <returns></returns>
[HttpPost, Route("Inspection/TrialDocument/userConfirm")]
[TrialGlobalLimit( "BeforeOngoingCantOpt", "SignSystemDocNoTrialId", "AfterStopCannNotOpt" )]
[TrialGlobalLimit("BeforeOngoingCantOpt", "SignSystemDocNoTrialId", "AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> UserConfirm(DataInspectionDto<UserConfirmCommand> opt)
{
@@ -519,10 +529,10 @@ namespace IRaCIS.Core.API.Controllers
/// </summary>
/// <returns></returns>
[HttpPost, Route("Inspection/VisitTask/ConfirmReReading")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork]
public async Task<IResponseOutput> ConfirmReReading(DataInspectionDto<ConfirmReReadingCommand> opt, [FromServices] IVisitTaskService _visitTaskService)
public async Task<IResponseOutput> ConfirmReReading(DataInspectionDto<ConfirmReReadingCommand> opt, [FromServices] IVisitTaskService _visitTaskService)
{
var singId = await _inspectionService.RecordSing(opt.SignInfo);
var result = await _visitTaskService.ConfirmReReading(opt.Data);
@@ -527,7 +527,7 @@ namespace IRaCIS.Core.API.Controllers
}
var uploadFinishedTime = DateTime.Now;
var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync((t => t.Id == noneDicomStudyId));
var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync(t => t.Id == noneDicomStudyId,true);
noneDicomStudy.FileCount = noneDicomStudy.FileCount + (incommand.VisitTaskId != null ? 0 : incommand.UploadedFileList.Count);
@@ -20,6 +20,8 @@ namespace IRaCIS.Core.API.HostService;
public class HangfireHostService(IRecurringMessageScheduler _recurringMessageScheduler,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IMediator _mediator,
ILogger<HangfireHostService> _logger) : IHostedService
{
@@ -55,6 +57,20 @@ public class HangfireHostService(IRecurringMessageScheduler _recurringMessageSch
}
// 系统邮件定时任务
var systemTaskInfoList = await _emailNoticeConfigrepository.Where(t => t.EmailCron != string.Empty && t.IsAutoSend)
.Select(t => new { t.Id, t.Code, t.EmailCron, t.BusinessScenarioEnum, })
.ToListAsync();
foreach (var task in systemTaskInfoList)
{
//利用主键作为任务Id
var jobId = $"{task.Id}_({task.BusinessScenarioEnum})";
HangfireJobHelper.AddOrUpdateSystemCronJob(jobId, task.BusinessScenarioEnum, task.EmailCron);
}
//await _recurringMessageScheduler.ScheduleRecurringPublish(new QCImageQuestionSchedule() { CronExpression = "0/3 * * * * ? " }, new MasstransiTestCommand { value = "message at " + DateTime.Now.ToString() });
+12 -7
View File
@@ -69,24 +69,23 @@
<ItemGroup>
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.14" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.10">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="ConfigMapFileProvider" Version="2.0.1" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.14" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.18" />
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
<PackageReference Include="Hangfire.InMemory" Version="1.0.0" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.14" />
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
<PackageReference Include="LogDashboard" Version="1.4.8" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.18" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.Email" Version="4.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.9.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="8.1.1" />
</ItemGroup>
<ItemGroup>
@@ -114,6 +113,12 @@
</Content>
</ItemGroup>
<ItemGroup>
<None Update="Resources\GeoLite2-City.mmdb">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties properties_4launchsettings_1json__JsonSchema="" />
+3 -4
View File
@@ -7,7 +7,6 @@ using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.Service.BusinessFilter;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure.Extention;
using LogDashboard;
using MassTransit;
using MassTransit.NewIdProviders;
using Microsoft.AspNetCore.Builder;
@@ -39,7 +38,7 @@ var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
var openSwaggerStr = config["ASPNETCORE_OpenSwagger"];
var isOpenSwagger= openSwaggerStr == null&& openSwaggerStr?.ToLower()=="true";
var isOpenSwagger= openSwaggerStr == null|| openSwaggerStr?.ToLower()=="true";
if (string.IsNullOrWhiteSpace(enviromentName))
@@ -136,7 +135,7 @@ builder.Services.AddFusionCache();
builder.Services.AddhangfireSetup(_configuration);
//Serilog 日志可视化 LogDashboard日志
builder.Services.AddLogDashboardSetup();
//builder.Services.AddLogDashboardSetup();
//Dicom影像渲染图片 跨平台
builder.Services.AddDicomSetup();
@@ -221,7 +220,7 @@ app.UseResponseCompression();
app.UseStaticFiles();
//LogDashboard
app.UseLogDashboard("/LogDashboard");
//app.UseLogDashboard("/LogDashboard");
//hangfire
app.UseHangfireConfig(env);
Binary file not shown.

After

Width:  |  Height:  |  Size: 73 MiB

@@ -1,15 +1,15 @@
using LogDashboard;
using LogDashboard.Authorization;
//using LogDashboard;
//using LogDashboard.Authorization;
namespace IRaCIS.Core.API.Filter
{
//namespace IRaCIS.Core.API.Filter
//{
public class LogDashBoardAuthFilter : ILogDashboardAuthorizationFilter
{
//在此可以利用 本系统的UerTypeEnum 判断
public bool Authorization(LogDashboardContext context)
{
return context.HttpContext.User.Identity.IsAuthenticated;
}
}
}
// public class LogDashBoardAuthFilter : ILogDashboardAuthorizationFilter
// {
// //在此可以利用 本系统的UerTypeEnum 判断
// public bool Authorization(LogDashboardContext context)
// {
// return context.HttpContext.User.Identity.IsAuthenticated;
// }
// }
//}
@@ -1,25 +1,25 @@
using LogDashboard;
using Microsoft.Extensions.DependencyInjection;
//using LogDashboard;
//using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.API
{
public static class LogDashboardSetup
{
public static void AddLogDashboardSetup(this IServiceCollection services)
{
//IIS 配置虚拟路径部署,会出现IIS静态文件404
services.AddLogDashboard(opt =>
{
//opt.PathMatch = "/api/LogDashboard";
opt.PathMatch = "/LogDashboard";
//namespace IRaCIS.Core.API
//{
// public static class LogDashboardSetup
// {
// public static void AddLogDashboardSetup(this IServiceCollection services)
// {
// //IIS 配置虚拟路径部署,会出现IIS静态文件404
// services.AddLogDashboard(opt =>
// {
// //opt.PathMatch = "/api/LogDashboard";
// opt.PathMatch = "/LogDashboard";
//opt.AddAuthorizationFilter(new LogDashboardBasicAuthFilter("admin", "zhizhun2018"));
// //opt.AddAuthorizationFilter(new LogDashboardBasicAuthFilter("admin", "zhizhun2018"));
//opt.AddAuthorizationFilter(new LogDashBoardAuthFilter());
// //opt.AddAuthorizationFilter(new LogDashBoardAuthFilter());
});
// });
}
}
}
// }
// }
//}
@@ -16,30 +16,30 @@ namespace IRaCIS.Core.API;
public enum SwaggerVersion
{
[Description("文件记录")]
[Description("文件记录(FileRecord)")]
FileRecord = -1,
[Description("医生模块")]
[Description("医生模块(Reviewer)")]
Reviewer = 1,
[Description("项目模块")]
[Description("项目模块(Trial)")]
Trial = 2,
[Description("入组模块")]
[Description("入组模块(Enroll)")]
Enroll = 3,
[Description("工作量模块")]
[Description("工作量模块(Workload)")]
Workload = 4,
[Description("通用信息获取")]
[Description("通用信息获取(Common)")]
Common = 5,
[Description("机构信息模块")]
[Description("机构信息模块(Institution)")]
Institution = 6,
[Description("统计模块")]
[Description("统计模块(DashboardStatistics)")]
DashboardStatistics = 7,
[Description("财务模块")]
[Description("财务模块(Financial)")]
Financial = 8,
[Description("管理模块")]
[Description("管理模块(Management)")]
Management =9,
[Description("影像模块")]
[Description("影像模块(Image)")]
Image =10,
[Description("读片模块")]
[Description("读片模块(Reading)")]
Reading =11
};
+6 -3
View File
@@ -7,8 +7,8 @@
}
},
"ConnectionStrings": {
"RemoteNew": "Server=47.117.164.182,1434;Database=Event_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=47.117.164.182,1434;Database=Event_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
"RemoteNew": "Server=101.132.253.119,1435;Database=irc_Prpd_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=101.132.253.119,1435;Database=irc_Hangfire_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"ObjectStoreService": {
"ObjectStoreUse": "AliyunOSS",
@@ -52,7 +52,10 @@
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90
"ChangePassWordDays": 90,
// 模板类型 1 Elevate 2 Extensive
"TemplateType": 2
},
"SystemEmailSendConfig": {
"Port": 465,
+3 -1
View File
@@ -51,7 +51,9 @@
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90
"ChangePassWordDays": 90,
// 模板类型 1 Elevate 2 Extensive
"TemplateType": 2
},
"SystemEmailSendConfig": {
@@ -69,6 +69,8 @@
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 模板类型 1 Elevate 2 Extensive
"TemplateType": 2,
"OpenTrialRelationDelete": true,
+2 -1
View File
@@ -54,7 +54,8 @@
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 模板类型 1 Elevate 2 Extensive
"TemplateType": 1,
"OpenTrialRelationDelete": false
+2 -1
View File
@@ -64,7 +64,8 @@
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90,
// 模板类型 1 Elevate 2 Extensive
"TemplateType": 1,
"OpenLoginMFA": true
},
+3 -1
View File
@@ -63,7 +63,9 @@
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90
"ChangePassWordDays": 90,
// 模板类型 1 Elevate 2 Extensive
"TemplateType": 1
},
"SystemEmailSendConfig": {
+3 -1
View File
@@ -70,7 +70,9 @@
"ReadingRestTimeMin": 10,
"IsNeedChangePassWord": true,
"ChangePassWordDays": 90
"ChangePassWordDays": 90,
// 模板类型 1 Elevate 2 Extensive
"TemplateType": 2
},
"SystemEmailSendConfig": {
@@ -34,6 +34,8 @@ public class ServiceVerifyConfigOption
[Description("修改密码的天数")]
public int ChangePassWordDays { get; set; }
public SysTemplateType TemplateType { get; set; }
public string ThirdPdfUrl { get; set; }
}
@@ -73,6 +75,7 @@ public class SystemEmailSendConfig
public class SystemEmailSendConfigView
{
public string SystemShortName { get; set; } = string.Empty;
public string CompanyName { get; set; } = string.Empty;
public string CompanyNameCN { get; set; } = string.Empty;
@@ -11,6 +11,12 @@ public static class SendEmailHelper
public static async Task SendEmailAsync(MimeMessage messageToSend, SystemEmailSendConfig _systemEmailConfig, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
{
//没有收件人 那么不发送
if (messageToSend.To.Count == 0)
{
return;
}
try
{
using (var smtp = new MailKit.Net.Smtp.SmtpClient())
@@ -20,12 +20,12 @@ namespace IRaCIS.Core.Application.Helper
//添加 或者更新定时任务 Id 要唯一标识一个定义任务
public static void AddOrUpdateCronJob<T>(string jobId, Expression<Action<T>> methodCall, string cron, string queueName = "default")
{
RecurringJob.AddOrUpdate<T>(jobId, queueName, methodCall, cron);
RecurringJob.AddOrUpdate<T>(jobId, queueName, methodCall, cron, new RecurringJobOptions() { TimeZone = TimeZoneInfo.Local });
}
public static void AddOrUpdateInitCronJob<T>(string jobId, Expression<Action<T>> methodCall, string cron)
{
RecurringJob.AddOrUpdate<T>(jobId, "sys_init", methodCall, cron);
RecurringJob.AddOrUpdate<T>(jobId, "sys_init", methodCall, cron, new RecurringJobOptions() { TimeZone = TimeZoneInfo.Local });
}
public static void RemoveCronJob(string jobId)
@@ -73,17 +73,30 @@ namespace IRaCIS.Core.Application.Helper
case EmailBusinessScenario.QCToCRCImageQuestion:
HangfireJobHelper.AddOrUpdateCronJob<IMediator>(jobId, t => t.Send(new QCImageQuestionRecurringEvent() { TrialId = trialId }, default), emailCron);
break;
//加急阅片 10分钟
//加急阅片 10分钟
case EmailBusinessScenario.ExpeditedReading:
HangfireJobHelper.AddOrUpdateCronJob<IMediator>(jobId, t => t.Send(new UrgentIRUnReadTaskRecurringEvent() { TrialId = trialId }, default), emailCron);
break;
default:
break;
}
}
public static void AddOrUpdateSystemCronJob(string jobId, EmailBusinessScenario businessScenario, string emailCron)
{
switch (businessScenario)
{
case EmailBusinessScenario.GeneralTraining_ExpirationNotification:
HangfireJobHelper.AddOrUpdateCronJob<IMediator>(jobId, t => t.Send(new SystemDocumentErverDayEvent() { }, default), emailCron);
break;
default:
break;
}
}
}
}
@@ -0,0 +1,42 @@
using IRaCIS.Core.Domain.Models;
using MaxMind.GeoIP2;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper
{
public static class IPCityHelper
{
public static string GetCityResponse(string ip)
{
var path = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources, "GeoLite2-City.mmdb");
try
{
using (var reader = new DatabaseReader(path))
{
var city = reader.City(ip);
//Console.WriteLine(city.Country.IsoCode); // 'US' 'CN'
//Console.WriteLine(city.Country.Name); // 'United States' 'China'
////Console.WriteLine(city.Country.Names["zh-CN"]); // '美国'
//Console.WriteLine(city.MostSpecificSubdivision.Name); // 'Minnesota' 'Hubei'
//Console.WriteLine(city.City.Name); // 'Minneapolis' 'WUHan'
return $"{city.Country.Name} | {city.MostSpecificSubdivision.Name} | {city.City.Name}";
}
}
catch (Exception ex)
{
return $"UN | UN | {ip}";
}
}
}
}
@@ -15,14 +15,20 @@ public static class ImageHelper
fileStorePath = fileStorePath ?? filePath + ".preview.jpeg";
using (var image = SixLabors.ImageSharp.Image.Load(filePath))
{
// 读取 DICOM 文件
var dicomImage = new DicomImage(filePath);
// 渲染 DICOM 图像到 ImageSharp 格式
using (var image = dicomImage.RenderImage().AsSharpImage())
{
// 生成缩略图(调整大小)
image.Mutate(x => x.Resize(500, 500));
image.Save(fileStorePath);
// 保存缩略图为 JPEG
image.Save(fileStorePath, new JpegEncoder());
}
}
@@ -33,37 +33,38 @@
<ItemGroup>
<PackageReference Include="IdentityModel.OidcClient" Version="6.0.0" />
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.4" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.400.36" />
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.5" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.401.81" />
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
<PackageReference Include="AWSSDK.S3" Version="3.7.405" />
<PackageReference Include="DocX" Version="3.0.1" />
<PackageReference Include="AWSSDK.S3" Version="3.7.416.8" />
<PackageReference Include="DocX" Version="4.0.25105.5786" />
<PackageReference Include="FreeSpire.Doc" Version="12.2.0" />
<PackageReference Include="Hangfire.Core" Version="1.8.14" />
<PackageReference Include="Hangfire.Core" Version="1.8.18" />
<PackageReference Include="ExcelDataReader" Version="3.7.0" />
<PackageReference Include="ExcelDataReader.DataSet" Version="3.7.0" />
<PackageReference Include="DistributedLock.Redis" Version="1.0.3" />
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.5" />
<PackageReference Include="fo-dicom" Version="5.1.3" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.3" />
<PackageReference Include="fo-dicom.Codecs" Version="5.15.1" />
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.6" />
<PackageReference Include="fo-dicom" Version="5.2.1" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.1" />
<PackageReference Include="fo-dicom.Codecs" Version="5.16.1" />
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
<PackageReference Include="MailKit" Version="4.7.1.1" />
<PackageReference Include="MailKit" Version="4.11.0" />
<PackageReference Include="Masa.Contrib.Service.MinimalAPIs" Version="1.0.0" />
<PackageReference Include="MaxMind.GeoIP2" Version="5.2.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" />
<PackageReference Include="MimeKit" Version="4.7.1" />
<PackageReference Include="MiniExcel" Version="1.34.2" />
<PackageReference Include="Minio" Version="6.0.3" />
<PackageReference Include="MiniWord" Version="0.8.0" />
<PackageReference Include="MimeKit" Version="4.11.0" />
<PackageReference Include="MiniExcel" Version="1.41.3" />
<PackageReference Include="Minio" Version="6.0.4" />
<PackageReference Include="MiniWord" Version="0.9.2" />
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="NPOI" Version="2.7.1" />
<PackageReference Include="NPOI" Version="2.7.3" />
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
<PackageReference Include="RestSharp" Version="112.1.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
<PackageReference Include="ZiggyCreatures.FusionCache" Version="1.4.0" />
<PackageReference Include="ZiggyCreatures.FusionCache" Version="2.1.0" />
</ItemGroup>
<ItemGroup>
@@ -522,7 +522,7 @@
<param name="agreeReReadingCommand"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.Allocation.VisitTaskService.PMSetTaskBack(System.Guid,System.Guid)">
<member name="M:IRaCIS.Core.Application.Service.Allocation.VisitTaskService.PMSetTaskBack(System.Guid,System.Guid,System.String)">
<summary>
PM 设置任务 退回
</summary>
@@ -736,6 +736,10 @@
<param name="_trialRepository"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.Common.ExcelExportService.GetSysDocumentConfirmList_Export(IRaCIS.Core.Application.Contracts.SystemDocQuery,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Application.Interfaces.IDictionaryService)">
getSysDocumentConfirmList 系统文档培训查询
</member>
<member name="M:IRaCIS.Core.Application.Service.Common.ExcelExportService.PMTrainingRecordList_Export(IRaCIS.Core.Application.Contracts.DocumentTrialUnionQuery,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CommonDocument},IRaCIS.Application.Interfaces.IDictionaryService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument})">
<summary>
getDocumentConfirmList 培训记录导出--new
@@ -1383,6 +1387,107 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.Service.AuditDocumentService">
<summary>
稽查文档
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditDocument},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
稽查文档
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.GetAuditDocumentList(IRaCIS.Core.Application.ViewModel.AuditDocumentQuery)">
<summary>
获取稽查文档
</summary>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.UpdateAuditDocument(IRaCIS.Core.Application.ViewModel.AuditDocumentUpdateDto)">
<summary>
修改稽查文档
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.AddFolder(IRaCIS.Core.Application.ViewModel.AuditDocumentAddOrEdit)">
<summary>
新增文件夹
</summary>
<param name="inDto"></param>
<returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.AddAuditDocument(System.Collections.Generic.List{IRaCIS.Core.Application.ViewModel.AuditDocumentAddOrEdit})">
<summary>
新增稽查文档
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.AddOrUpdateAuditDocument(IRaCIS.Core.Application.ViewModel.AuditDocumentAddOrEdit)">
<summary>
通用方法
</summary>
<param name="inDto"></param>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.GetBreadcrumbData(IRaCIS.Core.Application.ViewModel.GetBreadcrumbDataInDto)">
<summary>
获取面包屑导航
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.GetAuditDocumentData(IRaCIS.Core.Application.ViewModel.GetAuditDocumentDataInDto)">
<summary>
获取文件树形结构 (传Id 根节点就是自己)
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.DeleteAuditDocument(IRaCIS.Core.Application.ViewModel.DeleteAuditDocumentInDto)">
<summary>
删除稽查文档
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.MovieFileOrFolder(IRaCIS.Core.Application.ViewModel.MovieFileOrFolderInDto)">
<summary>
移动文件或者文件夹 到其他文件夹
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.CopyFileOrFolder(IRaCIS.Core.Application.ViewModel.MovieFileOrFolderInDto)">
<summary>
复制文件或者文件夹
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.GetHistoricalVersion(IRaCIS.Core.Application.ViewModel.GetHistoricalVersionInDto)">
<summary>
获取历史版本
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.SetCurrentVersion(IRaCIS.Core.Application.ViewModel.SetCurrentVersionInDto)">
<summary>
把历史版本设置为当前版本
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.SetIsAuthorization(IRaCIS.Core.Application.ViewModel.SetIsAuthorizationInDto)">
<summary>
设置是否授权
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.Service.SysFileTypeService">
<summary>
系统文件类型
@@ -1499,7 +1604,7 @@
<param name="_userInfo"></param>
<param name="_localizer"></param>
</member>
<member name="M:IRaCIS.Core.Application.Service.TrialFileTypeService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialFileType},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SysFileType},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<member name="M:IRaCIS.Core.Application.Service.TrialFileTypeService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialFileType},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SysFileType},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
项目文件类型
</summary>
@@ -2552,6 +2657,13 @@
<returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member>
<member name="M:IRaCIS.Core.Application.Service.UserService.SetIsIgnoreUncommonly(IRaCIS.Core.Application.ViewModel.SetIsIgnoreUncommonlyInDto)">
<summary>
设置是否忽略异地登录
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.UserService.GetUserLoginRoleList(IRaCIS.Application.Contracts.IRCLoginDto,IRaCIS.Core.Application.Auth.ITokenService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
账号验证,获取账号角色信息 获取临时token
@@ -4453,6 +4565,291 @@
<param name="digitPlaces"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetReadingCalculationData(IRaCIS.Core.Application.Service.Reading.Dto.GetReadingCalculationDataInDto)">
<summary>
获取阅片的计算数据
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="F:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.sODData">
<summary>
获取Sod的值
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetDeleteLesionStatrIndex(IRaCIS.Core.Application.Service.Reading.Dto.DeleteReadingRowAnswerInDto)">
<summary>
删除病灶获取起始病灶序号(RECIST1Point1 固定是1
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetReadingReportEvaluation(IRaCIS.Core.Application.Service.Reading.Dto.GetReadingReportEvaluationInDto)">
<summary>
获取阅片报告
</summary>
<param name="indto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.TestCalculate(System.Guid,IRaCIS.Core.Domain.Share.QuestionType)">
<summary>
测试计算
</summary>
<param name="visitTaskId"></param>
<param name="type"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.CalculateTask(IRaCIS.Core.Application.Service.Reading.Dto.CalculateTaskInDto)">
<summary>
计算任务
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetReportVerify(IRaCIS.Core.Application.Service.Reading.Dto.GetReportVerifyInDto)">
<summary>
获取报告验证的信息(这里每个标准可能不一样 返回用object)
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.ReadingCalculate(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto,System.Collections.Generic.List{IRaCIS.Core.Domain.Share.QuestionType})">
<summary>
自动计算
</summary>
<param name="inDto"></param>
<param name="calculateType"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetReportTumor(System.Guid)">
<summary>
获取报告整体整体评估
</summary>
<param name="visitTaskId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetReportIsExistDisease(System.Guid)">
<summary>
获取报告是否存在疾病
</summary>
<param name="visitTaskId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.VerifyVisitTaskQuestions(IRaCIS.Core.Application.Service.Reading.Dto.VerifyVisitTaskQuestionsInDto)">
<summary>
验证访视提交
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.AddTaskLesionAnswerFromLastTask(IRaCIS.Core.Application.ViewModel.AddTaskLesionAnswerFromLastTaskInDto)">
<summary>
将上一次的访视病灶添加到这一次
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetSODData(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
获取SOD
</summary>
<remarks>
靶病灶径线之和(SOD)
非淋巴结的长径 和淋巴结的短径
</remarks>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetSumOfDiameter(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
非淋巴结靶病灶长径之和
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetSODChange(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
与基线SOD相比变化量(mm)
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetSODPercent(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
与基线访视相比SOD变化百分比
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetLowestIncrease(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
与整个访视期间SOD最低点相比增加的值(mm)
</summary>
<param name="inDto"></param>
<remarks>
要更新之前的
</remarks>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetLowPercent(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
与整个访视期间SOD最低点相比增加的百分比
</summary>
<param name="inDto"></param>
<remarks>
要更新之前的
</remarks>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetLowVisit(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
整个访视期间SOD最低点访视名称
</summary>
<param name="inDto"></param>
<remarks>
要更新之前的
</remarks>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetIsLymphTarget(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
是否存在非淋巴结靶病灶
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetIsAddFive(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
是否存在淋巴结靶病灶且该病灶比上一访视短径增加5MM以上
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetIsAddFiveRowIndexs(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
获取存在淋巴结靶病灶且该病灶比上一访视短径增加5MM以上的病灶
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetNETarget(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
被评估为NE的单个靶病灶
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetTumor(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
整体肿瘤评估
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.TestOncology">
<summary>
测试肿瘤学评估
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.CalculationGetImgOncology(System.String,System.String,System.String)">
<summary>
计算整体肿瘤评估 【测试】
</summary>
<param name="targetLesion">靶病灶</param>
<param name="noTargetLesion"> 非靶病灶</param>
<param name="newLesions">新病灶</param>
<remarks>
靶病灶 非靶病灶 存在新病灶 整体肿瘤评估
1. CR CR 否 CR
2. CR ND 否 CR
3. ND CR 否 CR
4. CR NN/NE 否/疑似/NE PR
5. CR CR/ND 疑似/NE PR
6. PR CR/ND/NN/NE 否/疑似/NE PR
7. ND CR 疑似/NE PR
8. SD CR/ND/NN/NE 否/疑似/NE SD
9. ND NN 否/疑似/NE NN
10.NE CR/ND/NN/NE 否/疑似/NE NE
11.ND NE 否/疑似/NE NE
12.ND ND NE NE
13.ND ND 否/疑似 ND
14.PD CR/NN/PD/ND/NE 是/否/疑似/NE PD
15.CR/PR/SD/PD/ND/NE PD 是/否/疑似/NE PD
16.CR/PR/SD/PD/ND/NE CR/NN/PD/ND/NE 是 PD
</remarks>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetIsExistDisease(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
是否存在疾病
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.ChangeAllLowestIncrease(IRaCIS.Core.Application.Service.Reading.Dto.ChangeAllTaskDto)">
<summary>
修改与整个访视期间SOD最低点相比增加的值(mm)
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.ChangeAllLowVisitName(IRaCIS.Core.Application.Service.Reading.Dto.ChangeAllTaskDto)">
<summary>
修改最低方式点名称
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.ChangeAllVisitTaskAnswer(System.Collections.Generic.List{System.Guid},System.Guid,System.String)">
<summary>
修改所有访视任务的答案
</summary>
<param name="visitTaskGuids"></param>
<param name="questionId"></param>
<param name="answer"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetBaseLineSOD(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
获取基线SOD
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetLowSODVisit(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
获取最低方式
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetVisitTaskAnswerList(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
获取访视任务信息
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetLastVisitTaskId(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
获取上一个访视任务Id
</summary>
<returns></returns>
</member>
<!-- Badly formed XML comment ignored for member "M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetTargetLesionEvaluate(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)" -->
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetNoTargetLesionEvaluate(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
获取非靶病灶评估
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRECISTHCCCalculateService.GetNewLesionEvaluate(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<summary>
获取新病灶评估
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.MRIPDFFCalculateService.GetReadingCalculationData(IRaCIS.Core.Application.Service.Reading.Dto.GetReadingCalculationDataInDto)">
<summary>
获取阅片的计算数据
@@ -8462,6 +8859,11 @@
eCRF报告是否显示在图像页面
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GetReadingTaskDto.ReadingVersionEnum">
<summary>
阅片版本
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.GetReadingTaskDto.IsReadingTaskViewInOrder">
<summary>
任务展示访视 读片任务显示是否顺序
@@ -10118,6 +10520,16 @@
修约小数点
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.AddOrUpdateReadingQuestionCriterionTrialInDto.ReadingVersionEnum">
<summary>
阅片版本
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.AddOrUpdateReadingQuestionCriterionTrialInDto.ReadingToolList">
<summary>
阅片工具
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.AddOrUpdateReadingQuestionCriterionSystemInDto.CriterionGroup">
<summary>
标准分组
@@ -12064,7 +12476,7 @@
阅片问题.标准
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingQuestionService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataTrialSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataSystemSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemCriterionDictionaryCode},IRaCIS.Core.Application.Contracts.IReadingImageTaskService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingSystemCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCriterionPage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TumorAssessment_RECIST1Point1},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.OrganInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.PreviousPDF},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<member name="M:IRaCIS.Core.Application.Service.ReadingQuestionService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataTrialSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataSystemSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CriterionNidusSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemCriterionDictionaryCode},IRaCIS.Core.Application.Contracts.IReadingImageTaskService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingSystemCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCriterionPage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TumorAssessment_RECIST1Point1},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.OrganInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.PreviousPDF},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
阅片问题.标准
</summary>
@@ -12346,7 +12758,7 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingNoneDicomMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserLog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingOncologyTaskInfo},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Application.Service.IVisitTaskService,IRaCIS.Core.Application.Contracts.IReadingClinicalDataService,IRaCIS.Core.Application.Service.IReadingCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserFeedBack},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingGlobalTaskInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCriterionPage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskRelation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingJudgeInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.OrganInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocument},IRaCIS.Core.Application.Service.ReadingCalculate.Interface.ILuganoCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCustomTag},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTrialCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Application.Service.IGeneralCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskStudy},IRaCIS.Core.Application.Service.ImageAndDoc.IDownloadAndUploadService,IRaCIS.Core.Application.Interfaces.ITrialEmailNoticeConfigService,AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer,ZiggyCreatures.Caching.Fusion.IFusionCache)">
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingNoneDicomMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserLog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingOncologyTaskInfo},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Application.Service.IVisitTaskService,IRaCIS.Core.Application.Contracts.IReadingClinicalDataService,IRaCIS.Core.Application.Service.IReadingCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserFeedBack},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingGlobalTaskInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCriterionPage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskRelation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingJudgeInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.OrganInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.OrganTrialInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocument},IRaCIS.Core.Application.Service.ReadingCalculate.Interface.ILuganoCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCustomTag},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTrialCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Application.Service.IGeneralCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskStudy},IRaCIS.Core.Application.Service.ImageAndDoc.IDownloadAndUploadService,IRaCIS.Core.Application.Interfaces.ITrialEmailNoticeConfigService,AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer,ZiggyCreatures.Caching.Fusion.IFusionCache)">
<summary>
IR影像阅片
</summary>
@@ -12900,7 +13312,7 @@
阅片期配置
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingPeriodSetService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitStage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodPlan},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Site},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<member name="M:IRaCIS.Core.Application.Service.ReadingPeriodSetService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitStage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Application.Contracts.IReadingImageTaskService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodPlan},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Site},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
阅片期配置
</summary>
@@ -12972,7 +13384,7 @@
生成的阅片模块(在大列表上展示的) 阅片期
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadModuleService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataTrialSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModuleView},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingClinicalData},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<member name="M:IRaCIS.Core.Application.Service.ReadModuleService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataTrialSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModuleView},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingClinicalData},IRaCIS.Core.Application.Contracts.IReadingImageTaskService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
生成的阅片模块(在大列表上展示的) 阅片期
</summary>
@@ -13523,6 +13935,22 @@
<param name="_readingConsistentClinicalDataRepository"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.IQCBackToUpload(System.Guid[],IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialQCQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingClinicalData})">
<summary>
IQC 回退到影像上传
</summary>
<param name="subjectVisitIdList"></param>
<param name="_subjectVisitRepository"></param>
<param name="_trialQCQuestionAnswerRepository"></param>
<param name="_readingClinicalDataReposiotry"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.BackImageResize(System.Guid,System.Guid)">
<summary>
后端处理某个中心缩略图有问题 先下载,生成缩略图上传,然后更新数据库
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.DealTialFileSie(IRaCIS.Core.Application.Helper.IOSSService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingClinicalDataPDF})">
<summary>
非dicom 临床数据
@@ -13664,6 +14092,26 @@
接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(IRaCIS.Core.Domain.Models.EmailNoticeConfig,MimeKit.MimeMessage,System.Func{System.ValueTuple{System.String,System.String},System.ValueTuple{System.String,System.String}})">
<summary>
系统默认邮件 + 项目默认邮件 (不用添加到项目邮件配置中,才发送)
</summary>
<param name="configInfo"></param>
<param name="messageToSend"></param>
<param name="emailFunc"></param>
<returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig,MimeKit.MimeMessage,System.Func{System.ValueTuple{System.String,System.String},System.ValueTuple{System.String,System.String}})">
<summary>
项目手动邮件 (需要添加到项目邮件配置中,才发送)
</summary>
<param name="configInfo"></param>
<param name="messageToSend"></param>
<param name="emailFunc"></param>
<returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CommonEmailHelper.TranslationDictionary(IRaCIS.Core.Application.MassTransit.Consumer.TranslationDictionaryDto)">
<summary>
翻译字典
@@ -13726,17 +14174,67 @@
返回
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ConsistencyCheckConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Domain.Share.IUserInfo,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSite},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},AutoMapper.IMapper,Microsoft.Extensions.Localization.IStringLocalizer,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ConsistencyCheckConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Domain.Share.IUserInfo,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSite},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},AutoMapper.IMapper,Microsoft.Extensions.Localization.IStringLocalizer,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary})">
<summary>
构造函数注入
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.ImageConsumer">
<summary>
影像重传和阅片人筛选相关邮件发送
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ImageConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Enroll},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeUserType},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSite},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
影像重传和阅片人筛选相关邮件发送
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ImageConsumer.Consume(MassTransit.ConsumeContext{IRaCIS.Core.Domain._DomainEvent.DirectApplyReupdloadEvent})">
<summary>
处理直接申请流程的重传事件
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ImageConsumer.Consume(MassTransit.ConsumeContext{IRaCIS.Core.Domain._DomainEvent.CheckReuploadEvent})">
<summary>
处理一致性核查申请重传事件
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ImageConsumer.Consume(MassTransit.ConsumeContext{IRaCIS.Core.Domain._DomainEvent.QCChanllengeReuploadEvent})">
<summary>
处理质疑CRC申请重传事件
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ImageConsumer.Consume(MassTransit.ConsumeContext{IRaCIS.Core.Domain._DomainEvent.HaveReadVisitTaskReReading})">
<summary>
处理已阅任务重阅申请事件
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ImageConsumer.SendImageReuploadEmail(IRaCIS.Core.Application.MassTransit.Consumer.Dto.SendImageReuploadEmailInDto)">
<summary>
发送影像重传相关邮件的通用方法
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ImageConsumer.Consume(MassTransit.ConsumeContext{IRaCIS.Core.Domain._DomainEvent.ReviewerPMApplyEvent})">
<summary>
处理PM申请阅片人筛选事件
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ImageConsumer.Consume(MassTransit.ConsumeContext{IRaCIS.Core.Domain._DomainEvent.ReviewerSPMApprovedEvent})">
<summary>
处理SPM审批阅片人筛选事件
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.ImageConsumer.SendReviewerSelectionEmail(IRaCIS.Core.Domain.Models.EmailNoticeConfig,System.Guid,System.Collections.Generic.List{System.Guid})">
<summary>
发送阅片人筛选相关邮件的通用方法
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.UrgentMedicalReviewAddedEventConsumer">
<summary>
加急的医学反馈任务 通知MIM
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.UrgentMedicalReviewAddedEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskMedicalReview},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.UrgentMedicalReviewAddedEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskMedicalReview},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
加急的医学反馈任务 通知MIM
</summary>
@@ -13754,7 +14252,7 @@
MIM 回复医学返回通知IR
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.UrgentMIMRepliedMedicalReviewConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskMedicalReview},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.UrgentMIMRepliedMedicalReviewConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskMedicalReview},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
MIM 回复医学返回通知IR
</summary>
@@ -13771,19 +14269,19 @@
加急阅片 IR 申请重阅 或者PM 申请重阅
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.UrgentIRApplyedReReadingConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskMedicalReview},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.UrgentIRApplyedReReadingConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskMedicalReview},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
加急阅片 IR 申请重阅 或者PM 申请重阅
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.UserSiteSurveySubmitedEventConsumer">
<summary>
用户提交 发送邮件 通知SPM 或者PM
用户提交 发送邮件 通知SPM 或者PM 项目默认邮件,不用添加到项目中,直接发送的
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.UserSiteSurveySubmitedEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSite},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialSiteSurvey},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
用户提交 发送邮件 通知SPM 或者PM
用户提交 发送邮件 通知SPM 或者PM 项目默认邮件,不用添加到项目中,直接发送的
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.SiteSurveySPMSubmitedEventConsumer">
@@ -13811,7 +14309,7 @@
CRC 提交了 通知QC进行质控 Code005006
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CRCSubmitedAndQCToAuditEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CRCSubmitedAndQCToAuditEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
CRC 提交了 通知QC进行质控 Code005006
</summary>
@@ -13821,7 +14319,7 @@
CRC 回复质控质疑 通知QC Code012013
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CRCRepliedQCChallengeEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallenge},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CRCRepliedQCChallengeEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallenge},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
CRC 回复质控质疑 通知QC Code012013
</summary>
@@ -13831,7 +14329,7 @@
QC回复 质控质疑,通知CRC (014015)
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.QCRepliedQCChallengeEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallenge},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.QCRepliedQCChallengeEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallenge},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
QC回复 质控质疑,通知CRC (014015)
</summary>
@@ -13841,19 +14339,19 @@
CRC 回复一致性核查质疑 通知PM (019,020)
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CRCRepliedCheckChallengeEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallenge},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CRCRepliedCheckChallengeEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallenge},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
CRC 回复一致性核查质疑 通知PM (019,020)
</summary>
</member>
<!-- Badly formed XML comment ignored for member "T:IRaCIS.Core.Application.MassTransit.Consumer.PMRepliedCheckChallengeEventConsumer" -->
<!-- Badly formed XML comment ignored for member "M:IRaCIS.Core.Application.MassTransit.Consumer.PMRepliedCheckChallengeEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CheckChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})" -->
<!-- Badly formed XML comment ignored for member "M:IRaCIS.Core.Application.MassTransit.Consumer.PMRepliedCheckChallengeEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CheckChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})" -->
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.CheckStateChangedToAuditEventConsumer">
<summary>
通知PM 进行一致性核查 (018,030)
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CheckStateChangedToAuditEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallenge},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.CheckStateChangedToAuditEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallenge},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
通知PM 进行一致性核查 (018,030)
</summary>
@@ -13863,7 +14361,7 @@
QC 领取了质控任务 (007008)
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.QCClaimTaskEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallenge},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<member name="M:IRaCIS.Core.Application.MassTransit.Consumer.QCClaimTaskEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallenge},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.QCChallengeDialog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
QC 领取了质控任务 (007008)
</summary>
@@ -13929,6 +14427,17 @@
影像质控
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.SystemDocumentErverDayEvent">
<summary>
定时提醒
</summary>
</member>
<member name="P:IRaCIS.Core.Application.MassTransit.Consumer.SystemDocumentPublishEvent.NewUserTypeIds">
<summary>
新增的需要发送邮件的用户角色ID列表
如果为null或空,则发送给所有相关角色
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Consumer.QCImageQuestionRecurringSchedule">
<summary>
QC 影像质疑待处理
@@ -13949,11 +14458,31 @@
10分钟检测通知IR 已通知的进行标注,下次不会再通知
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Recurring.UrgentIRUnReadTaskRecurringEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<member name="M:IRaCIS.Core.Application.MassTransit.Recurring.UrgentIRUnReadTaskRecurringEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialEmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
10分钟检测通知IR 已通知的进行标注,下次不会再通知
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentErverDayEventConsumer">
<summary>
定时过期提醒
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentErverDayEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
定时过期提醒
</summary>
</member>
<member name="T:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentPublishEventConsumer">
<summary>
生效通知
</summary>
</member>
<member name="M:IRaCIS.Core.Application.MassTransit.Recurring.SystemDocumentPublishEventConsumer.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Dictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.EmailNoticeConfig},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary>
生效通知
</summary>
</member>
<member name="T:IRaCIS.Core.Application.ViewModel.TaskAllocationRuleView">
<summary> TaskAllocationRuleView 列表视图模型 </summary>
</member>
@@ -14308,6 +14837,11 @@
<member name="T:IRaCIS.Core.Application.ViewModel.PublishLogAddOrEdit">
<summary> PublishLogAddOrEdit 列表查询参数模型</summary>
</member>
<member name="P:IRaCIS.Core.Application.ViewModel.SysFileTypeAddOrEdit.SysTemplateTypeEnum">
<summary>
文档类型
</summary>
</member>
<member name="P:IRaCIS.Core.Application.ViewModel.SysFileTypeAddOrEdit.ShowOrder">
<summary>
显示顺序
@@ -15414,6 +15948,26 @@
<member name="T:IRaCIS.Core.Application.Contracts.SystemDocumentQuery">
<summary>SystemDocumentQuery 列表查询参数模型</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.SystemDocQuery.IsDeleted">
<summary>
课时状态
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.SystemDocQuery.UserName">
<summary>
用户名
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.SystemDocQuery.StartConfirmTime">
<summary>
开始时间
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.SystemDocQuery.EndConfirmTime">
<summary>
结束时间
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.DocumentTrialUnionQuery.IsDeleted">
<summary>
课时状态
@@ -15437,6 +15991,21 @@
<member name="T:IRaCIS.Core.Application.Contracts.SystemDocumentAddOrEdit">
<summary> SystemDocumentAddOrEdit 列表查询参数模型</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.SystemDocumentAddOrEdit.CurrentStaffTrainDays">
<summary>
现有员工培训天数
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.SystemDocumentAddOrEdit.NewStaffTrainDays">
<summary>
新员工培训天数
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.SystemDocumentAddOrEdit.IsPublish">
<summary>
是否发布
</summary>
</member>
<member name="T:IRaCIS.Core.Application.Contracts.TrialDocumentUserConfirmView">
<summary> TrialDocumentUserConfirmView 列表视图模型 </summary>
</member>
@@ -15712,6 +16281,16 @@
组件一致性和原Arm2是否有差异
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.ImageBackViewModel.ApplyReason">
<summary>
申请原因
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.ImageBackViewModel.ResultRemark">
<summary>
结果备注
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.GetNextCRCChallengeInDto.QCChallengeId">
<summary>
QCChallengeId
@@ -16157,6 +16736,11 @@
流程配置是否确认
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.GetTrialReadingInfoOutDto.ReadingToolList">
<summary>
阅片工具
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Contracts.GetTrialReadingInfoOutDto.TrialId">
<summary>
项目ID
@@ -16546,12 +17130,33 @@
<member name="T:IRaCIS.Core.Application.Services.SystemDocumentService">
<summary>
SystemDocumentService
</summary>
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},MassTransit.Mediator.IScopedMediator,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocumentAttachment},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
SystemDocumentService
</summary>
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.GetSystemDocumentAttachmentList(IRaCIS.Core.Application.Contracts.SystemDocumentAttachmentQuery)">
<summary>
获取系统文档附件
</summary>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.AddOrUpdateSystemDocumentAttachment(IRaCIS.Core.Application.Contracts.SystemDocumentAttachmentAddOrEdit)">
<summary>
新增或编辑系统文档附件
</summary>
<param name="addOrEditSystemDocumentAttachment"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.DeleteSystemDocumentAttachment(System.Guid)">
<summary>
删除系统文档附件
</summary>
<param name="systemDocumentAttachmentId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.GetSystemDocumentListAsync(IRaCIS.Core.Application.Contracts.SystemDocumentQuery)">
<summary>
@@ -16560,6 +17165,18 @@
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.PublishSystemDocument(IRaCIS.Core.Application.Contracts.PublishSystemDocumentInDto)">
<summary>
发布系统文档
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.OutLineSystemDocument(IRaCIS.Core.Application.Contracts.PublishSystemDocumentInDto)">
<summary>
下线系统文档
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Services.SystemDocumentService.getWaitSignSysDocList(IRaCIS.Core.Application.Contracts.SystemDocumentQuery)">
<summary>
获取需要签署的系统文档列表
@@ -16571,7 +17188,7 @@
TrialDocumentService
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Services.TrialDocumentService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Application.Contracts.ISystemDocumentService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocNeedConfirmedUserType},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocNeedConfirmedUserType},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<member name="M:IRaCIS.Core.Application.Services.TrialDocumentService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Application.Contracts.ISystemDocumentService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocNeedConfirmedUserType},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocNeedConfirmedUserType},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SystemDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialUserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.IdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocConfirmedIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
TrialDocumentService
</summary>
@@ -16604,6 +17221,12 @@
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Services.TrialDocumentService.GetSysDocSignUserList">
<summary>
获取系统签署文档签署人下拉框
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Services.TrialDocumentService.GetTrialUserSelect(System.Guid)">
<summary>
项目下面的参与用户下拉
@@ -16956,6 +17579,25 @@
<param name="qaDialogCommand"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Image.QA.QCOperationService.RequestImageBack(System.Guid,System.String)">
<summary>
CRC IQC 申请影像回退
</summary>
<param name="subjectVisitId"></param>
<param name="ApplyReason"></param>
<returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member>
<member name="M:IRaCIS.Core.Application.Image.QA.QCOperationService.AuditImageBack(System.Guid,System.Boolean,System.String)">
<summary>
PM 审核CRC IQC 申请影像回退
</summary>
<param name="iamgeBackRecordId"></param>
<param name="isAgree"></param>
<param name="resultRemark"></param>
<returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member>
<member name="M:IRaCIS.Core.Application.Image.QA.QCOperationService.AddCheckChallengeReply(IRaCIS.Core.Application.Contracts.DTO.CheckChallengeDialogCommand)">
<summary>
一致性核查 质疑的添加/回复
@@ -14,19 +14,20 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer;
public static class CommonEmailHelper
{
public static async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(IRepository<EmailNoticeConfig> _emailNoticeConfigrepository, EmailBusinessScenario scenario, MimeMessage messageToSend,
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc)
/// <summary>
/// 系统默认邮件 + 项目默认邮件 (不用添加到项目邮件配置中,才发送)
/// </summary>
/// <param name="configInfo"></param>
/// <param name="messageToSend"></param>
/// <param name="emailFunc"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
public static async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailNoticeConfig configInfo, MimeMessage messageToSend,
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).FirstOrDefaultAsync();
if (configInfo == null)
{
throw new BusinessValidationFailedException("系统未找到当前场景邮件配置信息,请联系运维人员核查");
}
var (topicStr, htmlBodyStr) = isEn_US ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
try
@@ -36,8 +37,9 @@ public static class CommonEmailHelper
}
catch (Exception ex)
{
//"邮件模板内容有误,填充内容出现问题,请联系运维人员核查"
throw new BusinessValidationFailedException("邮件模板内容有误,填充内容出现问题,请联系运维人员核查");
throw new BusinessValidationFailedException(I18n.T("CommonEmail_ConfigError"));
}
@@ -52,6 +54,49 @@ public static class CommonEmailHelper
return configInfo;
}
/// <summary>
/// 项目手动邮件 (需要添加到项目邮件配置中,才发送)
/// </summary>
/// <param name="configInfo"></param>
/// <param name="messageToSend"></param>
/// <param name="emailFunc"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
public static async Task<TrialEmailNoticeConfig> GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(TrialEmailNoticeConfig configInfo, MimeMessage messageToSend,
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var (topicStr, htmlBodyStr) = isEn_US ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
try
{
//每个场景修改主题 和body的逻辑不一样
(topicStr, htmlBodyStr) = emailFunc((topicStr, htmlBodyStr));
}
catch (Exception ex)
{
//"邮件模板内容有误,填充内容出现问题,请联系运维人员核查"
throw new BusinessValidationFailedException(I18n.T("CommonEmail_ConfigError"));
}
messageToSend.Subject = topicStr;
var builder = new BodyBuilder();
builder.HtmlBody = htmlBodyStr;
messageToSend.Body = builder.ToMessageBody();
return configInfo;
}
public static string ReplaceCompanyName(SystemEmailSendConfig _systemEmailConfig, string needDealtxt)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
@@ -74,12 +119,13 @@ public static class CommonEmailHelper
var enumValueList = inDto.DictionaryList.Select(x => x.EnumValue).ToList();
var dicList =await inDto.DictionaryRepository.Where(x => dictionaryCodelist.Contains(x.Parent.Code) && enumValueList.Contains(x.Code)).Select(x=>new DictionaryData() {
DictionaryCode=x.Parent.Code,
EnumValue=x.Code,
Value=x.Value,
ValueCN=x.ValueCN
var dicList = await inDto.DictionaryRepository.Where(x => dictionaryCodelist.Contains(x.Parent.Code) && enumValueList.Contains(x.Code)).Select(x => new DictionaryData()
{
DictionaryCode = x.Parent.Code,
EnumValue = x.Code,
Value = x.Value,
ValueCN = x.ValueCN
}).ToListAsync();
@@ -88,7 +134,7 @@ public static class CommonEmailHelper
inDto.DictionaryList.ForEach(x =>
{
var dic = dicList.Where(y => y.EnumValue == x.EnumValue && y.DictionaryCode == x.DictionaryCode).FirstOrDefault();
var dic = dicList.Where(y => y.EnumValue == x.EnumValue && y.DictionaryCode.Equals(x.DictionaryCode,StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
result.Add(dic == null ? string.Empty : (inDto.IsEn_US ? dic.Value : dic.ValueCN));
});
@@ -1,8 +1,10 @@
using AutoMapper;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Domain.Share;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
@@ -24,6 +26,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
private readonly SystemEmailSendConfig _systemEmailConfig;
private readonly IRepository<Dictionary> _dictionaryRepository;
/// <summary>
/// 构造函数注入
/// </summary>
@@ -31,7 +34,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
public ConsistencyCheckConsumer(IRepository<DicomStudy> studyRepository, IUserInfo userInfo,
IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository,
IRepository<TrialSite> trialSiteRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository,
IMapper mapper, IStringLocalizer localizer, IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig)
IMapper mapper, IStringLocalizer localizer, IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig, IRepository<Dictionary> dictionaryRepository)
{
_noneDicomStudyRepository = noneDicomStudyRepository;
_studyRepository = studyRepository;
@@ -43,6 +46,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
_localizer = localizer;
_systemEmailConfig = systemEmailConfig.CurrentValue;
_dictionaryRepository = dictionaryRepository;
}
@@ -52,6 +56,9 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
var trialId = context.Message.TrialId;
//系统定义MRI 到底是MR 还是MRI
var mriModality = await _dictionaryRepository.Where(t => t.Parent.Code == "Modality").Where(t => t.Code == "MRI").Select(t => t.Value).FirstNotNullAsync();
//处理Excel大小写
context.Message.ETCList.ForEach(t => { t.Modality = t.Modality.ToUpper().Trim(); t.StudyDate = Convert.ToDateTime(t.StudyDate).ToString("yyyy-MM-dd"); t.SiteCode = t.SiteCode.ToUpper().Trim(); t.VisitName = t.VisitName.ToUpper().Trim(); t.SubjectCode = t.SubjectCode.ToUpper().Trim(); });
var etcList = context.Message.ETCList;
@@ -120,6 +127,16 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
var etcVisitStudyList = etcList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();
//以我们系统数据库为准 ,判断是MR 还是MRI, 把Excel 里的MR 或者MRI 处理成一致,MR MRI 是一致的
foreach (var item in etcVisitStudyList)
{
if (item.Modality == "MR" || item.Modality == "MRI")
{
item.Modality = mriModality;
}
}
StringBuilder dialogMsg = new StringBuilder();
//---您好,根据本系统自动识别,该受试者当前访视在IRC系统中已提交的影像检查情况如下:
@@ -229,7 +246,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
{
num++;
//影像检查(EDC 缺少) ConsistencyVerification_EdcL
dialogMsg.AppendLine($"<br/><div style='text-indent: 20px;'>{num}. {_localizer["ConsistencyVerification_EdcL", item.StudyDate, item.Modality, _systemEmailConfig.SystemShortName]}</div>");
dialogMsg.AppendLine($"<br/><div style='text-indent: 20px;'>{num}. {_localizer["ConsistencyVerification_EdcL", item.StudyDate, item.Modality/*, _systemEmailConfig.SystemShortName*/]}</div>");
}
@@ -243,8 +260,8 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
dialogMsg.AppendLine($"<br/>");
dialogMsg.AppendLine(@$"<div>{_localizer["ConsistencyVerification_Desc"]}</div>");
dbSV.CheckResult =
String.Join(" | ", dbExceptExcel.Select(t => $"{_localizer["ConsistencyVerification_EdcL", t.StudyDate, t.Modality, _systemEmailConfig.SystemShortName]}")) + " | "
dbSV.CheckResult =
String.Join(" | ", dbExceptExcel.Select(t => $"{_localizer["ConsistencyVerification_EdcL", t.StudyDate, t.Modality/*, _systemEmailConfig.SystemShortName*/]}")) + " | "
+ String.Join(" | ", excelExceptDB.Select(t => $"{_localizer["ConsistencyVerification_IrcLi", t.StudyDate, t.Modality, _systemEmailConfig.SystemShortName]}"));
//新增一致性核查质疑记录
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.MassTransit.Consumer.Dto
{
public class SendImageReuploadEmailInDto
{
public EmailNoticeConfig EmailNoticeConfig { get; set; }
public EmailBusinessScenario Scenario { get; set; }
public SubjectVisit SubjectVisit { get; set; }
public Guid TrialId { get; set; }
public List<UserTypeEnum> UserTypes { get; set; } = null;
public ImageBackStateEnum ImageBackStateEnum { get; set; } = ImageBackStateEnum.None;
public RequestBackStateEnum RequestBackStateEnum { get; set; } = RequestBackStateEnum.NotRequest;
public ReReadingApplyState ReReadingApplyState { get; set; } = ReReadingApplyState.Default;
}
}
@@ -0,0 +1,522 @@
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MassTransit.Command;
using IRaCIS.Core.Application.MassTransit.Consumer.Dto;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain;
using IRaCIS.Core.Domain._DomainEvent;
using IRaCIS.Core.Domain.BaseModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using MassTransit;
using MassTransit.Mediator;
using MassTransit.Scheduling;
using Medallion.Threading;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Options;
using MimeKit;
using Newtonsoft.Json;
using Panda.DynamicWebApi.Attributes;
using RestSharp;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.MassTransit.Consumer;
/// <summary>
/// 影像重传和阅片人筛选相关邮件发送
/// </summary>
public class ImageConsumer(
IRepository<UserRole> _userRoleRepository,
IRepository<TrialUserRole> _trialUseRoleRepository,
IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<Trial> _trialRepository,
IRepository<Enroll> _enrollRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<ReadModule> _readModuleRepository,
IRepository<EmailNoticeUserType> _emailNoticeUserTypeRepository,
IRepository<TrialSite> _trialSiteRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) :
IConsumer<DirectApplyReupdloadEvent>,
IConsumer<CheckReuploadEvent>,
IConsumer<QCChanllengeReuploadEvent>,
IConsumer<HaveReadVisitTaskReReading>,
IConsumer<ReviewerPMApplyEvent>,
IConsumer<ReviewerSPMApprovedEvent>
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
/// <summary>
/// 处理直接申请流程的重传事件
/// </summary>
public async Task Consume(ConsumeContext<DirectApplyReupdloadEvent> context)
{
Console.WriteLine("发送【影像重传-直接申请流程】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var subjectVisitId = context.Message.SubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).FirstNotNullAsync();
var trialId = subjectVisit.TrialId;
List<UserTypeEnum> userTypes = null;
// 根据申请角色和状态确定邮件场景
EmailBusinessScenario scenario;
if (context.Message.ImageBackState == ImageBackStateEnum.None)
{
switch (context.Message.ApplyUserRole)
{
case ImageBackApplyEnum.IQCRequestBack:
scenario = EmailBusinessScenario.ImageQC_IQCApplyRe_Uploading; // 64
break;
case ImageBackApplyEnum.CRCRequestBack:
scenario = EmailBusinessScenario.ImageUploadCRCApplyRe_Uploading; // 65
break;
default:
scenario = EmailBusinessScenario.ImageQC_IQCApplyRe_Uploading; // 64
break;
}
}
else
{
scenario = EmailBusinessScenario.ImageReUpload_PMApprovalRe_Uploading; // 66
if (context.Message.ApplyUserRole == ImageBackApplyEnum.IQCRequestBack)
{
userTypes = new List<UserTypeEnum>() { UserTypeEnum.IQC, UserTypeEnum.ClinicalResearchCoordinator };
}
else if (context.Message.ApplyUserRole == ImageBackApplyEnum.CRCRequestBack)
{
userTypes = new List<UserTypeEnum>() { UserTypeEnum.ClinicalResearchCoordinator };
}
}
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault();
if (emailConfig != null)
{
var inDto = new SendImageReuploadEmailInDto
{
EmailNoticeConfig = emailConfig,
Scenario = scenario,
SubjectVisit = subjectVisit,
TrialId = trialId,
UserTypes = userTypes,
ImageBackStateEnum = context.Message.ImageBackState
};
await SendImageReuploadEmail(inDto);
}
}
/// <summary>
/// 处理一致性核查申请重传事件
/// </summary>
public async Task Consume(ConsumeContext<CheckReuploadEvent> context)
{
Console.WriteLine("发送【一致性核查-影像重传】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var subjectVisitId = context.Message.SubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).FirstNotNullAsync();
var trialId = subjectVisit.TrialId;
// 根据状态确定邮件场景
EmailBusinessScenario scenario;
switch (context.Message.RequestBackState)
{
case RequestBackStateEnum.CRC_RequestBack:
scenario = EmailBusinessScenario.DataReconciliation_CRCApplyRe_Uploading; // 62
break;
case RequestBackStateEnum.PM_AgressBack:
case RequestBackStateEnum.PM_NotAgree:
scenario = EmailBusinessScenario.DataReconciliation_PMApprovalRe_Uploading; // 63
break;
default:
return; // 其他状态不发送邮件
}
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault();
if (emailConfig != null)
{
var inDto = new SendImageReuploadEmailInDto
{
EmailNoticeConfig = emailConfig,
Scenario = scenario,
SubjectVisit = subjectVisit,
TrialId = trialId,
RequestBackStateEnum = context.Message.RequestBackState,
};
await SendImageReuploadEmail(inDto);
}
}
/// <summary>
/// 处理质疑CRC申请重传事件
/// </summary>
public async Task Consume(ConsumeContext<QCChanllengeReuploadEvent> context)
{
Console.WriteLine("发送【影像质疑-影像重传】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var subjectVisitId = context.Message.SubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).FirstNotNullAsync();
var trialId = subjectVisit.TrialId;
// 根据状态确定邮件场景
EmailBusinessScenario scenario;
switch (context.Message.ReuploadEnum)
{
case QCChanllengeReuploadEnum.CRCRequestReupload:
scenario = EmailBusinessScenario.ImageQueryCRCApplyRe_Uploading; // 60
break;
case QCChanllengeReuploadEnum.QCAgreeUpload:
scenario = EmailBusinessScenario.ImageQuery_IQCApprovalRe_Uploading; // 61
break;
default:
return; // 其他状态不发送邮件
}
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault();
if (emailConfig != null)
{
var inDto = new SendImageReuploadEmailInDto
{
EmailNoticeConfig = emailConfig,
Scenario = scenario,
SubjectVisit = subjectVisit,
TrialId = trialId
};
await SendImageReuploadEmail(inDto);
}
}
/// <summary>
/// 处理已阅任务重阅申请事件
/// </summary>
public async Task Consume(ConsumeContext<HaveReadVisitTaskReReading> context)
{
Console.WriteLine("发送【重阅-影像重传】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var visitTaskId = context.Message.VisitTaskId;
// 获取VisitTask关联的SubjectVisit
var visitTask = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x => x.Subject).Include(x => x.SourceSubjectVisit).FirstNotNullAsync();
var subjectVisit = new SubjectVisit() { };
if (visitTask.SourceSubjectVisitId != null)
{
subjectVisit = visitTask.SourceSubjectVisit;
}
else if (visitTask.SouceReadModuleId != null)
{
var readModule = await _readModuleRepository.Where(x => x.Id == visitTask.SouceReadModuleId).Include(x => x.SubjectVisit).FirstOrDefaultAsync();
subjectVisit = readModule.SubjectVisit;
}
var trialId = subjectVisit.TrialId;
// 根据状态确定邮件场景
EmailBusinessScenario scenario;
switch (context.Message.ReReadingApplyState)
{
case ReReadingApplyState.TrialGroupHaveApplyed:
scenario = EmailBusinessScenario.ReadTracking_PMApplyRe_Reading; // 67
break;
case ReReadingApplyState.Agree:
case ReReadingApplyState.Reject:
scenario = EmailBusinessScenario.Re_ReadApproval_SPMCPMApprovalRe_Reading; // 68
break;
default:
return; // 其他状态不发送邮件
}
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault();
if (emailConfig != null)
{
var inDto = new SendImageReuploadEmailInDto
{
EmailNoticeConfig = emailConfig,
Scenario = scenario,
SubjectVisit = subjectVisit,
TrialId = trialId,
ReReadingApplyState= context.Message.ReReadingApplyState,
};
await SendImageReuploadEmail(inDto);
}
}
/// <summary>
/// 发送影像重传相关邮件的通用方法
/// </summary>
private async Task SendImageReuploadEmail(SendImageReuploadEmailInDto inDto)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
inDto.SubjectVisit = await _subjectVisitRepository.Where(x => x.Id == inDto.SubjectVisit.Id).Include(x => x.Subject).FirstNotNullAsync();
// 获取项目信息
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == inDto.TrialId);
// 根据不同场景获取不同角色的用户
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == inDto.TrialId && !x.TrialUser.IsDeleted).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
// 根据场景确定收件人
List<UserRole> toUserList = new List<UserRole>();
List<UserRole> ccUserList = new List<UserRole>();
var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == inDto.EmailNoticeConfig.Id).ToListAsync();
var userTypeEnum = emailNoticeUserList.Select(x => x.UserType).ToList();
if (inDto.UserTypes != null)
{
userTypeEnum = inDto.UserTypes;
}
var crcUserList = new List<UserRole>() { };
if (userTypeEnum.Contains(UserTypeEnum.ClinicalResearchCoordinator))
{
crcUserList = await _trialSiteRepository.Where(x => x.Id == inDto.SubjectVisit.TrialSiteId).SelectMany(x => x.CRCUserList.Select(y => y.UserRole)).ToListAsync();
}
if (inDto.UserTypes == null)
{
var toList = emailNoticeUserList.Where(x => x.EmailUserType == EmailUserType.To && x.UserType != UserTypeEnum.ClinicalResearchCoordinator).Select(x => x.UserType).ToList();
toUserList = trialUser.Where(x => toList.Contains(x.UserTypeEnum)).ToList();
if (emailNoticeUserList.Any(x => x.EmailUserType == EmailUserType.To && x.UserType == UserTypeEnum.ClinicalResearchCoordinator))
{
toUserList.AddRange(crcUserList);
}
}
else
{
var toList = inDto.UserTypes.Where(x => x != UserTypeEnum.ClinicalResearchCoordinator).ToList();
toUserList = trialUser.Where(x => toList.Contains(x.UserTypeEnum)).ToList();
if (inDto.UserTypes.Any(x => x == UserTypeEnum.ClinicalResearchCoordinator))
{
toUserList.AddRange(crcUserList);
}
}
var ccList = emailNoticeUserList.Where(x => x.EmailUserType == EmailUserType.Copy && x.UserType != UserTypeEnum.ClinicalResearchCoordinator).Select(x => x.UserType).ToList();
ccUserList = trialUser.Where(x => ccList.Contains(x.UserTypeEnum)).ToList();
if (emailNoticeUserList.Any(x => x.EmailUserType == EmailUserType.Copy && x.UserType == UserTypeEnum.ClinicalResearchCoordinator))
{
ccUserList.AddRange(crcUserList);
}
// 如果没有收件人,则不发送邮件
if (toUserList.Count == 0)
{
return;
}
List<DictionaryDto> dictionaryDtos = new List<DictionaryDto>() {
new DictionaryDto (){DictionaryCode= "YesOrNo",EnumValue=inDto.SubjectVisit.IsUrgent.ToString().ToLower(), }, //是否加急
};
switch (inDto.Scenario)
{
case EmailBusinessScenario.Re_ReadApproval_SPMCPMApprovalRe_Reading:
dictionaryDtos.Add(new DictionaryDto() { DictionaryCode = "ReReadingApplyState", EnumValue = inDto.ReReadingApplyState.GetEnumInt(), });
break;
case EmailBusinessScenario.DataReconciliation_PMApprovalRe_Uploading:
dictionaryDtos.Add(new DictionaryDto() { DictionaryCode = "RequestBackState", EnumValue = inDto.RequestBackStateEnum.GetEnumInt(), });
break;
default:
dictionaryDtos.Add(new DictionaryDto() { DictionaryCode = "ImageBackStateEnum", EnumValue = inDto.ImageBackStateEnum.GetEnumInt(), });//审批结果
break;
}
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = dictionaryDtos
});
foreach (var userinfo in toUserList)
{
var messageToSend = new MimeMessage();
// 发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
// 添加抄送
foreach (var ccUser in ccUserList)
{
messageToSend.Cc.Add(new MailboxAddress(String.Empty, ccUser.EMail));
}
// 格式化邮件内容
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = inDto.SubjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, inDto.SubjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
inDto.SubjectVisit.VisitName, // 访视 {3}
dictionValue[0], // 是否加急 {4}
dictionValue[1], // 审批结果 {5}
_systemEmailConfig.SiteUrl // 链接 {6}
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(inDto.EmailNoticeConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
/// <summary>
/// 处理PM申请阅片人筛选事件
/// </summary>
public async Task Consume(ConsumeContext<ReviewerPMApplyEvent> context)
{
Console.WriteLine("发送【阅片人筛选-PM申请审批】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
// 获取项目信息
var enrollIdList = context.Message.EnrollIdList;
if (enrollIdList == null || !enrollIdList.Any())
{
return;
}
// 获取第一个Enroll的TrialId
var enrollId = enrollIdList.First();
var enroll = await _enrollRepository.Where(x => x.Id == enrollId).FirstNotNullAsync();
var trialId = enroll.TrialId;
// 设置邮件场景
var scenario = EmailBusinessScenario.ReviewerSelection_PMApplyApproving; // 69
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault();
if (emailConfig != null)
{
await SendReviewerSelectionEmail(emailConfig, trialId, enrollIdList);
}
}
/// <summary>
/// 处理SPM审批阅片人筛选事件
/// </summary>
public async Task Consume(ConsumeContext<ReviewerSPMApprovedEvent> context)
{
Console.WriteLine("发送【阅片人筛选-SPM审批】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
// 获取项目信息
var enrollIdList = context.Message.EnrollIdList;
if (enrollIdList == null || !enrollIdList.Any())
{
return;
}
// 获取第一个Enroll的TrialId
var enrollId = enrollIdList.First();
var enroll = await _enrollRepository.Where(x => x.Id == enrollId).FirstNotNullAsync();
var trialId = enroll.TrialId;
// 设置邮件场景
var scenario = EmailBusinessScenario.ReviewerSelection_SPMCPMApproval; // 70
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault();
if (emailConfig != null)
{
await SendReviewerSelectionEmail(emailConfig, trialId, enrollIdList);
}
}
/// <summary>
/// 发送阅片人筛选相关邮件的通用方法
/// </summary>
private async Task SendReviewerSelectionEmail(EmailNoticeConfig emailNoticeConfig, Guid trialId, List<Guid> enrollIdList)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
// 获取项目信息
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
// 根据不同场景获取不同角色的用户
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == trialId && !x.TrialUser.IsDeleted).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
// 根据场景确定收件人
List<UserRole> toUserList = new List<UserRole>();
List<UserRole> ccUserList = new List<UserRole>();
var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == emailNoticeConfig.Id).ToListAsync();
var toList = emailNoticeUserList.Where(x => x.EmailUserType == EmailUserType.To).Select(x => x.UserType).ToList();
toUserList = trialUser.Where(x => toList.Contains(x.UserTypeEnum)).ToList();
var ccList = emailNoticeUserList.Where(x => x.EmailUserType == EmailUserType.Copy && x.UserType != UserTypeEnum.ClinicalResearchCoordinator).Select(x => x.UserType).ToList();
ccUserList = trialUser.Where(x => ccList.Contains(x.UserTypeEnum)).ToList();
// 如果没有收件人,则不发送邮件
if (toUserList.Count == 0)
{
return;
}
foreach (var userinfo in toUserList)
{
var messageToSend = new MimeMessage();
// 发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
// 添加抄送
foreach (var ccUser in ccUserList)
{
messageToSend.Cc.Add(new MailboxAddress(String.Empty, ccUser.EMail));
}
// 格式化邮件内容
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
"", // 受试者 {2} - 阅片人筛选不涉及受试者
"", // 访视 {3} - 阅片人筛选不涉及访视
"", // 是否加急 {4}
"", // 预留 {5}
_systemEmailConfig.SiteUrl // 链接 {6}
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailNoticeConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
@@ -29,7 +29,7 @@ public class UrgentMedicalReviewAddedEventConsumer(
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig
) : IConsumer<UrgentMedicalReviewAddedEvent>
{
@@ -48,52 +48,62 @@ public class UrgentMedicalReviewAddedEventConsumer(
var medicalReviewId = context.Message.MedicalReviewId;
var medicalReview = await _taskMedicalReviewRepository.Where(x => x.Id == medicalReviewId).Include(x => x.VisitTask).Include(x=>x.MedicalManagerUser).FirstOrDefaultAsync();
var medicalReview = await _taskMedicalReviewRepository.Where(x => x.Id == medicalReviewId).Include(x => x.VisitTask).Include(x => x.MedicalManagerUser).FirstOrDefaultAsync();
if (medicalReview.MedicalManagerUserId == null)
{
Console.WriteLine("MIMId为空 ID"+ medicalReviewId);
Console.WriteLine("MIMId为空 ID" + medicalReviewId);
return;
}
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).FirstOrDefaultAsync();
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x=>x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
var trialId = medicalReview.TrialId;
var scenario = context.Message.IsPD ? EmailBusinessScenario.PDVerification_MedicalQC : EmailBusinessScenario.EligibilityVerification_MedicalQC;
var visitid = taskInfo.SourceSubjectVisit == null ? taskInfo.ReadModule.SubjectVisitId : taskInfo.SourceSubjectVisitId;
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
if (trialEmailConfig != null)
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).FirstOrDefaultAsync();
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
DictionaryList = new List<DictionaryDto>()
{
var visitid = taskInfo.SourceSubjectVisit == null ? taskInfo.ReadModule.SubjectVisitId : taskInfo.SourceSubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= "ReadingCategory",EnumValue=taskInfo.ReadingCategory.GetEnumInt(), },
new DictionaryDto (){DictionaryCode= "MedicalReviewDoctorUserIdea",EnumValue=medicalReview.DoctorUserIdeaEnum.GetEnumInt(), },
new DictionaryDto (){DictionaryCode= "MedicalReviewAuditState",EnumValue=medicalReview.AuditState.GetEnumInt(), },
new DictionaryDto (){DictionaryCode= "YesOrNo",EnumValue=taskInfo.IsUrgent.ToString().ToLower(), }
}
}) ;
});
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
@@ -107,7 +117,7 @@ public class UrgentMedicalReviewAddedEventConsumer(
subjectName, // 受试者 {3}
taskInfo.TaskBlindName, // 访视 {4}
dictionValue[0], // 任务类型 {5}
//dictionValue[1], // 阅片人是否同意 {6}
//dictionValue[1], // 阅片人是否同意 {6}
dictionValue[2], // 审核状态 {6}
dictionValue[3], // 是否加急 {7}
_systemEmailConfig.SiteUrl // 链接 {8}
@@ -116,13 +126,12 @@ public class UrgentMedicalReviewAddedEventConsumer(
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
context.Message.IsPD ? EmailBusinessScenario.PDVerification_MedicalQC : EmailBusinessScenario.EligibilityVerification_MedicalQC,
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
@@ -135,7 +144,7 @@ public class UrgentIRRepliedMedicalReviewConsumer(
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<UrgentIRRepliedMedicalReview>
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
@@ -151,79 +160,85 @@ public class UrgentIRRepliedMedicalReviewConsumer(
var medicalReview = await _taskMedicalReviewRepository.Where(x => x.Id == medicalReviewId).Include(x => x.VisitTask).Include(x => x.MedicalManagerUser).FirstOrDefaultAsync();
if (medicalReview.MedicalManagerUserId == null)
{
Console.WriteLine("MIMId为空 ID" + medicalReviewId);
return;
}
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).FirstOrDefaultAsync();
var trialId = medicalReview.TrialId;
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
var scenario = context.Message.IsPD ? EmailBusinessScenario.PDVerification_ExpeditedMedicalQCResponse : EmailBusinessScenario.EligibilityVerification_ExpeditedMedicalQCResponse;
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
var visitid = taskInfo.SourceSubjectVisit == null ? taskInfo.ReadModule.SubjectVisitId : taskInfo.SourceSubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
if (trialEmailConfig != null)
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).FirstOrDefaultAsync();
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
DictionaryList = new List<DictionaryDto>()
var visitid = taskInfo.SourceSubjectVisit == null ? taskInfo.ReadModule.SubjectVisitId : taskInfo.SourceSubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= "ReadingCategory",EnumValue=taskInfo.ReadingCategory.GetEnumInt(), },
new DictionaryDto (){DictionaryCode= "MedicalReviewDoctorUserIdea",EnumValue=medicalReview.DoctorUserIdeaEnum.GetEnumInt(), },
new DictionaryDto (){DictionaryCode= "MedicalReviewAuditState",EnumValue=medicalReview.AuditState.GetEnumInt(), },
new DictionaryDto (){DictionaryCode= "YesOrNo",EnumValue=taskInfo.IsUrgent.ToString().ToLower(), }
}
});
});
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
criterion.CriterionName, // 阅片标准 {2}
subjectCode, // 受试者 {3}
taskInfo.TaskBlindName, // 访视 {4}
dictionValue[0], // 任务类型 {5}
dictionValue[1], // 阅片人是否同意 {6}
dictionValue[2], // 审核状态 {7}
dictionValue[3], // 是否加急 {8}
_systemEmailConfig.SiteUrl // 链接 {9}
);
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
criterion.CriterionName, // 阅片标准 {2}
subjectCode, // 受试者 {3}
taskInfo.TaskBlindName, // 访视 {4}
dictionValue[0], // 任务类型 {5}
dictionValue[1], // 阅片人是否同意 {6}
dictionValue[2], // 审核状态 {7}
dictionValue[3], // 是否加急 {8}
_systemEmailConfig.SiteUrl // 链接 {9}
);
return (topicStr, htmlBodyStr);
};
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
context.Message.IsPD ? EmailBusinessScenario.PDVerification_ExpeditedMedicalQCResponse : EmailBusinessScenario.EligibilityVerification_ExpeditedMedicalQCResponse,
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
@@ -238,7 +253,7 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<UrgentMIMRepliedMedicalReview>
{
@@ -254,91 +269,93 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
Console.WriteLine("发送(022) 【加急医学反馈】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var medicalReviewId = context.Message.MedicalReviewId;
var medicalReview = await _taskMedicalReviewRepository.Where(x => x.Id == medicalReviewId).Include(x => x.VisitTask).Include(x => x.MedicalManagerUser).FirstOrDefaultAsync();
if (medicalReview.MedicalManagerUserId == null)
{
Console.WriteLine("MIMId为空 ID" + medicalReviewId);
return;
}
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
var userinfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).FirstOrDefaultAsync();
var trialId = medicalReview.TrialId;
var scenario = EmailBusinessScenario.ExpeditedMedicalQCToIR;
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
var visitid = taskInfo.SourceSubjectVisit == null ? taskInfo.ReadModule.SubjectVisitId : taskInfo.SourceSubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
if (trialEmailConfig != null)
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
var userinfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).FirstOrDefaultAsync();
DictionaryList = new List<DictionaryDto>()
var visitid = taskInfo.SourceSubjectVisit == null ? taskInfo.ReadModule.SubjectVisitId : taskInfo.SourceSubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= "ReadingCategory",EnumValue=taskInfo.ReadingCategory.GetEnumInt(), },
new DictionaryDto (){DictionaryCode= "IsPass",EnumValue=medicalReview.IsHaveQuestion.ToString().ToLower(), },// 审核结论
new DictionaryDto (){DictionaryCode= "AuditAdvice",EnumValue=medicalReview.AuditAdviceEnum.GetEnumInt(), },// 审核建议
new DictionaryDto (){DictionaryCode= "YesOrNo",EnumValue=taskInfo.IsUrgent.ToString().ToLower(), }, //是否加急
new DictionaryDto (){DictionaryCode= "YesOrNo",EnumValue=taskInfo.IsUrgent.ToString().ToLower(), }, //是否加急
}
});
});
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
taskInfo.TaskBlindName, // 访视 {3}
criterion.CriterionName, // 阅片标准 {4}
dictionValue[0], // 任务类型 {5}
dictionValue[1], // 审核结论 {6}
dictionValue[2], // 医学审核建议 {7}
dictionValue[3], // 是否加急 {8}
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
taskInfo.TaskBlindName, // 访视 {3}
criterion.CriterionName, // 阅片标准 {4}
dictionValue[0], // 任务类型 {5}
dictionValue[1], // 审核结论 {6}
dictionValue[2], // 医学审核建议 {7}
dictionValue[3], // 是否加急 {8}
_systemEmailConfig.SiteUrl // 链接 {9}
);
_systemEmailConfig.SiteUrl // 链接 {9}
);
return (topicStr, htmlBodyStr);
};
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
EmailBusinessScenario.ExpeditedMedicalQCToIR,
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
@@ -354,7 +371,7 @@ public class UrgentIRApplyedReReadingConsumer(
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<UrgentApplyedReReading>
{
@@ -367,82 +384,90 @@ public class UrgentIRApplyedReReadingConsumer(
var visitTaskId = context.Message.VisitTaskId;
var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == taskInfo.TrialReadingCriterionId);
var doctorInfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).FirstOrDefaultAsync();
var trialId=taskInfo.TrialId;
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == taskInfo.TrialId).Include(x => x.UserRole).Select(x=>x.UserRole).ToListAsync();
var scenario = context.Message.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed ? EmailBusinessScenario.ReReadFromPMApproval : EmailBusinessScenario.ReReadFromIRApproval;
var userinfoList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.ProjectManager||x.UserTypeEnum==UserTypeEnum.APM).ToList();
if (context.Message.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (trialEmailConfig != null)
{
userinfoList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.CPM || x.UserTypeEnum == UserTypeEnum.SPM).ToList();
}
var visitid = taskInfo.SourceSubjectVisit == null ? taskInfo.ReadModule.SubjectVisitId : taskInfo.SourceSubjectVisitId;
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == taskInfo.TrialReadingCriterionId);
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
var doctorInfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).FirstOrDefaultAsync();
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == taskInfo.TrialId && x.TrialUser.IsDeleted==false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == taskInfo.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ProjectManager || x.UserTypeEnum == UserTypeEnum.APM).ToList();
if (context.Message.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)
{
userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.CPM || x.UserTypeEnum == UserTypeEnum.SPM).ToList();
}
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
var visitid = taskInfo.SourceSubjectVisit == null ? taskInfo.ReadModule.SubjectVisitId : taskInfo.SourceSubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == taskInfo.TrialId);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= "ReadingCategory",EnumValue=taskInfo.ReadingCategory.GetEnumInt(), }, //任务类型
new DictionaryDto (){DictionaryCode= "RequestReReadingResult",EnumValue="0", }, //审批结果 都是待审批
}
});
});
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
taskInfo.TaskBlindName, // 访视 {3}
dictionValue[0], // 任务类型 {4}
doctorInfo.FullName, // 阅片人 {5}
criterion.CriterionName, // 阅片标准 {6}
dictionValue[1], // 审批结果 {7}
_systemEmailConfig.SiteUrl // 链接 {8}
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
taskInfo.TaskBlindName, // 访视 {3}
dictionValue[0], // 任务类型 {4}
doctorInfo.FullName, // 阅片人 {5}
criterion.CriterionName, // 阅片标准 {6}
dictionValue[1], // 审批结果 {7}
_systemEmailConfig.SiteUrl // 链接 {8}
);
);
return (topicStr, htmlBodyStr);
};
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
context.Message.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed? EmailBusinessScenario.ReReadFromPMApproval: EmailBusinessScenario.ReReadFromIRApproval,
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
}
@@ -25,7 +25,7 @@ using System.Threading.Tasks;
namespace IRaCIS.Core.Application.MassTransit.Consumer;
/// <summary>
/// 用户提交 发送邮件 通知SPM 或者PM
/// 用户提交 发送邮件 通知SPM 或者PM 项目默认邮件,不用添加到项目中,直接发送的
/// </summary>
public class UserSiteSurveySubmitedEventConsumer(
IRepository<Trial> _trialRepository,
@@ -47,75 +47,83 @@ public class UserSiteSurveySubmitedEventConsumer(
var trialId = siteSurveyInfo.TrialId;
var trialUserList = await _trialUserRoleRepository.Where(t => t.TrialId == siteSurveyInfo.TrialId)
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM)
.Select(t => new { t.UserRole.FullName, t.UserRole.IdentityUser.EMail, t.UserRole.UserTypeEnum }).ToListAsync();
var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList();
var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList();
var messageToSend = new MimeMessage();
var toUserName = string.Empty;
//有SPM
if (sPMOrCPMList.Count > 0)
{
foreach (var user in sPMOrCPMList)
{
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
}
toUserName = string.Join('、', sPMOrCPMList.Select(t => t.FullName));
foreach (var user in pmAndAPMList)
{
messageToSend.Cc.Add(new MailboxAddress(user.FullName, user.EMail));
}
}
else
{
foreach (var user in pmAndAPMList)
{
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
}
toUserName = string.Join('、', pmAndAPMList.Select(t => t.FullName));
}
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
toUserName,
siteInfo.TrialSiteCode,
siteInfo.TrialSiteAliasName,
siteSurveyInfo.UserName,
siteSurveyInfo.Email,
siteSurveyInfo.Phone,
_systemEmailConfig.SiteUrl
);
return (topicStr, htmlBodyStr);
};
var scenario = _trialSiteSurveyRepository.Where(t => t.Id != trialSiteSurveyId && t.TrialId == siteSurveyInfo.TrialId && t.TrialSiteId == siteSurveyInfo.TrialSiteId).IgnoreQueryFilters().Any() ?
EmailBusinessScenario.Approval_UpdateSiteSurvey : EmailBusinessScenario.Approval_SubmitSiteSurvey;
EmailBusinessScenario.Approval_UpdateSiteSurvey : EmailBusinessScenario.Approval_SubmitSiteSurvey;
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository, scenario, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig != null)
{
var trialUserList = await _trialUserRoleRepository.Where(t => t.TrialId == siteSurveyInfo.TrialId && t.TrialUser.IsDeleted == false)
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM)
.Select(t => new { t.UserRole.FullName, t.UserRole.IdentityUser.EMail, t.UserRole.UserTypeEnum }).ToListAsync();
var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList();
var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList();
var messageToSend = new MimeMessage();
var toUserName = string.Empty;
//有SPM
if (sPMOrCPMList.Count > 0)
{
foreach (var user in sPMOrCPMList)
{
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
}
toUserName = string.Join('、', sPMOrCPMList.Select(t => t.FullName));
foreach (var user in pmAndAPMList)
{
messageToSend.Cc.Add(new MailboxAddress(user.FullName, user.EMail));
}
}
else
{
foreach (var user in pmAndAPMList)
{
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
}
toUserName = string.Join('、', pmAndAPMList.Select(t => t.FullName));
}
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
toUserName,
siteInfo.TrialSiteCode,
siteInfo.TrialSiteAliasName,
siteSurveyInfo.UserName,
siteSurveyInfo.Email,
siteSurveyInfo.Phone,
_systemEmailConfig.SiteUrl
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
@@ -143,55 +151,65 @@ public class SiteSurveySPMSubmitedEventConsumer(
var trialId = siteSurveyInfo.TrialId;
var messageToSend = new MimeMessage();
var scenario = EmailBusinessScenario.Approval_SubmitSiteSurvey;
var trialUserList = _trialUserRoleRepository.Where(t => t.TrialId == trialId)
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM)
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum }).ToList();
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList();
var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList();
var toUserName = string.Empty;
foreach (var item in pmAndAPMList)
if (emailConfig != null)
{
messageToSend.To.Add(new MailboxAddress(item.FullName, item.EMail));
var messageToSend = new MimeMessage();
toUserName = string.Join('、', pmAndAPMList.Select(t => t.FullName));
var trialUserList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.IsDeleted == false)
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM)
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum }).ToList();
var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList();
var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList();
var toUserName = string.Empty;
foreach (var item in pmAndAPMList)
{
messageToSend.To.Add(new MailboxAddress(item.FullName, item.EMail));
toUserName = string.Join('、', pmAndAPMList.Select(t => t.FullName));
}
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
toUserName,
siteInfo.TrialSiteCode, //中心编号
siteInfo.TrialSiteAliasName,//中心名称
siteSurveyInfo.UserName, //联系人
siteSurveyInfo.Email, //联系邮箱
siteSurveyInfo.Phone, //联系电话
_systemEmailConfig.SiteUrl
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
toUserName,
siteInfo.TrialSiteCode,
siteInfo.TrialSiteAliasName,
siteSurveyInfo.UserName,
siteSurveyInfo.Email,
siteSurveyInfo.Phone,
_systemEmailConfig.SiteUrl
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository, EmailBusinessScenario.Approval_SubmitSiteSurvey, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
@@ -204,7 +222,7 @@ public class SiteSurverRejectedEventConsumer(
IRepository<Trial> _trialRepository,
IRepository<TrialSite> _trialSiteRepository,
IRepository<TrialSiteSurvey> _trialSiteSurveyRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig
) : IConsumer<SiteSurverRejectedEvent>
{
@@ -216,83 +234,95 @@ public class SiteSurverRejectedEventConsumer(
var trialSiteSurveyId = context.Message.TrialSiteSurveyId;
var siteSurveyInfo = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId).FirstOrDefault().IfNullThrowException();
var siteSurveyInfo = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId ,ignoreQueryFilters:true).FirstOrDefault().IfNullThrowException();
var trialId = siteSurveyInfo.TrialId;
var messageToSend = new MimeMessage();
var scenario = EmailBusinessScenario.SiteSurveyReject;
var toUserName = siteSurveyInfo.UserName;
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (context.Message.IsHaveSPMOrCPM)
if (emailConfig != null)
{
//PM 驳回到SPM
if (siteSurveyInfo.State == TrialSiteSurveyEnum.CRCSubmitted)
var messageToSend = new MimeMessage();
var toUserName = siteSurveyInfo.UserName;
if (context.Message.IsHaveSPMOrCPM)
{
//var user = await _userRoleRepository.FirstOrDefaultAsync(t => t.Id == siteSurveyInfo.PreliminaryUserId);
//name = user.FullName;
var sPMOrCPMList = _trialUserRoleRepository.Where(t => t.TrialId == trialId)
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM)
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum }).ToList();
foreach (var user in sPMOrCPMList)
//PM 驳回到SPM
if (siteSurveyInfo.State == TrialSiteSurveyEnum.CRCSubmitted)
{
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
//var user = await _userRoleRepository.FirstOrDefaultAsync(t => t.Id == siteSurveyInfo.PreliminaryUserId);
//name = user.FullName;
var sPMOrCPMList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.IsDeleted == false)
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM)
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum }).ToList();
foreach (var user in sPMOrCPMList)
{
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
}
toUserName = string.Join('、', sPMOrCPMList.Select(t => t.FullName));
}
//SPM 驳回到CRC
else if (siteSurveyInfo.State == TrialSiteSurveyEnum.ToSubmit)
{
messageToSend.To.Add(new MailboxAddress(toUserName, siteSurveyInfo.Email));
}
toUserName = string.Join('、', sPMOrCPMList.Select(t => t.FullName));
}
//SPM 驳回到CRC
else if (siteSurveyInfo.State == TrialSiteSurveyEnum.ToSubmit)
else
{
messageToSend.To.Add(new MailboxAddress(toUserName, siteSurveyInfo.Email));
//没有SPM PM驳回到CRC
messageToSend.To.Add(new MailboxAddress(String.Empty, siteSurveyInfo.Email));
}
}
else
{
//没有SPM PM驳回到CRC
messageToSend.To.Add(new MailboxAddress(String.Empty, siteSurveyInfo.Email));
}
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
toUserName,
trialInfo.TrialCode,
trialInfo.ResearchProgramNo,
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var topicStr = string.Format(input.topicStr, companyName,trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
toUserName,
trialInfo.TrialCode,
trialInfo.ResearchProgramNo,
trialInfo.ExperimentName,
siteInfo.TrialSiteCode,
siteInfo.TrialSiteAliasName,
siteSurveyInfo.LatestBackReason,
_systemEmailConfig.SiteUrl,
(siteSurveyInfo.State == TrialSiteSurveyEnum.ToSubmit ? "inline - block" : "none")
);
return (topicStr, htmlBodyStr);
};
siteInfo.TrialSiteCode, //中心编号
siteInfo.TrialSiteAliasName,//中心名称
siteSurveyInfo.LatestBackReason, //驳回原因
_systemEmailConfig.SiteUrl, //链接
(siteSurveyInfo.State == TrialSiteSurveyEnum.ToSubmit ? "inline - block" : "none")
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository, EmailBusinessScenario.SiteSurveyReject, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
@@ -24,13 +24,13 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer;
/// </summary>
public class CRCSubmitedAndQCToAuditEventConsumer(
IRepository<UserRole> _userRoleRepository,
IRepository<TrialUserRole> _trialUseRoleRepository,
IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<TrialUserRole> _trialUseRoleRepository,
IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<Trial> _trialRepository,
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<CRCSubmitedAndQCToAuditEvent>
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
@@ -41,46 +41,55 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
var subjectVisitId = context.Message.SubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).FirstOrDefaultAsync();
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).FirstNotNullAsync();
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var trialId = subjectVisit.TrialId;
var userinfoList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).ToList();
var scenario = context.Message.IsPd ? EmailBusinessScenario.PDVerification_PendingImageQCClaim : EmailBusinessScenario.EligibilityVerification_PendingClaim;
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
var pmandAPm = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var auditStateCode = "AuditStatePE";
if (trialInfo.QCProcessEnum == TrialQCProcess.DoubleAudit)
{
auditStateCode = "AuditStateRC";
}
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
if (trialEmailConfig != null)
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).ToList();
var pmandAPm = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var auditStateCode = "AuditStatePE";
if (trialInfo.QCProcessEnum == TrialQCProcess.DoubleAudit)
{
auditStateCode = "AuditStateRC";
}
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= auditStateCode,EnumValue=subjectVisit.AuditState.GetEnumInt(), }, //审核状态
}
});
});
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
foreach (var userinfo in userinfoList)
{
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
}
var userNames = userinfoList.Select(x => x.FullName).ToList();
@@ -111,14 +120,11 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
context.Message.IsPd ? EmailBusinessScenario.PDVerification_PendingImageQCClaim : EmailBusinessScenario.EligibilityVerification_PendingClaim,
messageToSend, emailConfigFunc);
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
@@ -134,7 +140,7 @@ public class CRCRepliedQCChallengeEventConsumer(
IRepository<QCChallenge> _qCChallengeRepository,
IRepository<QCChallengeDialog> _qCChallengeDialogRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<CRCRepliedQCChallengeEvent>
{
@@ -148,74 +154,75 @@ public class CRCRepliedQCChallengeEventConsumer(
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).Include(x => x.CurrentActionUser).FirstNotNullAsync();
var trialId = subjectVisit.TrialId;
var qCChallengeDialog = await _qCChallengeDialogRepository.Where(x => x.Id == context.Message.QCChallengeDialogId).Include(x => x.QCChallenge).FirstNotNullAsync();
var scenario = context.Message.IsPd ? EmailBusinessScenario.PDVerification_UnderQCQuery : EmailBusinessScenario.EligibilityVerification_Pending;
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var userinfoList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).ToList();
var pmandAPm = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var userinfo = subjectVisit.CurrentActionUser;
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
foreach (var pm in pmandAPm)
{
messageToSend.Cc.Add(new MailboxAddress(String.Empty, pm.EMail));
}
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
if (trialEmailConfig != null)
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
var qCChallengeDialog = await _qCChallengeDialogRepository.Where(x => x.Id == context.Message.QCChallengeDialogId).Include(x => x.QCChallenge).FirstNotNullAsync();
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).ToList();
var pmandAPm = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var userinfo = subjectVisit.CurrentActionUser;
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
foreach (var pm in pmandAPm)
{
messageToSend.Cc.Add(new MailboxAddress(String.Empty, pm.EMail));
}
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= "YesOrNo",EnumValue=qCChallengeDialog.QCChallenge.IsClosed.ToString().ToLower(), }, //是否关闭
}
});
});
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3}
dictionValue[0], // 是否关闭 {4}
qCChallengeDialog.TalkContent, // 质疑内容{5}
_systemEmailConfig.SiteUrl // 链接 {6}
);
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3}
dictionValue[0], // 是否关闭 {4}
qCChallengeDialog.TalkContent, // 质疑内容{5}
_systemEmailConfig.SiteUrl // 链接 {6}
);
return (topicStr, htmlBodyStr);
};
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
context.Message.IsPd ? EmailBusinessScenario.PDVerification_UnderQCQuery : EmailBusinessScenario.EligibilityVerification_Pending,
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
@@ -231,7 +238,7 @@ public class QCRepliedQCChallengeEventConsumer(
IRepository<QCChallenge> _qCChallengeRepository,
IRepository<QCChallengeDialog> _qCChallengeDialogRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<QCRepliedQCChallengeEvent>
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
@@ -240,90 +247,100 @@ public class QCRepliedQCChallengeEventConsumer(
Console.WriteLine("发送(014015) 【 QC回复 质控质疑,通知CRC】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
string talkContent = string.Empty;
var isclose = false;
if (context.Message.QCChallengeDialogId != null)
{
var qCChallengeDialog = await _qCChallengeDialogRepository.Where(x => x.Id == context.Message.QCChallengeDialogId.Value).Include(x => x.QCChallenge).FirstNotNullAsync();
talkContent = qCChallengeDialog.TalkContent;
isclose = qCChallengeDialog.QCChallenge.IsClosed;
}
else if(context.Message.QCChallengeId != null)
{
var qCChallenge = await _qCChallengeRepository.Where(x => x.Id == context.Message.QCChallengeId.Value).FirstNotNullAsync();
talkContent = qCChallenge.Content;
isclose = qCChallenge.IsClosed;
}
var subjectVisitId = context.Message.SubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).FirstNotNullAsync();
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var trialId = subjectVisit.TrialId;
var userinfoList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).ToList();
var scenario = context.Message.IsPd ? EmailBusinessScenario.PDVerification_ImageQuery : EmailBusinessScenario.EligibilityVerification_ImageQuery;
var craInfo = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).FirstOrDefault();
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
if (trialEmailConfig != null)
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
string talkContent = string.Empty;
var isclose = false;
if (context.Message.QCChallengeDialogId != null)
{
var qCChallengeDialog = await _qCChallengeDialogRepository.Where(x => x.Id == context.Message.QCChallengeDialogId.Value).Include(x => x.QCChallenge).FirstNotNullAsync();
talkContent = qCChallengeDialog.TalkContent;
isclose = qCChallengeDialog.QCChallenge.IsClosed;
}
else if (context.Message.QCChallengeId != null)
{
var qCChallenge = await _qCChallengeRepository.Where(x => x.Id == context.Message.QCChallengeId.Value).FirstNotNullAsync();
talkContent = qCChallenge.Content;
isclose = qCChallenge.IsClosed;
}
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).ToList();
var craInfo = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).FirstOrDefault();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= "YesOrNo",EnumValue=isclose.ToString().ToLower(), }, //是否关闭
}
});
});
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
if (craInfo != null)
foreach (var userinfo in userinfoList)
{
messageToSend.Cc.Add(new MailboxAddress(String.Empty, craInfo.EMail));
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
if (craInfo != null)
{
messageToSend.Cc.Add(new MailboxAddress(String.Empty, craInfo.EMail));
}
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3}
dictionValue[0], // 质疑是否关闭 {4}
talkContent, // 质疑内容 {5}
_systemEmailConfig.SiteUrl // 链接 {65}
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3}
dictionValue[0], // 质疑是否关闭 {4}
talkContent, // 质疑内容 {5}
_systemEmailConfig.SiteUrl // 链接 {65}
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
context.Message.IsPd ? EmailBusinessScenario.PDVerification_ImageQuery : EmailBusinessScenario.EligibilityVerification_ImageQuery,
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
@@ -340,7 +357,7 @@ public class CRCRepliedCheckChallengeEventConsumer(
IRepository<QCChallenge> _qCChallengeRepository,
IRepository<QCChallengeDialog> _qCChallengeDialogRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<CRCRepliedCheckChallengeEvent>
{
@@ -350,70 +367,80 @@ public class CRCRepliedCheckChallengeEventConsumer(
Console.WriteLine("发送(019,020) 【 CRC 回复一致性核查质疑 通知PM】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var subjectVisitId = context.Message.SubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).FirstNotNullAsync();
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var trialId = subjectVisit.TrialId;
var userinfoList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var scenario = context.Message.IsPd ? EmailBusinessScenario.PDVerification_UnderDRForPMOrAPM : EmailBusinessScenario.EligibilityVerification_UnderDRForPMOrAPM;
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
if (trialEmailConfig != null)
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= "CheckState",EnumValue=subjectVisit.CheckState.GetEnumInt(), }, //审核状态
}
});
});
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
foreach (var userinfo in userinfoList)
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3}
dictionValue[0], // 核查状态 {4}
_systemEmailConfig.SiteUrl // 链接 {5}
);
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
context.Message.IsPd ? EmailBusinessScenario.PDVerification_UnderDRForPMOrAPM : EmailBusinessScenario.EligibilityVerification_UnderDRForPMOrAPM,
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3}
dictionValue[0], // 核查状态 {4}
_systemEmailConfig.SiteUrl // 链接 {5}
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
}
@@ -432,7 +459,7 @@ public class PMRepliedCheckChallengeEventConsumer(
IRepository<CheckChallengeDialog> _checkChallengeDialogRepository,
IRepository<QCChallengeDialog> _qCChallengeDialogRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<PMRepliedCheckChallengeEvent>
{
@@ -441,80 +468,89 @@ public class PMRepliedCheckChallengeEventConsumer(
{
Console.WriteLine("发送(016017) 【 PM 一致性核查 通知CRC】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var checkChallengeDialog = await _checkChallengeDialogRepository.Where(x => x.Id == context.Message.CheckChallengeDialogId).FirstNotNullAsync();
var subjectVisitId = context.Message.SubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.NoneDicomStudyList).Include(x => x.StudyList).Include(x => x.Subject).FirstNotNullAsync();
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var trialId = subjectVisit.TrialId;
var userinfoList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).ToList();
var craInfo = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).FirstOrDefault();
var scenario = context.Message.IsPd ? EmailBusinessScenario.PDVerification_UnderDR : EmailBusinessScenario.EligibilityVerification_UnderDR;
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
List<string> modalities = new List<string>();
modalities =subjectVisit.NoneDicomStudyList.Select(t => t.Modality)
.Union(subjectVisit.StudyList.Select(k => k.ModalityForEdit)).ToList();
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
if (trialEmailConfig != null)
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
var checkChallengeDialog = await _checkChallengeDialogRepository.Where(x => x.Id == context.Message.CheckChallengeDialogId).FirstNotNullAsync();
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).ToList();
var craInfo = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).FirstOrDefault();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
List<string> modalities = new List<string>();
modalities = subjectVisit.NoneDicomStudyList.Select(t => t.Modality)
.Union(subjectVisit.StudyList.Select(k => k.ModalityForEdit)).ToList();
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= "CheckState",EnumValue=subjectVisit.CheckState.GetEnumInt(), }, //核查状态
}
});
});
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
if (craInfo != null)
foreach (var userinfo in userinfoList)
{
messageToSend.Cc.Add(new MailboxAddress(String.Empty, craInfo.EMail));
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
if (craInfo != null)
{
messageToSend.Cc.Add(new MailboxAddress(String.Empty, craInfo.EMail));
}
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3}
string.Join(',', modalities), // 检查类型 {4}
dictionValue[0], // 核查状态 {5}
checkChallengeDialog.TalkContent,// 质疑内容{6}
_systemEmailConfig.SiteUrl // 链接 {7}
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3}
string.Join(',', modalities), // 检查类型 {4}
dictionValue[0], // 核查状态 {5}
checkChallengeDialog.TalkContent,// 质疑内容{6}
_systemEmailConfig.SiteUrl // 链接 {7}
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
context.Message.IsPd ? EmailBusinessScenario.PDVerification_UnderDR : EmailBusinessScenario.EligibilityVerification_UnderDR,
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
@@ -531,7 +567,7 @@ public class CheckStateChangedToAuditEventConsumer(
IRepository<QCChallenge> _qCChallengeRepository,
IRepository<QCChallengeDialog> _qCChallengeDialogRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<CheckStateChangedToAuditEvent>
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
@@ -540,70 +576,80 @@ public class CheckStateChangedToAuditEventConsumer(
Console.WriteLine("发送(018,030) 【通知PM 进行一致性核查】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var subjectVisitId = context.Message.SubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).FirstNotNullAsync();
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var trialId = subjectVisit.TrialId;
var userinfoList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var scenario = context.Message.IsPd ? EmailBusinessScenario.PDVerification_DR : EmailBusinessScenario.EligibilityVerification_DR;
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
if (trialEmailConfig != null)
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= "CheckState",EnumValue=subjectVisit.CheckState.GetEnumInt(), }, //审核状态
}
});
});
foreach (var userinfo in userinfoList)
{
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
foreach (var userinfo in userinfoList)
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 姓名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3}
dictionValue[0], // 核查状态 {4}
_systemEmailConfig.SiteUrl // 链接 {5}
);
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
context.Message.IsPd ? EmailBusinessScenario.PDVerification_DR : EmailBusinessScenario.EligibilityVerification_DR,
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 姓名 {0}
trialInfo.ExperimentName, // 项目 {1}
subjectCode, // 受试者 {2}
subjectVisit.VisitName, // 访视 {3}
dictionValue[0], // 核查状态 {4}
_systemEmailConfig.SiteUrl // 链接 {5}
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
}
@@ -619,7 +665,7 @@ public class QCClaimTaskEventConsumer(
IRepository<QCChallenge> _qCChallengeRepository,
IRepository<QCChallengeDialog> _qCChallengeDialogRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<QCClaimTaskEvent>
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
@@ -628,87 +674,90 @@ public class QCClaimTaskEventConsumer(
Console.WriteLine("发送(Code007008) 【QC 领取了质控任务】邮件!!!");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var subjectVisitId = context.Message.SubjectVisitId;
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).Include(x => x.CurrentActionUser).FirstNotNullAsync();
var trialId = subjectVisit.TrialId;
var subjectVisitList = await _subjectVisitRepository.Where(x => x.CurrentActionUserId == context.Message.CurrentActionUserId && x.TrialId == subjectVisit.TrialId).Include(x => x.Subject).ToListAsync();
var scenario = context.Message.IsPd ? EmailBusinessScenario.PDVerification_PendingImageQC : EmailBusinessScenario.EligibilityVerification_PendingImageQC;
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var pmandAPm = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var userinfo = subjectVisit.CurrentActionUser;
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
foreach (var pm in pmandAPm)
if (trialEmailConfig != null)
{
messageToSend.Cc.Add(new MailboxAddress(String.Empty, pm.EMail));
}
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var auditStateCode = "AuditStatePE";
if (trialInfo.QCProcessEnum == TrialQCProcess.DoubleAudit)
{
auditStateCode = "AuditStateRC";
}
var subjectVisitList = await _subjectVisitRepository.Where(x => x.CurrentActionUserId == context.Message.CurrentActionUserId && x.TrialId == subjectVisit.TrialId).Include(x => x.Subject).ToListAsync();
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
var pmandAPm = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
var userinfo = subjectVisit.CurrentActionUser;
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
foreach (var pm in pmandAPm)
{
messageToSend.Cc.Add(new MailboxAddress(String.Empty, pm.EMail));
}
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
var auditStateCode = "AuditStatePE";
if (trialInfo.QCProcessEnum == TrialQCProcess.DoubleAudit)
{
auditStateCode = "AuditStateRC";
}
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= auditStateCode,EnumValue=subjectVisit.AuditState.GetEnumInt(), }, //审核状态
}
});
});
var subjectcodes = subjectVisitList.Select(x => x.Subject.Code).Distinct().ToList();
var visitnames = subjectVisitList.Select(x => x.VisitName).Distinct().ToList();
var subjectcodes = subjectVisitList.Select(x => x.Subject.Code).Distinct().ToList();
var visitnames = subjectVisitList.Select(x => x.VisitName).Distinct().ToList();
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
string.Join(',', subjectcodes), // 受试者 {2}
string.Join(',', visitnames), // 访视 {3}
dictionValue[0], // 审核状态 {4}
_systemEmailConfig.SiteUrl // 链接 {5}
);
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var subjectCode = subjectVisit.Subject.Code;
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.FullName, // 用户名 {0}
trialInfo.ExperimentName, // 项目 {1}
string.Join(',', subjectcodes), // 受试者 {2}
string.Join(',', visitnames), // 访视 {3}
dictionValue[0], // 审核状态 {4}
return (topicStr, htmlBodyStr);
};
_systemEmailConfig.SiteUrl // 链接 {5}
);
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
return (topicStr, htmlBodyStr);
};
context.Message.IsPd ? EmailBusinessScenario.PDVerification_PendingImageQC : EmailBusinessScenario.EligibilityVerification_PendingImageQC,
messageToSend, emailConfigFunc);
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
}
@@ -1,4 +1,5 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
@@ -27,7 +28,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
IRepository<VisitTask> _visitTaskRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<TrialUserRole> _trialUserRoleRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<UrgentIRUnReadTaskRecurringEvent>
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
@@ -35,144 +36,151 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
public async Task Consume(ConsumeContext<UrgentIRUnReadTaskRecurringEvent> context)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var trialId = context.Message.TrialId;
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
var scenario = EmailBusinessScenario.ExpeditedReading;
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (trialEmailConfig != null)
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
{
DictionaryRepository = _dictionaryRepository,
IsEn_US = isEn_US,
DictionaryList = new List<DictionaryDto>()
{
new DictionaryDto (){DictionaryCode= "YesOrNo",EnumValue="true" }
}
});
});
//找到该项目所有的IR 并且有加急 和Pd 未读的任务
//找到该项目所有的IR 并且有加急 和Pd 未读的任务
Expression<Func<VisitTask, bool>> comonTaskFilter = t => t.TrialId == trialId && t.TaskState == TaskState.Effect && t.ReadingTaskState != ReadingTaskState.HaveSigned && t.TaskAllocationState == TaskAllocationState.Allocated;
Expression<Func<VisitTask, bool>> comonTaskFilter = t => t.TrialId == trialId && t.TaskState == TaskState.Effect && t.ReadingTaskState != ReadingTaskState.HaveSigned && t.TaskAllocationState == TaskAllocationState.Allocated;
var trialUserList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.JoinTime != null).Select(t => new
{
t.UserId,
t.UserRole.FullName,
t.UserRole.IdentityUser.EMail,
t.UserRole.IdentityUser.UserName,
t.Trial.TrialCode,
t.Trial.ResearchProgramNo
//TrialReadingCriterionList = t.Trial.TrialReadingCriterionList.Select(t => new { t.CriterionName, TrialReadingCriterionId = t.Id }).ToList()
});
foreach (var trialUser in trialUserList)
{
var userId = trialUser.UserId;
var doctorCriterionList = await _trialReadingCriterionRepository.Where(t => t.IsSigned && t.IsConfirm && t.TrialId == trialId && t.Trial.TrialUserRoleList.Any(t => t.UserId == userId))
.Select(c => new
{
TrialReadingCriterionId = c.Id,
CriterionName = c.CriterionName,
UnReadList = c.VisitTaskList.Where(t => t.ExpetidEmailNoticeTime == null) //没有被通知
.Where(t => t.DoctorUserId == userId && t.ReadingTaskState != ReadingTaskState.HaveSigned && t.TaskState == TaskState.Effect)
// 前序 不存在 未一致性核查未通过的
.Where(t => !t.Subject.SubjectVisitList.Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum > sv.VisitNum))
//前序 不存在 未生成任务的访视
.Where(t => c.IsAutoCreate == false ? !t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(d => d.TrialReadingCriterionId == t.TrialReadingCriterionId).Any(f => f.IsGeneratedTask == false && t.VisitTaskNum > f.SubjectVisit.VisitNum) : true)
.Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
.Where(t => t.SourceSubjectVisit.PDState == PDStateEnum.PDProgress || t.SourceSubjectVisit.IsEnrollmentConfirm ||
t.ReadModule.SubjectVisit.PDState == PDStateEnum.PDProgress || t.ReadModule.SubjectVisit.IsEnrollmentConfirm)
.Select(c => new
{
SubejctCode = c.IsAnalysisCreate ? c.BlindSubjectCode : c.Subject.Code,
c.TaskBlindName,
c.TaskName,
VisitTaskId = c.Id
}).ToList()
}).ToListAsync();
var toTalUnreadCount = doctorCriterionList.SelectMany(t => t.UnReadList).Count();
if (toTalUnreadCount > 0)
var trialUserList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.JoinTime != null).Select(t => new
{
var messageToSend = new MimeMessage();
t.UserId,
t.UserRole.FullName,
t.UserRole.IdentityUser.EMail,
t.UserRole.IdentityUser.UserName,
t.Trial.TrialCode,
t.Trial.ResearchProgramNo
//TrialReadingCriterionList = t.Trial.TrialReadingCriterionList.Select(t => new { t.CriterionName, TrialReadingCriterionId = t.Id }).ToList()
});
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(trialUser.FullName, trialUser.EMail));
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
foreach (var trialUser in trialUserList)
{
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
var userId = trialUser.UserId;
var doctorCriterionList = await _trialReadingCriterionRepository.Where(t => t.IsSigned && t.IsConfirm && t.TrialId == trialId && t.Trial.TrialUserRoleList.Any(t => t.UserId == userId))
.Select(c => new
{
TrialReadingCriterionId = c.Id,
CriterionName = c.CriterionName,
UnReadList = c.VisitTaskList.Where(t => t.ExpetidEmailNoticeTime == null) //没有被通知
.Where(t => t.DoctorUserId == userId && t.ReadingTaskState != ReadingTaskState.HaveSigned && t.TaskState == TaskState.Effect)
// 前序 不存在 未一致性核查未通过的
.Where(t => !t.Subject.SubjectVisitList.Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum > sv.VisitNum))
//前序 不存在 未生成任务的访视
.Where(t => c.IsAutoCreate == false ? !t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(d => d.TrialReadingCriterionId == t.TrialReadingCriterionId).Any(f => f.IsGeneratedTask == false && t.VisitTaskNum > f.SubjectVisit.VisitNum) : true)
.Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
.Where(t => t.SourceSubjectVisit.PDState == PDStateEnum.PDProgress || t.SourceSubjectVisit.IsEnrollmentConfirm ||
t.ReadModule.SubjectVisit.PDState == PDStateEnum.PDProgress || t.ReadModule.SubjectVisit.IsEnrollmentConfirm)
.Select(c => new
{
SubejctCode = c.IsAnalysisCreate ? c.BlindSubjectCode : c.Subject.Code,
c.TaskBlindName,
c.TaskName,
VisitTaskId = c.Id
}).ToList()
}).ToListAsync();
var toTalUnreadCount = doctorCriterionList.SelectMany(t => t.UnReadList).Count();
if (toTalUnreadCount > 0)
{
var topicStr = string.Format(input.topicStr, trialUser.ResearchProgramNo);
var messageToSend = new MimeMessage();
var template = input.htmlBodyStr;
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(trialUser.FullName, trialUser.EMail));
//正则提取循环的部分 {%for%}(.*?){%end for%}
string pattern = @"{%for%}(.*?){%end for%}";
var match = Regex.Match(template, pattern, RegexOptions.Singleline);
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
string criteriaTemplate = match.Groups[1].Value; // 提取循环模板
// 构建循环内容
string criteriaDetails = "";
foreach (var criteria in doctorCriterionList)
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
if (criteria.UnReadList.Count() > 0)
var topicStr = string.Format(input.topicStr, trialUser.ResearchProgramNo);
var template = input.htmlBodyStr;
//正则提取循环的部分 {%for%}(.*?){%end for%}
string pattern = @"{%for%}(.*?){%end for%}";
var match = Regex.Match(template, pattern, RegexOptions.Singleline);
string criteriaTemplate = match.Groups[1].Value; // 提取循环模板
// 构建循环内容
string criteriaDetails = "";
foreach (var criteria in doctorCriterionList)
{
criteriaDetails += string.Format(criteriaTemplate, criteria.CriterionName, criteria.UnReadList.Select(t => t.SubejctCode).Distinct().Count(), criteria.UnReadList.Count());
if (criteria.UnReadList.Count() > 0)
{
criteriaDetails += string.Format(criteriaTemplate, criteria.CriterionName, criteria.UnReadList.Select(t => t.SubejctCode).Distinct().Count(), criteria.UnReadList.Count());
}
}
}
// 用循环内容替换原始模板中的循环部分
string emailContent = template.Replace(criteriaTemplate, criteriaDetails).Replace("{%for%}", "").Replace("{%end for%}", "");
// 用循环内容替换原始模板中的循环部分
string emailContent = template.Replace(criteriaTemplate, criteriaDetails).Replace("{%for%}", "").Replace("{%end for%}", "");
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, emailContent),
trialUser.FullName,
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, emailContent),
trialUser.FullName,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
toTalUnreadCount,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
toTalUnreadCount,
trialUser.ResearchProgramNo,
dictionValue[0],
_systemEmailConfig.SiteUrl
);
trialUser.ResearchProgramNo,
dictionValue[0],
_systemEmailConfig.SiteUrl
);
return (topicStr, htmlBodyStr);
};
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository, EmailBusinessScenario.ExpeditedReading, messageToSend, emailConfigFunc);
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
//处理标记已通知的任务
//处理标记已通知的任务
var visitTaskIdList = doctorCriterionList.Where(t => t.UnReadList.Count() > 0).SelectMany(t => t.UnReadList.Select(u => u.VisitTaskId)).ToList();
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => visitTaskIdList.Contains(t.Id), u => new VisitTask() { ExpetidEmailNoticeTime = DateTime.Now });
}
var visitTaskIdList = doctorCriterionList.Where(t => t.UnReadList.Count() > 0).SelectMany(t => t.UnReadList.Select(u => u.VisitTaskId)).ToList();
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => visitTaskIdList.Contains(t.Id), u => new VisitTask() { ExpetidEmailNoticeTime = DateTime.Now });
}
}
}
}
}
@@ -37,4 +37,24 @@ public class UrgentIRUnReadTaskRecurringEvent : DomainEvent
public Guid TrialId { get; set; }
}
/// <summary>
/// 定时提醒
/// </summary>
public class SystemDocumentErverDayEvent : DomainEvent
{
}
public class SystemDocumentPublishEvent : DomainEvent
{
public List<Guid> Ids { get; set; }
/// <summary>
/// 新增的需要发送邮件的用户角色ID列表
/// 如果为null或空,则发送给所有相关角色
/// </summary>
public List<Guid> NewUserTypeIds { get; set; }
}
@@ -0,0 +1,277 @@
using DocumentFormat.OpenXml;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MassTransit.Consumer;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain.Models;
using MassTransit;
using Microsoft.Extensions.Options;
using MimeKit;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reactive.Joins;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.MassTransit.Recurring
{
/// <summary>
/// 定时过期提醒
/// </summary>
public class SystemDocumentErverDayEventConsumer(
IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<SystemDocument> _systemDocumentRepository,
IRepository<IdentityUser> _identityUserRepository,
IRepository<SystemDocConfirmedIdentityUser> _systemDocConfirmedUserRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<TrialUserRole> _trialUserRoleRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<SystemDocumentErverDayEvent>
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
public async Task Consume(ConsumeContext<SystemDocumentErverDayEvent> context)
{
DateTime now = DateTime.Now;
Console.WriteLine("发送定时过期提醒");
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
var systemDocQuery =
from sysDoc in _systemDocumentRepository.AsQueryable(false)
from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
join confirmc in _systemDocConfirmedUserRepository.Where() on new { ConfirmUserId = identityUser.Id, SystemDocumentId = sysDoc.Id } equals new { confirmc.ConfirmUserId, confirmc.SystemDocumentId } into cc
from confirm in cc.DefaultIfEmpty()
select new UnionDocumentWithConfirmInfoView()
{
IsSystemDoc = true,
Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted,
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
Name = sysDoc.Name,
Path = sysDoc.Path,
FileTypeId = sysDoc.FileTypeId,
UpdateTime = sysDoc.UpdateTime,
ConfirmUserId = identityUser.Id,
ConfirmTime = confirm.ConfirmTime,
UserCreateTime = identityUser.CreateTime,
CurrentStaffTrainDays = sysDoc.CurrentStaffTrainDays,
NewStaffTrainDays = sysDoc.NewStaffTrainDays,
RealName = identityUser.FullName,
UserName = identityUser.UserName,
IsNeedSendEmial = identityUser.IsZhiZhun || (!identityUser.IsZhiZhun && sysDoc.DocUserSignType == DocUserSignType.InnerAndOuter),
FullFilePath = sysDoc.Path
};
var datalist = await systemDocQuery.IgnoreQueryFilters().Where(t => t.IsDeleted == false && t.ConfirmTime == null)
.ToListAsync();
datalist = datalist.Where(x => x.SuggestFinishTime != null && x.SuggestFinishTime.Value.Date == DateTime.Now.Date)
.Where(x => x.IsNeedSendEmial).ToList();
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
Console.WriteLine("发送定时过期提醒:人员数量" + userinfoList.Count);
int index = 1;
foreach (var userinfo in userinfoList)
{
try
{
Console.WriteLine($"{index}发送定时过期提醒,邮箱:{userinfo.EMail},姓名{userinfo.UserName}");
index++;
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.UserName, // 用户名 {0}
_systemEmailConfig.SiteUrl
);
return (topicStr, htmlBodyStr);
};
var scenario = EmailBusinessScenario.GeneralTraining_ExpirationNotification;
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig != null)
{
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
}
catch (Exception)
{
}
}
}
}
/// <summary>
/// 生效通知
/// </summary>
public class SystemDocumentPublishEventConsumer(
IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<SystemDocument> _systemDocumentRepository,
IRepository<IdentityUser> _identityUserRepository,
IRepository<SystemDocConfirmedIdentityUser> _systemDocConfirmedUserRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<TrialUserRole> _trialUserRoleRepository,
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<SystemDocumentPublishEvent>
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
public async Task Consume(ConsumeContext<SystemDocumentPublishEvent> context)
{
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
// 记录是否只发送给新增角色的日志
if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
{
Console.WriteLine($"只发送给新增的角色,角色数量: {context.Message.NewUserTypeIds.Count}");
}
// 构建查询
IQueryable<UnionDocumentWithConfirmInfoView> systemDocQuery;
if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
{
// 只查询新增角色的用户
systemDocQuery =
from sysDoc in _systemDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
from identityUser in _identityUserRepository.AsQueryable(false)
.Where(t => t.Status == UserStateEnum.Enable &&
t.UserRoleList.Where(t => t.IsUserRoleDisabled == false)
.Any(t => context.Message.NewUserTypeIds.Contains(t.UserTypeId) &&
sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
select new UnionDocumentWithConfirmInfoView()
{
IsSystemDoc = true,
Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted,
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
Name = sysDoc.Name,
Path = sysDoc.Path,
FileTypeId = sysDoc.FileTypeId,
UpdateTime = sysDoc.UpdateTime,
ConfirmUserId = identityUser.Id,
RealName = identityUser.FullName,
UserName = identityUser.UserName,
IsNeedSendEmial = identityUser.IsZhiZhun || (!identityUser.IsZhiZhun && sysDoc.DocUserSignType == DocUserSignType.InnerAndOuter),
FullFilePath = sysDoc.Path
};
}
else
{
// 查询所有相关角色的用户
systemDocQuery =
from sysDoc in _systemDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
from identityUser in _identityUserRepository.AsQueryable(false)
.Where(t => t.Status == UserStateEnum.Enable &&
t.UserRoleList.Where(t => t.IsUserRoleDisabled == false)
.Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
select new UnionDocumentWithConfirmInfoView()
{
IsSystemDoc = true,
Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted,
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
Name = sysDoc.Name,
Path = sysDoc.Path,
FileTypeId = sysDoc.FileTypeId,
UpdateTime = sysDoc.UpdateTime,
ConfirmUserId = identityUser.Id,
RealName = identityUser.FullName,
UserName = identityUser.UserName,
IsNeedSendEmial = identityUser.IsZhiZhun || (!identityUser.IsZhiZhun && sysDoc.DocUserSignType == DocUserSignType.InnerAndOuter),
FullFilePath = sysDoc.Path
};
}
var datalist = await systemDocQuery.IgnoreQueryFilters().Where(x => x.IsNeedSendEmial).ToListAsync();
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
int index = 1;
foreach (var userinfo in userinfoList)
{
string msg = $"{index}生效通知,邮箱:{userinfo.EMail},姓名{userinfo.UserName},";
index++;
try
{
var messageToSend = new MimeMessage();
//发件地址
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
var topicStr = string.Format(input.topicStr, companyName);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
userinfo.UserName, // 用户名 {0}
_systemEmailConfig.SiteUrl
);
return (topicStr, htmlBodyStr);
};
var scenario = EmailBusinessScenario.GeneralTraining_EffectiveNotification;
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig != null)
{
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
msg += "发送成功";
}
}
catch (Exception)
{
msg += "发送失败";
}
Console.WriteLine(msg);
}
}
}
}
@@ -214,6 +214,10 @@ namespace IRaCIS.Core.Application.ViewModel
/// </summary>
public bool IsManualGeneration { get; set; }
//public bool IsAfterConvertedTask { get; set; }
public string PMBackReason { get; set; }
public int? RandomOrder { get; set; }
}
@@ -480,6 +484,9 @@ namespace IRaCIS.Core.Application.ViewModel
public string? RequestReReadingReason { get; set; }
public ExportResult? ReadingExportType { get; set; }
public int? RandomOrder { get; set; }
public bool? IsRandomOrderList { get; set; }
}
@@ -906,6 +913,30 @@ namespace IRaCIS.Core.Application.ViewModel
CancelAssign = 4,
}
public class SetRandomTaskOrderCommand
{
[NotDefault]
public Guid TrialId { get; set; }
[NotDefault]
public Guid TrialReadingCriterionId { get; set; }
[NotDefault]
public Guid DoctorUserId { get; set; }
public bool IsAutoSet { get; set; }
public List<VisitTaskOrderCommand> SetList { get; set; }
}
public class VisitTaskOrderCommand
{
public Guid Id { get; set; }
public int? RandomOrder { get; set; }
}
}
@@ -35,7 +35,7 @@ namespace IRaCIS.Core.Application.Service
IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
IRepository<ClinicalDataTrialSet> _trialClinicalDataSetRepository,
IRepository<ReadingClinicalData> _readingClinicalDataRepository,
IRepository<ReadingConsistentClinicalData> _readingConsistentClinicalDataRepository,
IRepository<ReadingConsistentClinicalData> _readingConsistentClinicalDataRepository,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IWebHostEnvironment _hostEnvironment, IFusionCache _fusionCache) : BaseService, IVisitTaskHelpeService
{
@@ -47,16 +47,16 @@ namespace IRaCIS.Core.Application.Service
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<FileResult> ExportTemplateAsync(ExportTemplateAsyncDto inDto)
public async Task<FileResult> ExportTemplateAsync(ExportTemplateAsyncDto inDto)
{
return await ExcelExportHelper.ExportTemplateAsync(new ExportTemplateServiceDto()
{
Data=inDto.Data,
commonDocumentRepository= _commonDocumentRepository,
TemplateCode=inDto.TemplateCode,
ExportFileName=inDto.ExportFileName,
hostEnvironment=_hostEnvironment,
IsEnglish=_userInfo.IsEn_Us,
Data = inDto.Data,
commonDocumentRepository = _commonDocumentRepository,
TemplateCode = inDto.TemplateCode,
ExportFileName = inDto.ExportFileName,
hostEnvironment = _hostEnvironment,
IsEnglish = _userInfo.IsEn_Us,
});
}
@@ -757,248 +757,30 @@ namespace IRaCIS.Core.Application.Service
if (trialReadingCriterionConfig.TaskAllocateObjEnum == TaskAllocateObj.Subject)
{
var allocateSubjectArmList = _visitTaskRepository.Where(t => t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.TrialId == trialId && t.DoctorUserId != null && t.ArmEnum != Arm.JudgeArm)
.Select(t => new { t.DoctorUserId, t.ArmEnum }).Distinct().ToList();
//当前任务没有分配医生,初次分配 不处理 只生成任务,后续根据生成的任务 再进行分配
if (allocateSubjectArmList.Count == 0)
{
}
else
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
{
//并且配置了医生
if (assignConfigList.Count > 0 && trialReadingCriterionConfig.IsFollowVisitAutoAssign)
#region 访
//配置了医生
if (assignConfigList.Count > 0)
{
//之前有回退到影像上传的访视 那么当前访视一致性核查通过的时候,当前访视生成但是不分配出去(排除失访的)
#region 访 (PM 退 PM )
var beforeBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.VisitTaskNum < subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.SourceSubjectVisit.CheckState != CheckStateEnum.CVPassed && t.SourceSubjectVisit.IsLostVisit == false).OrderBy(t => t.VisitTaskNum).FirstOrDefaultAsync();
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
//之前有回退的,那么当前访视任务生成但是不分配
if (beforeBackVisitTask != null)
{
//之前有回退到影像上传的访视 那么当前访视一致性核查通过的时候,当前访视生成但是不分配出去(排除失访的)
var beforeBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.VisitTaskNum < subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.SourceSubjectVisit.CheckState != CheckStateEnum.CVPassed && t.SourceSubjectVisit.IsLostVisit == false).OrderBy(t => t.VisitTaskNum).FirstOrDefaultAsync();
//之前有回退的,那么当前访视任务生成但是不分配
if (beforeBackVisitTask != null)
{
//不用进行额外处理
//访视2 PM 回退 基线回退 访视2先一致性核查通过,生成访视2任务,但是不分配
}
else
{
#region 访
var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated;
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && task1 != null)
{
task1.TaskAllocationState = defaultState;
//分配给对应Arm的人
task1.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1)!.DoctorUserId;
task1.AllocateTime = DateTime.Now;
task1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2) && task2 != null)
{
task2.TaskAllocationState = defaultState;
task2.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2)!.DoctorUserId;
task2.AllocateTime = DateTime.Now;
task2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
#endregion
}
//后续最近的未一致性核查通过的访视任务
var followBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.VisitTaskNum > subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.SourceSubjectVisit.CheckState != CheckStateEnum.CVPassed && t.SourceSubjectVisit.IsLostVisit == false).OrderBy(t => t.VisitTaskNum).FirstOrDefaultAsync();
//大于当前访视 同时小于最近的未一致性核查通过的访视任务分配 或者生成
//存在退回访视1 又退回基线 这种情况 生成任务 考虑基线先一致性核查通过,但是访视1还未通过时 生成任务
var followVisitTaskList = await _visitTaskRepository
.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.VisitTaskNum > subjectVisit.VisitNum && t.SourceSubjectVisit.CheckState == CheckStateEnum.CVPassed && t.ReadingCategory == ReadingCategory.Visit && t.IsAnalysisCreate == false, true)
.WhereIf(followBackVisitTask != null, t => t.VisitTaskNum < followBackVisitTask!.VisitTaskNum)
.ToListAsync();
var followVisitGroup = followVisitTaskList.GroupBy(t => t.VisitTaskNum);
//每个访视去判断 是分配还是生成(因为影响哪里有些是取消分配,有些是重阅重置需要重新生成)
foreach (var visitGroup in followVisitGroup)
{
var visit = await _subjectVisitRepository.Where(x => x.Id == visitGroup.First().SourceSubjectVisitId).Select(x => new
{
x.PDState,
x.IsEnrollmentConfirm,
x.IsUrgent,
}).FirstNotNullAsync();
TaskUrgentType? urgentType = null;
if (subjectVisitInfo.PDState == PDStateEnum.PDProgress)
{
urgentType = TaskUrgentType.PDProgress;
}
else if (subjectVisitInfo.IsEnrollmentConfirm)
{
urgentType = TaskUrgentType.EnrollmentConfirm;
}
else if (subjectVisitInfo.IsUrgent)
{
urgentType = TaskUrgentType.VisitUrgent;
}
bool isCanEdit = urgentType == TaskUrgentType.EnrollmentConfirm || urgentType == TaskUrgentType.PDProgress ? false : true;
//如果后续访视已分配有效 就不用处理
if (visitGroup.Any(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.Allocated && t.ArmEnum == Arm.DoubleReadingArm1))
{
//不做处理
}
else
{
var arm1 = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null && t.ArmEnum == Arm.DoubleReadingArm1);
if (arm1 != null)
{
//有可能仅仅只分配了一个Subject 未分配 那么
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && task1 != null)
{
arm1.IsUrgent = visit.IsUrgent;
arm1.TaskUrgentType = urgentType;
arm1.IsCanEditUrgentState = isCanEdit;
arm1.TaskAllocationState = TaskAllocationState.Allocated;
arm1.AllocateTime = DateTime.Now;
arm1.DoctorUserId = task1.DoctorUserId;
arm1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
}
else
{
var latestTask = visitGroup.Where(t => t.ArmEnum == Arm.DoubleReadingArm1).OrderByDescending(t => t.CreateTime).First();
var taskOne = await _visitTaskRepository.AddAsync(new VisitTask()
{
TrialId = trialId,
SubjectId = subjectVisit.SubjectId,
IsUrgent = visit.IsUrgent,
TaskUrgentType = urgentType,
IsCanEditUrgentState = isCanEdit,
ArmEnum = Arm.DoubleReadingArm1,//特殊
Code = currentMaxCodeInt + 1,
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
ReadingCategory = ReadingCategory.Visit,
SourceSubjectVisitId = latestTask.SourceSubjectVisitId,
VisitTaskNum = latestTask.VisitTaskNum,
TaskBlindName = visitBlindConfig.BlindFollowUpPrefix + " " + visitNumList.IndexOf(latestTask.VisitTaskNum),
TaskName = latestTask.TaskName,
BlindSubjectCode = latestTask.BlindSubjectCode,
BlindTrialSiteCode = latestTask.BlindTrialSiteCode,
IsAnalysisCreate = latestTask.IsAnalysisCreate,
IsSelfAnalysis = latestTask.IsSelfAnalysis,
TaskAllocationState = TaskAllocationState.Allocated,
AllocateTime = DateTime.Now,
DoctorUserId = task1!.DoctorUserId,
SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget),
TrialReadingCriterionId = latestTask.TrialReadingCriterionId,
IsNeedClinicalDataSign = latestTask.IsNeedClinicalDataSign,
IsClinicalDataSign = latestTask.IsClinicalDataSign
});
currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
}
//如果后续访视已分配有效 就不用处理
if (visitGroup.Any(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.Allocated && t.ArmEnum == Arm.DoubleReadingArm2))
{
//不做处理
}
else
{
var arm2 = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null && t.ArmEnum == Arm.DoubleReadingArm2);
if (arm2 != null)
{
//有可能仅仅只分配了一个Subject
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2) && task2 != null)
{
arm2.IsUrgent = visit.IsUrgent;
arm2.TaskUrgentType = urgentType;
arm2.IsCanEditUrgentState = isCanEdit;
arm2.TaskAllocationState = TaskAllocationState.Allocated;
arm2.AllocateTime = DateTime.Now;
arm2.DoctorUserId = task2.DoctorUserId;
arm2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
}
else
{
var latestTask = visitGroup.Where(t => t.ArmEnum == Arm.DoubleReadingArm2).OrderByDescending(t => t.CreateTime).First();
var taskTwo = await _visitTaskRepository.AddAsync(new VisitTask()
{
TrialId = trialId,
SubjectId = subjectVisit.SubjectId,
IsUrgent = visit.IsUrgent,
TaskUrgentType = urgentType,
IsCanEditUrgentState = isCanEdit,
//CheckPassedTime = subjectVisit.CheckPassedTime,
ArmEnum = Arm.DoubleReadingArm2,//特殊
Code = currentMaxCodeInt + 1,
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
ReadingCategory = ReadingCategory.Visit,
SourceSubjectVisitId = latestTask.SourceSubjectVisitId,
VisitTaskNum = latestTask.VisitTaskNum,
TaskBlindName = visitBlindConfig.BlindFollowUpPrefix + " " + visitNumList.IndexOf(latestTask.VisitTaskNum),
TaskName = latestTask.TaskName,
BlindSubjectCode = latestTask.BlindSubjectCode,
BlindTrialSiteCode = latestTask.BlindTrialSiteCode,
IsAnalysisCreate = latestTask.IsAnalysisCreate,
IsSelfAnalysis = latestTask.IsSelfAnalysis,
TaskAllocationState = TaskAllocationState.Allocated,
AllocateTime = DateTime.Now,
DoctorUserId = task2!.DoctorUserId,
SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget),
TrialReadingCriterionId = latestTask.TrialReadingCriterionId,
IsNeedClinicalDataSign = latestTask.IsNeedClinicalDataSign,
IsClinicalDataSign = latestTask.IsClinicalDataSign
});
currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
}
}
//不用进行额外处理
//访视2 PM 回退 基线回退 访视2先一致性核查通过,生成访视2任务,但是不分配
}
//无序的时候 生成任务并分配出去
else
{
#region 访
var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated;
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && task1 != null)
@@ -1019,21 +801,237 @@ namespace IRaCIS.Core.Application.Service
task2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
#endregion
}
#endregion
}
else
//后续访视不自动分配,或者配置的医生数量不足,就不进行分配
#endregion
#region 访
//后续最近的未一致性核查通过的访视任务
var followBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.VisitTaskNum > subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.SourceSubjectVisit.CheckState != CheckStateEnum.CVPassed && t.SourceSubjectVisit.IsLostVisit == false).OrderBy(t => t.VisitTaskNum).FirstOrDefaultAsync();
//大于当前访视 同时小于最近的未一致性核查通过的访视任务分配 或者生成
//存在退回访视1 又退回基线 这种情况 生成任务 考虑基线先一致性核查通过,但是访视1还未通过时 生成任务
var followVisitTaskList = await _visitTaskRepository
.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.VisitTaskNum > subjectVisit.VisitNum && t.SourceSubjectVisit.CheckState == CheckStateEnum.CVPassed && t.ReadingCategory == ReadingCategory.Visit && t.IsAnalysisCreate == false, true)
.WhereIf(followBackVisitTask != null, t => t.VisitTaskNum < followBackVisitTask!.VisitTaskNum)
.ToListAsync();
var followVisitGroup = followVisitTaskList.GroupBy(t => t.VisitTaskNum);
//每个访视去判断 是分配还是生成(因为影响哪里有些是取消分配,有些是重阅重置需要重新生成)
foreach (var visitGroup in followVisitGroup)
{
var visit = await _subjectVisitRepository.Where(x => x.Id == visitGroup.First().SourceSubjectVisitId).Select(x => new
{
x.PDState,
x.IsEnrollmentConfirm,
x.IsUrgent,
}).FirstNotNullAsync();
TaskUrgentType? urgentType = null;
if (subjectVisitInfo.PDState == PDStateEnum.PDProgress)
{
urgentType = TaskUrgentType.PDProgress;
}
else if (subjectVisitInfo.IsEnrollmentConfirm)
{
urgentType = TaskUrgentType.EnrollmentConfirm;
}
else if (subjectVisitInfo.IsUrgent)
{
urgentType = TaskUrgentType.VisitUrgent;
}
bool isCanEdit = urgentType == TaskUrgentType.EnrollmentConfirm || urgentType == TaskUrgentType.PDProgress ? false : true;
//如果后续访视已分配有效 就不用处理
if (visitGroup.Any(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.Allocated && t.ArmEnum == Arm.DoubleReadingArm1))
{
//不做处理
}
else
{
var arm1 = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null && t.ArmEnum == Arm.DoubleReadingArm1);
if (arm1 != null)
{
arm1.IsUrgent = visit.IsUrgent;
arm1.TaskUrgentType = urgentType;
arm1.IsCanEditUrgentState = isCanEdit;
//有可能仅仅只分配了一个Subject 未分配 那么
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && task1 != null)
{
arm1.TaskAllocationState = TaskAllocationState.Allocated;
arm1.AllocateTime = DateTime.Now;
arm1.DoctorUserId = task1.DoctorUserId;
arm1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
}
else
{
var latestTask = visitGroup.Where(t => t.ArmEnum == Arm.DoubleReadingArm1).OrderByDescending(t => t.CreateTime).First();
var taskOne = await _visitTaskRepository.AddAsync(new VisitTask()
{
TrialId = trialId,
SubjectId = subjectVisit.SubjectId,
IsUrgent = visit.IsUrgent,
TaskUrgentType = urgentType,
IsCanEditUrgentState = isCanEdit,
ArmEnum = Arm.DoubleReadingArm1,//特殊
Code = currentMaxCodeInt + 1,
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
ReadingCategory = ReadingCategory.Visit,
SourceSubjectVisitId = latestTask.SourceSubjectVisitId,
VisitTaskNum = latestTask.VisitTaskNum,
TaskBlindName = visitBlindConfig.BlindFollowUpPrefix + " " + visitNumList.IndexOf(latestTask.VisitTaskNum),
TaskName = latestTask.TaskName,
BlindSubjectCode = latestTask.BlindSubjectCode,
BlindTrialSiteCode = latestTask.BlindTrialSiteCode,
IsAnalysisCreate = latestTask.IsAnalysisCreate,
IsSelfAnalysis = latestTask.IsSelfAnalysis,
TrialReadingCriterionId = latestTask.TrialReadingCriterionId,
IsNeedClinicalDataSign = latestTask.IsNeedClinicalDataSign,
IsClinicalDataSign = latestTask.IsClinicalDataSign
});
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && task1 != null)
{
taskOne.TaskAllocationState = TaskAllocationState.Allocated;
taskOne.AllocateTime = DateTime.Now;
taskOne. DoctorUserId = task1!.DoctorUserId;
taskOne. SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
}
//如果后续访视已分配有效 就不用处理
if (visitGroup.Any(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.Allocated && t.ArmEnum == Arm.DoubleReadingArm2))
{
//不做处理
}
else
{
var arm2 = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null && t.ArmEnum == Arm.DoubleReadingArm2);
if (arm2 != null)
{
arm2.IsUrgent = visit.IsUrgent;
arm2.TaskUrgentType = urgentType;
arm2.IsCanEditUrgentState = isCanEdit;
//有可能仅仅只分配了一个Subject
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2) && task2 != null)
{
arm2.TaskAllocationState = TaskAllocationState.Allocated;
arm2.AllocateTime = DateTime.Now;
arm2.DoctorUserId = task2.DoctorUserId;
arm2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
}
else
{
var latestTask = visitGroup.Where(t => t.ArmEnum == Arm.DoubleReadingArm2).OrderByDescending(t => t.CreateTime).First();
var taskTwo = await _visitTaskRepository.AddAsync(new VisitTask()
{
TrialId = trialId,
SubjectId = subjectVisit.SubjectId,
IsUrgent = visit.IsUrgent,
TaskUrgentType = urgentType,
IsCanEditUrgentState = isCanEdit,
//CheckPassedTime = subjectVisit.CheckPassedTime,
ArmEnum = Arm.DoubleReadingArm2,//特殊
Code = currentMaxCodeInt + 1,
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
ReadingCategory = ReadingCategory.Visit,
SourceSubjectVisitId = latestTask.SourceSubjectVisitId,
VisitTaskNum = latestTask.VisitTaskNum,
TaskBlindName = visitBlindConfig.BlindFollowUpPrefix + " " + visitNumList.IndexOf(latestTask.VisitTaskNum),
TaskName = latestTask.TaskName,
BlindSubjectCode = latestTask.BlindSubjectCode,
BlindTrialSiteCode = latestTask.BlindTrialSiteCode,
IsAnalysisCreate = latestTask.IsAnalysisCreate,
IsSelfAnalysis = latestTask.IsSelfAnalysis,
TrialReadingCriterionId = latestTask.TrialReadingCriterionId,
IsNeedClinicalDataSign = latestTask.IsNeedClinicalDataSign,
IsClinicalDataSign = latestTask.IsClinicalDataSign
});
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2) && task2 != null)
{
taskTwo.TaskAllocationState = TaskAllocationState.Allocated;
taskTwo.AllocateTime = DateTime.Now;
taskTwo.DoctorUserId = task2!.DoctorUserId;
taskTwo.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
}
}
}
#endregion
}
else
{
//无序的时候 生成任务并分配出去
if (assignConfigList.Count > 0 && trialReadingCriterionConfig.IsFollowVisitAutoAssign)
{
var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated;
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && task1 != null)
{
task1.TaskAllocationState = defaultState;
//分配给对应Arm的人
task1.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1)!.DoctorUserId;
task1.AllocateTime = DateTime.Now;
task1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2) && task2 != null)
{
task2.TaskAllocationState = defaultState;
task2.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2)!.DoctorUserId;
task2.AllocateTime = DateTime.Now;
task2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
}
}
}
@@ -16,6 +16,7 @@ using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Linq.Dynamic.Core;
using Subject = IRaCIS.Core.Domain.Models.Subject;
@@ -74,7 +75,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
return await _visitTaskRepository.SaveChangesAsync();
}
public async Task<List<TrialReadingCriterionDto>> GetTrialCriterionList(Guid trialId, bool isHaveSigned = true, bool? isAutoCreate = null)
public async Task<List<TrialReadingCriterionDto>> GetTrialCriterionList(Guid trialId, bool isHaveSigned = true, bool? isAutoCreate = null, bool? isRandom = null)
{
var list = await _readingQuestionCriterionTrialRepository.Where(t => t.TrialId == trialId && t.IsConfirm)
@@ -107,7 +108,8 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
return list.AsQueryable().WhereIf(isHaveSigned == true, t => t.ReadingInfoSignTime != null)
.WhereIf(isAutoCreate == false, t => t.IsAutoCreate == isAutoCreate).ToList();
.WhereIf(isAutoCreate == false, t => t.IsAutoCreate == isAutoCreate)
.WhereIf(isRandom == true, t => t.IsReadingTaskViewInOrder == ReadingOrder.Random).ToList();
}
@@ -761,6 +763,8 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate)
.WhereIf(inQuery.BeginSignTime != null, t => t.SignTime > inQuery.BeginSignTime)
.WhereIf(inQuery.EndSignTime != null, t => t.SignTime < inQuery.EndSignTime)
.WhereIf(inQuery.RandomOrder != null, t => t.RandomOrder == inQuery.RandomOrder)
.WhereIf(inQuery.IsRandomOrderList == true, t => (t.ReadingTaskState == ReadingTaskState.WaitReading || t.ReadingTaskState==ReadingTaskState.Reading) && t.TaskAllocationState==TaskAllocationState.Allocated)
.ProjectTo<ReadingTaskView>(_mapper.ConfigurationProvider);
var defalutSortArray = new string[] { nameof(ReadingTaskView.IsUrgent) + " desc", nameof(ReadingTaskView.SubjectCode), nameof(ReadingTaskView.VisitTaskNum) };
@@ -1005,6 +1009,10 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
if (critrion.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
{
var extralObj = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.TrialExtraConfigJsonStr }).FirstOrDefault();
var extralConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(extralObj?.TrialExtraConfigJsonStr) ?? new TrialExtraConfig();
var visitQuery = _visitTaskRepository.Where(x => x.TrialId == inQuery.TrialId && x.DoctorUserId == _userInfo.UserRoleId && x.TaskState == TaskState.Effect)
.WhereIf(inQuery.SubjectId != null, x => x.SubjectId == inQuery.SubjectId)
@@ -1012,7 +1020,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
.WhereIf(critrion.IsAutoCreate == false, t => !t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(f => f.IsGeneratedTask == false && t.VisitTaskNum > f.SubjectVisit.VisitNum))
// 前序 不存在 未一致性核查未通过的
.Where(t => !t.Subject.SubjectVisitList.Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum >= sv.VisitNum))
.Where(t => !t.Subject.SubjectVisitList.Where(t => extralConfig.IsOpenLostVistRead ? t.IsLostVisit == false : true).Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum >= sv.VisitNum))
//.WhereIf(critrion.IsAutoCreate == false, t => t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(t => t.IsGeneratedTask == false) ?
//t.VisitTaskNum <= t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsGeneratedTask == false).Min(t => t.SubjectVisit.VisitNum) : true)
//.Where(t => t.Subject.SubjectVisitList.Any(t => t.CheckState != CheckStateEnum.CVPassed) ? t.VisitTaskNum <= t.Subject.SubjectVisitList.Where(t => t.CheckState != CheckStateEnum.CVPassed).Min(t => t.VisitNum) : true)
@@ -1035,14 +1043,15 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
UnReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).Count(),
//未读 里可读任务量
UnReadCanReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned && y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)
UnReadCanReadTaskCount = x.Where(t => extralConfig.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false).Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)
//不能对包含聚合或子查询的表达式执行聚合函数
//&& !x.Any(t => t.ReadingTaskState != ReadingTaskState.HaveSigned && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false && t.VisitTaskNum<y.VisitTaskNum )
).Count(),
UnReadCanReadTaskList = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned)
.Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
.Where(t => extralConfig.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false)
.Where(y => /*y.IsFrontTaskNeedSignButNotSign == false &&*/ (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
.OrderBy(x => x.VisitTaskNum)
.Select(u => new IRUnreadTaskView()
{
@@ -1055,7 +1064,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
ReadingCategory = u.ReadingCategory,
IsAnalysisCreate = u.IsAnalysisCreate,
ArmEnum = u.ArmEnum,
IsExistUnprocessedFeedback=u.UserFeedBackList.Any(t => t.State ==0),
IsExistUnprocessedFeedback = u.UserFeedBackList.Any(t => t.State == 0),
TrialReadingCriterionId = u.TrialReadingCriterionId,
IsNeedClinicalDataSign = u.IsNeedClinicalDataSign,
IsClinicalDataSign = u.IsClinicalDataSign,
@@ -2203,12 +2212,13 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
{
item.Id = Guid.Empty;
item.VisitTaskId = newTask.Id;
item.MeasureData = item.MeasureData.Replace(origenalTask.Id.ToString(), newTask.Id.ToString());
}
_ = _readingCustomTagRepository.AddRangeAsync(readingCustomTagList).Result;
var readingTaskQuestionAnswerList = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
@@ -2216,6 +2226,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
{
item.Id = Guid.Empty;
item.VisitTaskId = newTask.Id;
}
_ = _readingTaskQuestionAnswerRepository.AddRangeAsync(readingTaskQuestionAnswerList).Result;
@@ -2227,9 +2238,11 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
item.Id = Guid.Empty;
item.FristAddTaskId = item.VisitTaskId == item.FristAddTaskId ? newTask.Id : item.FristAddTaskId;
item.VisitTaskId = newTask.Id;
item.MeasureData = item.MeasureData.Replace(origenalTask.Id.ToString(), newTask.Id.ToString());
}
//ReadingTableAnswerRowInfo ReadingTableQuestionAnswer 一起加
var readingTableAnswerRowInfoList = _readingTableAnswerRowInfoRepository.Where(t => t.VisitTaskId == origenalTask.Id).Include(t => t.LesionAnswerList).ToList();
@@ -2240,7 +2253,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
var originalVisitTaskId = item.VisitTaskId;
var originalFristAddTaskId = item.FristAddTaskId;
var newRowId= NewId.NextSequentialGuid();
var newRowId = NewId.NextSequentialGuid();
foreach (var mark in readingTaskQuestionMarkList)
{
@@ -2253,6 +2266,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
//默认值是当前任务添加的
item.FristAddTaskId = originalVisitTaskId == originalFristAddTaskId ? newTask.Id : item.FristAddTaskId;
item.MeasureData = item.MeasureData.Replace(origenalTask.Id.ToString(), newTask.Id.ToString());
foreach (var item2 in item.LesionAnswerList)
{
@@ -2276,11 +2290,11 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
/// PM 设置任务 退回
/// </summary>
/// <returns></returns>
[HttpPut("{trialId:guid}/{taskId:guid}")]
[HttpPut("{trialId:guid}/{taskId:guid}/{pmBackReason}")]
[UnitOfWork]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> PMSetTaskBack(Guid trialId, Guid taskId)
public async Task<IResponseOutput> PMSetTaskBack(Guid trialId, Guid taskId, string pmBackReason)
{
//var trialConfig = (await _trialRepository.Where(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.IsReadingTaskViewInOrder, t.ReadingType }).FirstOrDefaultAsync()).IfNullThrowException();
@@ -2341,7 +2355,6 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
#region
//执行类似一致性核查回退流程 回退访视到影像上传流程
await VisitBackAsync(task.SourceSubjectVisitId);
@@ -2458,6 +2471,9 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
}
var trackTask = await _visitTaskRepository.FindAsync(task.Id);
trackTask.PMBackReason = pmBackReason;
}
else
{
@@ -2570,7 +2586,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
sv.CurrentActionUserId = null;
sv.PreliminaryAuditUserId = null;
sv.ReviewAuditUserId = null;
sv.SecondReviewState = SecondReviewState.None;
if (sv.IsBaseLine)
{
@@ -2609,7 +2625,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
private bool IsSpmOrCPM()
{
return _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM ;
return _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM;
}
/// <summary>
@@ -2674,6 +2690,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
{
//默认影响的都是该标准的任务
filterExpression = filterExpression.And(t => t.TrialReadingCriterionId == filterObj.TrialReadingCriterionId);
}
@@ -2934,6 +2951,88 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
}
#region
[HttpPost]
[UnitOfWork]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> SetRandomTaskOrder(SetRandomTaskOrderCommand inCommand)
{
if (inCommand.IsAutoSet)
{
//找到所有的已分配的,未阅片的,生效的 非一致性分析
var needRandomOrderList = _visitTaskRepository.Where(t => t.TrialId == inCommand.TrialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId && t.DoctorUserId == inCommand.DoctorUserId)
.Where(t => t.TaskAllocationState == TaskAllocationState.Allocated && t.ReadingTaskState == ReadingTaskState.WaitReading && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze))
.Select(t => t.Id).ToList();
//var haveSignOrderList = _visitTaskRepository.Where(t => t.TrialId == inCommand.TrialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId && t.DoctorUserId == inCommand.DoctorUserId)
// .Where(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.SignTime != null && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze))
// .Select(t => t.RandomOrder).ToList();
//已阅,阅片中任务的序号
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == inCommand.TrialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId
&& t.DoctorUserId == inCommand.DoctorUserId && t.ReadingTaskState != ReadingTaskState.WaitReading, u => new VisitTask() { RandomOrder = null });
//随机赋值编号 比如要处理5个任务,实例化一个包含1-5的数组,每次随机取出一个
List<int> availableNumbers = Enumerable.Range(1, needRandomOrderList.Count).ToList();
Random rng = new Random();
foreach (var id in needRandomOrderList)
{
int randomIndex = rng.Next(availableNumbers.Count);
var num = availableNumbers[randomIndex];
var order = 11 + 5 * (num - 1);
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, t => new VisitTask() { RandomOrder = order });
availableNumbers.RemoveAt(randomIndex);
}
}
else
{
foreach (var item in inCommand.SetList)
{
var task = await _visitTaskRepository.Where(t => t.Id == item.Id).Select(t => new { t.RandomOrder, t.ReadingTaskState, t.TaskAllocationState, t.DoctorUserId }).FirstNotNullAsync();
if (task.ReadingTaskState != ReadingTaskState.WaitReading || task.DoctorUserId != inCommand.DoctorUserId
|| task.TaskAllocationState != TaskAllocationState.Allocated)
{
//"任务不符合设置阅片序号条件"
return ResponseOutput.NotOk(_localizer["VisitTask_NotRandomOrderTask"]);
}
//设置交换序号的任务,可能不符合条件
//没有序号,直接设置
if (task.RandomOrder == null)
{
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, t => new VisitTask() { RandomOrder = item.RandomOrder });
}
else
{
if(!_visitTaskRepository.Any(t => t.TrialId == inCommand.TrialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId && t.DoctorUserId == inCommand.DoctorUserId
&& t.TaskAllocationState == TaskAllocationState.Allocated && t.ReadingTaskState == ReadingTaskState.WaitReading && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze)
&& t.RandomOrder == item.RandomOrder))
{
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, t => new VisitTask() { RandomOrder = item.RandomOrder });
}
else
{
//"序号已被占用!"
return ResponseOutput.NotOk(_localizer["VisitTask_RandomOrderUserd"]);
}
}
}
}
return ResponseOutput.Ok();
}
#endregion
#region
@@ -96,6 +96,8 @@ namespace IRaCIS.Core.Application.ViewModel
public int State { get; set; }
public Guid? PublishLogId { get; set; }
public List<BatchAddInternationalizationDto> AddList { get; set; }
}
@@ -4,8 +4,10 @@
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using System.Text.RegularExpressions;
namespace IRaCIS.Core.Application.Contracts
@@ -44,12 +46,20 @@ namespace IRaCIS.Core.Application.Contracts
{
var verifyExp1 = new EntityVerifyExp<EmailNoticeConfig>()
{
VerifyExp = t => t.BusinessScenarioEnum == addOrEditEmailNoticeConfig.BusinessScenarioEnum && t.CriterionTypeEnum== addOrEditEmailNoticeConfig.CriterionTypeEnum,
VerifyExp = t => t.BusinessScenarioEnum == addOrEditEmailNoticeConfig.BusinessScenarioEnum && t.CriterionTypeEnum == addOrEditEmailNoticeConfig.CriterionTypeEnum,
VerifyMsg = _localizer["EmailNoticeConfig_RepeatEmailScenario"]
};
var verifyExp2 = new EntityVerifyExp<EmailNoticeConfig>()
{
VerifyExp = t => t.Code == addOrEditEmailNoticeConfig.Code && t.IsDistinguishCriteria == addOrEditEmailNoticeConfig.IsDistinguishCriteria && t.SystemLevel == addOrEditEmailNoticeConfig.SystemLevel,
VerifyMsg = _localizer["EmailNoticeConfig_RepeatCode"]
};
// 匹配所有占位符的正则表达式,允许包含空格的占位符
var regex = new Regex(@"\{\s*\d+\s*\}");
@@ -61,10 +71,14 @@ namespace IRaCIS.Core.Application.Contracts
}
var entity = new EmailNoticeConfig() { };
if (addOrEditEmailNoticeConfig.Id == null)
{
var entity = _mapper.Map<EmailNoticeConfig>(addOrEditEmailNoticeConfig);
entity = _mapper.Map<EmailNoticeConfig>(addOrEditEmailNoticeConfig);
foreach (var item in addOrEditEmailNoticeConfig.ToUserTypeList)
@@ -80,9 +94,9 @@ namespace IRaCIS.Core.Application.Contracts
}
await _emailNoticeConfigrepository.AddAsync(entity, true, verifyExp1);
await _emailNoticeConfigrepository.AddAsync(entity, true, verifyExp1, verifyExp2);
return ResponseOutput.Ok(entity.Id.ToString());
}
else
{
@@ -103,14 +117,32 @@ namespace IRaCIS.Core.Application.Contracts
}
var entity = await _emailNoticeConfigrepository.UpdateFromDTOAsync(addOrEditEmailNoticeConfig, true, false, verifyExp1);
entity = await _emailNoticeConfigrepository.UpdateFromDTOAsync(addOrEditEmailNoticeConfig, true, false, verifyExp1, verifyExp2);
return ResponseOutput.Ok(entity.Id.ToString());
}
if (entity.EmailCron != string.Empty)
{
var jobId = $"{entity.Id}_({entity.BusinessScenarioEnum})";
//有的job 可能编辑控制直接不发,需要移除已存在的
HangfireJobHelper.RemoveCronJob(jobId);
if (entity.IsAutoSend && entity.IsEnable)
{
HangfireJobHelper.AddOrUpdateSystemCronJob(jobId, entity.BusinessScenarioEnum, entity.EmailCron);
}
}
return ResponseOutput.Ok(entity.Id.ToString());
}
@@ -350,6 +350,114 @@ namespace IRaCIS.Core.Application.Service.Common
#region
///getSysDocumentConfirmList 系统文档培训查询
///
[HttpPost]
public async Task<IActionResult> GetSysDocumentConfirmList_Export(SystemDocQuery inQuery,
[FromServices] IRepository<SystemDocument> _systemDocumentRepository,
[FromServices] IRepository<IdentityUser> _identityUserRepository,
[FromServices] IDictionaryService _dictionaryService)
{
var systemDocQuery =
from sysDoc in _systemDocumentRepository.AsQueryable(false)
.Where(t => inQuery.UserTypeId != null ? t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId) : true)
from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.Status == UserStateEnum.Enable && t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
.Where(t => inQuery.UserId != null ? t.Id == inQuery.UserId : true)
.Where(t => inQuery.UserTypeId != null ? t.UserRoleList.Any(t => t.UserTypeId == inQuery.UserTypeId && t.IsUserRoleDisabled == false) : true)
join confirm in _systemDocConfirmedUserRepository.Where() on new { ConfirmUserId = identityUser.Id, SystemDocumentId = sysDoc.Id } equals new { confirm.ConfirmUserId, confirm.SystemDocumentId } into cc
from confirm in cc.DefaultIfEmpty()
select new TrainingRecordExportDTO()
{
IsSystemDoc = true,
Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted,
Name = sysDoc.Name,
FileType = _userInfo.IsEn_Us ? sysDoc.FileType.Value : sysDoc.FileType.ValueCN,
FileTypeId = sysDoc.FileTypeId,
//IsConfirmed = confirm.ConfirmTime != null,
ConfirmUserId = identityUser.Id,
ConfirmTime = confirm.ConfirmTime,
RealName = identityUser.FullName,
UserName = identityUser.UserName,
//UpdateTime = sysDoc.UpdateTime,
//SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
//UserTypeId = trialUser.UserRole.UserTypeId,
//UserTypeShortName = trialUser.UserRole.UserTypeRole.UserTypeShortName,
//Path = sysDoc.Path,
//FullFilePath = sysDoc.Path
};
var unionQuery = systemDocQuery.IgnoreQueryFilters().Where(t => !(t.IsDeleted == true && t.ConfirmTime == null))
.WhereIf(!string.IsNullOrEmpty(inQuery.Name), t => t.Name.Contains(inQuery.Name))
.WhereIf(inQuery.FileTypeId != null, t => t.FileTypeId == inQuery.FileTypeId)
.WhereIf(inQuery.IsConfirmed == true, t => t.ConfirmTime != null)
.WhereIf(inQuery.IsConfirmed == false, t => t.ConfirmTime == null)
.WhereIf(inQuery.StartConfirmTime != null, t => t.ConfirmTime >= inQuery.StartConfirmTime.Value)
.WhereIf(inQuery.EndConfirmTime != null, t => t.ConfirmTime <= inQuery.EndConfirmTime.Value)
.WhereIf(inQuery.BeginCreateTime != null, t => t.CreateTime >= inQuery.BeginCreateTime)
.WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime)
.WhereIf(!string.IsNullOrEmpty(inQuery.UserName), t => t.UserName.Contains(inQuery.UserName))
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted);
var list = await unionQuery.SortToListAsync(inQuery);
#region
var trialDocIdList = list.Where(t => t.IsSystemDoc == false).Select(t => t.Id).ToList();
var sysDocIdList = list.Where(t => t.IsSystemDoc == true).Select(t => t.Id).ToList();
var identityUserIdList = list.Select(t => t.ConfirmUserId).Distinct().ToList();
var sysDocUserTypeList = _systemDocNeedConfirmedUserTypeRepository.Where(t => sysDocIdList.Contains(t.SystemDocumentId)).Select(t => new { t.SystemDocumentId, t.UserTypeRole.UserTypeShortName }).ToList();
var identityUserUserTypeList = _identityUserRepository.Where(t => identityUserIdList.Contains(t.Id)).IgnoreQueryFilters().Select(t => new { IdentityUserId = t.Id, UserTypeList = t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Select(c => c.UserTypeRole.UserTypeShortName).ToList() });
//Concat 不能用导航属性
var sysids = list.Where(t => t.IsSystemDoc == true).Select(t => t.Id).ToList();
//var sysDataList = await _systemDocumentRepository.Where(x => sysids.Contains(x.Id)).Include(x => x.SystemDocumentAttachmentList).ToListAsync();
foreach (var item in list)
{
//if (sysDataList.Any(y => y.Id == item.Id))
//{
// item.AttachmentCount = sysDataList.Where(y => y.Id == item.Id).Select(x => x.SystemDocumentAttachmentList.Where(z => !z.OffLine).Count()).FirstOrDefault();
//}
if (item.IsSystemDoc)
{
item.DocNeedSignUserTypeList = sysDocUserTypeList.Where(t => t.SystemDocumentId == item.Id).Select(t => t.UserTypeShortName).ToList();
}
item.IdentityUserTypeList = identityUserUserTypeList.Where(t => t.IdentityUserId == item.ConfirmUserId).SelectMany(c => c.UserTypeList).ToList();
}
#endregion
var exportInfo = new ExcelExportInfo();
exportInfo.List = list;
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
return await ExcelExportHelper.DataExportAsync(StaticData.Export.CommonTrainingRecordList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(TrainingRecordExportDTO));
}
/// <summary>
/// getDocumentConfirmList 培训记录导出--new
/// </summary>
@@ -1194,39 +1302,65 @@ namespace IRaCIS.Core.Application.Service.Common
[FromServices] IRepository<Trial> _trialRepository)
{
var list = await _visitTaskRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsAnalysisCreate == false)
//.Where(t => t.IsAnalysisCreate == false && t.DoctorUserId != null)
//.Where(t => t.IsAnalysisCreate == false && t.DoctorUserId != null)
.WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState)
.WhereIf(inQuery.ArmEnum != null, t => t.ArmEnum == inQuery.ArmEnum)
.WhereIf(inQuery.TrialSiteId != null, t => t.Subject.TrialSiteId == inQuery.TrialSiteId)
.WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId)
.WhereIf(inQuery.IsUrgent != null, t => t.IsUrgent == inQuery.IsUrgent)
.WhereIf(inQuery.DoctorUserId != null, t => t.DoctorUserId == inQuery.DoctorUserId)
.WhereIf(inQuery.ReadingCategory != null, t => t.ReadingCategory == inQuery.ReadingCategory)
.WhereIf(inQuery.ReadingTaskState != null, t => t.ReadingTaskState == inQuery.ReadingTaskState)
.WhereIf(inQuery.TaskAllocationState != null, t => t.TaskAllocationState == inQuery.TaskAllocationState)
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
.WhereIf(inQuery.IsEffect == true, t => t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze)
.WhereIf(inQuery.IsEffect == false, t => t.TaskState == TaskState.Adbandon || t.TaskState == TaskState.HaveReturned)
.WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState)
.WhereIf(inQuery.TrialSiteId != null, t => t.Subject.TrialSiteId == inQuery.TrialSiteId)
.WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId)
.WhereIf(inQuery.IsUrgent != null, t => t.IsUrgent == inQuery.IsUrgent)
.WhereIf(inQuery.DoctorUserId != null, t => t.DoctorUserId == inQuery.DoctorUserId)
.WhereIf(inQuery.ReadingCategory != null, t => t.ReadingCategory == inQuery.ReadingCategory)
.WhereIf(inQuery.ReadingTaskState != null, t => t.ReadingTaskState == inQuery.ReadingTaskState)
.WhereIf(inQuery.TaskAllocationState != null, t => t.TaskAllocationState == inQuery.TaskAllocationState)
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
.WhereIf(inQuery.ReReadingApplyState != null, t => t.ReReadingApplyState == inQuery.ReReadingApplyState)
.WhereIf(inQuery.CompleteClinicalDataEnum == CompleteClinicalDataEnum.Complete, t => t.IsClinicalDataSign && t.IsNeedClinicalDataSign == true)
.WhereIf(inQuery.CompleteClinicalDataEnum == CompleteClinicalDataEnum.NotComplete, t => t.IsClinicalDataSign == false && t.IsNeedClinicalDataSign == true)
.WhereIf(inQuery.CompleteClinicalDataEnum == CompleteClinicalDataEnum.NA, t => t.IsNeedClinicalDataSign == false)
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false))
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName))
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate))
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime > inQuery.BeginAllocateDate)
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate)
.WhereIf(inQuery.BeginSignTime != null, t => t.SignTime > inQuery.BeginSignTime)
.WhereIf(inQuery.EndSignTime != null, t => t.SignTime < inQuery.EndSignTime)
.WhereIf(inQuery.RandomOrder != null, t => t.RandomOrder == inQuery.RandomOrder)
.WhereIf(inQuery.IsRandomOrderList == true, t => (t.ReadingTaskState == ReadingTaskState.WaitReading || t.ReadingTaskState == ReadingTaskState.Reading) && t.TaskAllocationState == TaskAllocationState.Allocated)
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false))
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName))
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.Subject.Code.Contains(inQuery.SubjectCode) || t.BlindSubjectCode.Contains(inQuery.SubjectCode))
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime > inQuery.BeginAllocateDate)
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1))
.ProjectTo<ReadingTaskExportDto>(_mapper.ConfigurationProvider).ToListAsync();
//var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) };
list = list.OrderBy(t => t.TrialSiteCode).ThenBy(t => t.SubjectCode).ThenBy(t => t.VisitTaskNum).ToList();
var exportInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId).IgnoreQueryFilters().ProjectTo<ExcelExportInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialReadingTaskList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(ReadingTaskExportDto));
if (inQuery.IsRandomOrderList == true)
{
list = list.OrderBy(t => t.RandomOrder).ToList();
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialTaskRandomOrderList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(ReadingTaskExportDto));
}
else
{
list = list.OrderBy(t => t.TrialSiteCode).ThenBy(t => t.SubjectCode).ThenBy(t => t.VisitTaskNum).ToList();
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialReadingTaskList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(ReadingTaskExportDto));
}
}
@@ -1550,8 +1684,8 @@ namespace IRaCIS.Core.Application.Service.Common
{
var emailNoticeConfigQueryable = _emailNoticeConfigrepository
//.WhereIf(inQuery.SystemLevel == null, t => t.SystemLevel == SysEmailLevel.not_sys)
//.WhereIf(inQuery.SystemLevel != null, t => t.SystemLevel == inQuery.SystemLevel)
//.WhereIf(inQuery.IsDistinguishCriteria != null, t => t.IsDistinguishCriteria == inQuery.IsDistinguishCriteria)
.WhereIf(inQuery.SystemLevel != null, t => t.SystemLevel == inQuery.SystemLevel)
.WhereIf(inQuery.IsDistinguishCriteria != null, t => t.IsDistinguishCriteria == inQuery.IsDistinguishCriteria)
.WhereIf(inQuery.CriterionTypeEnum != null, t => t.CriterionTypeEnum == inQuery.CriterionTypeEnum)
.WhereIf(inQuery.BusinessScenarioEnum != null, t => t.BusinessScenarioEnum == inQuery.BusinessScenarioEnum)
.WhereIf(inQuery.IsReturnRequired != null, t => t.IsReturnRequired == inQuery.IsReturnRequired)
@@ -143,6 +143,7 @@ namespace IRaCIS.Core.Application.Service
mapItem.InternationalizationType = batchAdd.InternationalizationType;
mapItem.State = batchAdd.State;
mapItem.PublishLogId = batchAdd.PublishLogId;
var verifyExp1 = new EntityVerifyExp<Internationalization>()
{
@@ -1,4 +1,5 @@
using DocumentFormat.OpenXml.Office2019.Excel.ThreadedComments;
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Helper;
@@ -231,9 +232,9 @@ namespace IRaCIS.Core.Application.Service
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<(DoctorSummarize,bool)> AddOrUpdateGneralSituation(SummarizeInfoDto inDto)
public async Task<(DoctorSummarize, bool)> AddOrUpdateGneralSituation(SummarizeInfoDto inDto)
{
if (inDto.TrialId != null&&inDto.Id==null)
if (inDto.TrialId != null && inDto.Id == null)
{
var systemCount = await _doctorSummarizeRepository.Where(x => x.DoctorId == inDto.DoctorId && x.TrialId == null).CountAsync();
if (systemCount == 0)
@@ -242,7 +243,7 @@ namespace IRaCIS.Core.Application.Service
var dictionery = await _dictionaryRepository.Where(x => x.Parent.Code == "Indication" && x.Code == trialinfo.IndicationEnum.ToString()).FirstNotNullAsync();
inDto.IndicationEn = dictionery.Value;
inDto.Indication = dictionery.ValueCN;
var system= inDto.Clone();
var system = inDto.Clone();
system.TrialId = null;
system.IsMain = true;
await _doctorSummarizeRepository.InsertOrUpdateAsync(system, true);
@@ -255,7 +256,7 @@ namespace IRaCIS.Core.Application.Service
if (systemCount == 0)
{
inDto.IsMain = true;
}
if (inDto.Indication.IsNullOrEmpty() && inDto.IndicationEn.IsNullOrEmpty())
{
@@ -263,19 +264,19 @@ namespace IRaCIS.Core.Application.Service
inDto.IndicationEn = "Default";
}
var exists = await _doctorSummarizeRepository
.Where(x=> x.IndicationEn!=string.Empty && x.Indication!=string.Empty)
.Where( x => x.IndicationEn == inDto.IndicationEn|| x.Indication == inDto.Indication)
.AnyAsync(x => x.DoctorId == inDto.DoctorId && x.TrialId == null&&x.Id!=inDto.Id);
.Where(x => x.IndicationEn != string.Empty && x.Indication != string.Empty)
.Where(x => x.IndicationEn == inDto.IndicationEn || x.Indication == inDto.Indication)
.AnyAsync(x => x.DoctorId == inDto.DoctorId && x.TrialId == null && x.Id != inDto.Id);
if (exists)
{
throw new BusinessValidationFailedException(_localizer["DoctorSummarize_repeat"]);
}
}
if (inDto.TrialId != null && inDto.SaveSummarizeInfoType!= SaveSummarizeInfo.SaveSelf)
if (inDto.TrialId != null && inDto.SaveSummarizeInfoType != SaveSummarizeInfo.SaveSelf)
{
switch (inDto.SaveSummarizeInfoType)
{
@@ -313,16 +314,16 @@ namespace IRaCIS.Core.Application.Service
if (inDto.TrialId == null && inDto.IsMain)
{
await _doctorSummarizeRepository.BatchUpdateNoTrackingAsync(x => x.DoctorId == inDto.DoctorId && x.TrialId == null,
await _doctorSummarizeRepository.BatchUpdateNoTrackingAsync(x => x.DoctorId == inDto.DoctorId && x.TrialId == null,
x => new DoctorSummarize()
{
IsMain = false
});
{
IsMain = false
});
}
var entity = await _doctorSummarizeRepository.InsertOrUpdateAsync(inDto, true);
return (entity,true);
return (entity, true);
}
/// <summary>
@@ -333,7 +334,7 @@ namespace IRaCIS.Core.Application.Service
[HttpPost]
public async Task<bool> DeleteSummarizeInfo(DeleteSummarizeInfoInDto inDto)
{
var result = await _doctorSummarizeRepository.DeleteFromQueryAsync(x=>x.Id==inDto.Id);
var result = await _doctorSummarizeRepository.DeleteFromQueryAsync(x => x.Id == inDto.Id);
return await _doctorSummarizeRepository.SaveChangesAsync();
}
@@ -345,7 +346,7 @@ namespace IRaCIS.Core.Application.Service
[HttpPost]
public async Task<UpdateGneralSituationDto> GetSummarizeInfo(GetSummarizeInfoInDto inDto)
{
if (inDto.TrialId != null)
{
var doctorInfo = await trialExperienceService.GetTrialDoctorInfo(new GetTrialDoctorInfoInDto()
@@ -357,8 +358,9 @@ namespace IRaCIS.Core.Application.Service
}
var result = await _doctorSummarizeRepository.Where(t => t.DoctorId == inDto.DoctorId && t.TrialId == inDto.TrialId)
.ProjectTo<SummarizeInfoDto>(_mapper.ConfigurationProvider).ToListAsync();
return new UpdateGneralSituationDto() {
SummarizeList= result
return new UpdateGneralSituationDto()
{
SummarizeList = result
};
}
@@ -378,30 +380,36 @@ namespace IRaCIS.Core.Application.Service
messageToSend.To.Add(new MailboxAddress(String.Empty, item));
}
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
{
;
var topicStr = string.Format(input.topicStr,string.Empty);
;
var topicStr = string.Format(input.topicStr, string.Empty);
var htmlBodyStr = string.Format(
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
_systemEmailConfig.SiteUrl.Replace("login",string.Empty)+inDto.Url
_systemEmailConfig.SiteUrl.Replace("login", string.Empty) + inDto.Url
);
return (topicStr, htmlBodyStr);
};
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(_emailNoticeConfigrepository,
EmailBusinessScenario.Reviewer_CV_Collection,
var scenario = EmailBusinessScenario.Reviewer_CV_Collection;
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
if (emailConfig != null)
{
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
}
messageToSend, emailConfigFunc);
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
return true;
}
@@ -491,7 +499,7 @@ namespace IRaCIS.Core.Application.Service
var doctorBasicInfo = (await _doctorRepository.Where(t => t.Id == doctorId)
.ProjectTo<DoctorBasicInfoDTO>(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
doctorBasicInfo.IsHaveAccount =await _userRoleRepository.AnyAsync(x => x.DoctorId == doctorId);
doctorBasicInfo.IsHaveAccount = await _userRoleRepository.AnyAsync(x => x.DoctorId == doctorId);
return doctorBasicInfo;
@@ -0,0 +1,585 @@
//--------------------------------------------------------------------
// 此代码由liquid模板自动生成 byzhouhang 20240909
// 生成时间 2025-03-27 06:13:33Z
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using IRaCIS.Core.Domain.Models;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Infrastructure.Extention;
using System.Threading.Tasks;
using IRaCIS.Core.Infra.EFCore;
using AutoMapper.Execution;
using System.Linq;
using IRaCIS.Core.Infrastructure;
using DocumentFormat.OpenXml.Office2010.Excel;
using MassTransit;
using NPOI.POIFS.Properties;
using Org.BouncyCastle.Crypto;
using Microsoft.AspNetCore.Http;
namespace IRaCIS.Core.Application.Service;
/// <summary>
/// 稽查文档
/// </summary>
/// <returns></returns>
[ApiExplorerSettings(GroupName = "FileRecord")]
public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepository,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer): BaseService
{
/// <summary>
/// 获取稽查文档
/// </summary>
/// <param name="inQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<PageOutput<AuditDocumentView>> GetAuditDocumentList(AuditDocumentQuery inQuery)
{
var auditDocumentQueryable = _auditDocumentRepository
.ProjectTo<AuditDocumentView>(_mapper.ConfigurationProvider);
var pageList = await auditDocumentQueryable.ToPagedListAsync(inQuery);
return pageList;
}
/// <summary>
/// 修改稽查文档
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> UpdateAuditDocument(AuditDocumentUpdateDto inDto)
{
AuditDocumentAddOrEdit addOrEdit = _mapper.Map<AuditDocumentAddOrEdit>(inDto);
addOrEdit.IsUpdate = true;
var result= await AddOrUpdateAuditDocument(addOrEdit);
return ResponseOutput.Ok(result.Id);
}
/// <summary>
/// 新增文件夹
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
[HttpPost]
public async Task<IResponseOutput> AddFolder(AuditDocumentAddOrEdit inDto)
{
if (await _auditDocumentRepository.AnyAsync(x => x.Name == inDto.Name && x.AuditDocumentTypeEnum == inDto.AuditDocumentTypeEnum && x.ParentId == inDto.ParentId))
{
throw new BusinessValidationFailedException(_localizer["AuditDocument_CanNotAddFolder"]);
}
List<AuditDocumentAddOrEdit> auditDocumentAddOrEdits = new List<AuditDocumentAddOrEdit>();
auditDocumentAddOrEdits.Add(inDto);
var result= await AddAuditDocument(auditDocumentAddOrEdits);
return ResponseOutput.Ok(result);
}
/// <summary>
/// 新增稽查文档
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> AddAuditDocument(List<AuditDocumentAddOrEdit> inDto)
{
List<Guid> resultData = new List<Guid>();
inDto.ForEach(x => x.IsUpdate = false);
await addData(inDto);
async Task addData(List<AuditDocumentAddOrEdit> data)
{
foreach(var item in data)
{
var result= await AddOrUpdateAuditDocument(item);
resultData.Add(result.Id);
item.Children.ForEach(x => {
x.ParentId = result.Id;
x.IsUpdate = false;
});
if (item.Children.Count() > 0)
{
await addData(item.Children);
}
}
}
return ResponseOutput.Ok(resultData);
}
/// <summary>
/// 通用方法
/// </summary>
/// <param name="inDto"></param>
private async Task<AuditDocument> AddOrUpdateAuditDocument(AuditDocumentAddOrEdit inDto)
{
var alikeData = await _auditDocumentRepository.Where(x =>x.Id!=inDto.Id&& x.ParentId == inDto.ParentId&&x.Name==inDto.Name&&x.AuditDocumentTypeEnum==inDto.AuditDocumentTypeEnum).FirstOrDefaultAsync();
if (alikeData != null)
{
if (inDto.AuditDocumentTypeEnum == AuditDocumentType.Folder)
{
if (inDto.IsUpdate)
{
throw new BusinessValidationFailedException(_localizer["AuditDocument_CanNotAddFolder"]);
}
else
{
return alikeData;
}
}
else
{
var entityData = await _auditDocumentRepository.InsertOrUpdateAsync(inDto, true);
var historicalVersionIds = await _auditDocumentRepository.Where(x => x.MainFileId == alikeData.Id).OrderBy(x => x.Version).Select(x => x.Id).ToListAsync();
historicalVersionIds.Add(alikeData.Id);
int num = 1;
foreach (var item in historicalVersionIds)
{
await _auditDocumentRepository.UpdatePartialFromQueryAsync(item, x => new AuditDocument()
{
MainFileId = entityData.Id,
ParentId = null,
Version = num,
AuditDocumentTypeEnum = AuditDocumentType.HistoricalVersion
},true);
num++;
}
return entityData;
}
}
var entity = await _auditDocumentRepository.InsertOrUpdateAsync(inDto, true);
return entity;
}
/// <summary>
/// 获取面包屑导航
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<AuditDocumentUpdateDto>> GetBreadcrumbData(GetBreadcrumbDataInDto inDto)
{
List<AuditDocumentUpdateDto> result=new List<AuditDocumentUpdateDto>();
await findParent(result, inDto.Id);
async Task findParent(List<AuditDocumentUpdateDto> datas, Guid id)
{
var data= await _auditDocumentRepository.Where(x => x.Id == id).ProjectTo<AuditDocumentUpdateDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
datas.Add(data);
if (data.ParentId != null)
{
await findParent(datas, data.ParentId.Value);
}
}
result.Reverse();
return result;
}
/// <summary>
/// 获取文件树形结构 (传Id 根节点就是自己)
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<PageOutput<AuditDocumentData>> GetAuditDocumentData(GetAuditDocumentDataInDto inDto)
{
var defalutSortArray = new string[] { nameof(AuditDocumentData.AuditDocumentTypeEnum), nameof(AuditDocumentData.Name) };
if (inDto.SortField.IsNotNullOrEmpty())
{
defalutSortArray = new string[] { nameof(AuditDocumentData.AuditDocumentTypeEnum), inDto.SortField + (inDto.Asc ? " asc" : " desc") };
inDto.SortField = string.Empty;
}
// 新取出来排序 然后再找子项
var data= (await _auditDocumentRepository
.Where(x=>x.AuditDocumentTypeEnum!=AuditDocumentType.HistoricalVersion)
.WhereIf(inDto.IsAuthorization!=null,x=>x.IsAuthorization==inDto.IsAuthorization)
.ProjectTo<AuditDocumentData>(_mapper.ConfigurationProvider).ToPagedListAsync(new PageInput() {
PageIndex=1,
PageSize=999999,
}, defalutSortArray) ).CurrentPageData.ToList();
if (inDto.Name.IsNotNullOrEmpty())
{
List<Guid> findIds = new List<Guid>();
var findData = data.Where(x => x.Name.Contains(inDto.Name)).Select(x => x.Id.Value).ToList();
GetParentId(findIds, findData, data);
findIds.AddRange(findData);
data = data.Where(x => findIds.Distinct().Contains(x.Id.Value)).ToList();
}
var query = data
.WhereIf(inDto.SelfId != null, x => inDto.SelfId == x.Id)
.WhereIf(inDto.Id != null, x => inDto.Id == x.ParentId)
.WhereIf(inDto.Id == null&& inDto.SelfId == null, x => x.ParentId == null);
PageOutput<AuditDocumentData> result = new PageOutput<AuditDocumentData>()
{
PageIndex = inDto.PageIndex,
PageSize = inDto.PageSize,
TotalCount = query.Count(),
};
var root = query
.Skip(inDto.PageSize * (inDto.PageIndex - 1)).Take(inDto.PageSize).ToList();
var historicalVersionList = await _auditDocumentRepository
.Where(x => x.AuditDocumentTypeEnum == AuditDocumentType.HistoricalVersion).ProjectTo<AuditDocumentData>(_mapper.ConfigurationProvider).ToListAsync();
foreach (var item in root)
{
GetChildren(item, data, historicalVersionList);
}
result.CurrentPageData = root;
return result;
}
private void GetParentId(List<Guid> parentIds, List<Guid> ids, List<AuditDocumentData> dataList)
{
var parentid = dataList.Where(x => ids.Contains(x.Id.Value) && x.ParentId != null).Select(x => x.ParentId.Value).ToList();
if (parentid.Count() > 0)
{
parentIds.AddRange(parentid);
GetParentId(parentIds, parentid, dataList);
}
}
private void GetChildren(AuditDocumentData item, List<AuditDocumentData> dataList, List<AuditDocumentData> historyList)
{
item.Children = dataList.Where(x => x.ParentId == item.Id).ToList();
item.HistoricalVersionsCount= historyList.Where(x => x.MainFileId == item.Id).Count();
foreach (var x in item.Children)
{
GetChildren(x, dataList, historyList);
}
}
/// <summary>
/// 删除稽查文档
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> DeleteAuditDocument(DeleteAuditDocumentInDto inDto)
{
var data = await _auditDocumentRepository.Select(x => new DeleteAudit (){
Id=x.Id,
ParentId= x.ParentId,
MainFileId= x.MainFileId
}).ToListAsync();
List<Guid> DeleteId= inDto.Ids;
finId(inDto.Ids, data);
void finId(List<Guid> deletids, List<DeleteAudit> deletes)
{
DeleteId.AddRange(deletids);
var temp = deletes.Where(x =>(x.ParentId!=null&& deletids.Contains(x.ParentId.Value))||(x.MainFileId!=null&& deletids.Contains(x.MainFileId.Value))).Select(x => x.Id).ToList();
if (temp.Count() > 0)
{
finId(temp, deletes);
}
}
DeleteId = DeleteId.Distinct().ToList();
var mainFileId=await _auditDocumentRepository.Where(x => DeleteId.Contains(x.Id)&&x.MainFileId!=null).Select(x => x.MainFileId).Distinct().ToListAsync();
var success = await _auditDocumentRepository.DeleteFromQueryAsync(t => DeleteId.Distinct().Contains(t.Id), true);
foreach (var item in mainFileId)
{
var historicalVersionList = await _auditDocumentRepository.Where(x => x.MainFileId == item).OrderBy(x=>x.Version).ToListAsync();
var num = 1;
foreach (var historical in historicalVersionList)
{
await _auditDocumentRepository.UpdatePartialFromQueryAsync(historical.Id, x => new AuditDocument()
{
Version = num,
}, true);
num++;
}
}
return ResponseOutput.Ok();
}
/// <summary>
/// 移动文件或者文件夹 到其他文件夹
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> MovieFileOrFolder(MovieFileOrFolderInDto inDto)
{
var data = await _auditDocumentRepository.Select(x => new DeleteAudit()
{
Id = x.Id,
ParentId = x.ParentId,
AuditDocumentTypeEnum = x.AuditDocumentTypeEnum,
MainFileId = x.MainFileId
}).ToListAsync();
foreach (var id in inDto.Ids)
{
var file = data.Where(x => x.Id == id).FirstOrDefault();
if (file.AuditDocumentTypeEnum == AuditDocumentType.Folder)
{
if (finChild(new List<Guid> { id }, inDto.ParentId, data))
{
throw new BusinessValidationFailedException(_localizer["AuditDocument_CanNotMove"]);
}
}
}
bool finChild(List<Guid> ids, Guid ChildId, List<DeleteAudit> data)
{
var child = data.Where(x => x.ParentId != null && ids.Contains(x.ParentId.Value)).ToList();
if (child.Count() == 0)
{
return false;
}
else if (child.Any(x => x.Id == ChildId))
{
return true;
}
else
{
var newids = child.Select(x => x.Id).ToList();
return finChild(newids, ChildId, data);
}
}
foreach (var id in inDto.Ids)
{
await _auditDocumentRepository.UpdatePartialFromQueryAsync(id, x => new AuditDocument()
{
ParentId = inDto.ParentId
});
await _auditDocumentRepository.SaveChangesAsync();
}
return ResponseOutput.Ok();
}
/// <summary>
/// 复制文件或者文件夹
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> CopyFileOrFolder(MovieFileOrFolderInDto inDto)
{
foreach (var item in inDto.Ids)
{
var data = (await GetAuditDocumentData(new GetAuditDocumentDataInDto()
{
SelfId =item,
PageIndex=1,
PageSize= 1000
})).CurrentPageData;
List<AuditDocumentAddOrEdit> auditDocumentAddOrEdits = _mapper.Map<List<AuditDocumentAddOrEdit>>(data);
auditDocumentAddOrEdits.ForEach(x => {
x.IsUpdate = false;
x.Id = null;
x.ParentId = inDto.ParentId;
});
await addData(auditDocumentAddOrEdits);
}
async Task addData(List<AuditDocumentAddOrEdit> data)
{
foreach (var item in data)
{
item.Id = null;
var result = await AddOrUpdateAuditDocument(item);
item.Children.ForEach(x => {
x.ParentId = result.Id;
x.IsUpdate = false;
x.Id = null;
});
if (item.Children.Count() > 0)
{
await addData(item.Children);
}
}
}
return ResponseOutput.Ok();
}
/// <summary>
/// 获取历史版本
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<HistoricalVersionDto>> GetHistoricalVersion(GetHistoricalVersionInDto inDto)
{
List< HistoricalVersionDto > result=new List<HistoricalVersionDto>();
result = await _auditDocumentRepository.Where(x => x.MainFileId == inDto.Id).ProjectTo<HistoricalVersionDto>(_mapper.ConfigurationProvider).OrderByDescending(x => x.Version).ToListAsync();
var currentData = await _auditDocumentRepository.Where(x => x.Id == inDto.Id).ProjectTo<HistoricalVersionDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
currentData.IsCurrentVersion = true;
result.Insert(0, currentData);
return result;
}
/// <summary>
/// 把历史版本设置为当前版本
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> SetCurrentVersion(SetCurrentVersionInDto inDto)
{
var file = await _auditDocumentRepository.Where(x => x.Id == inDto.Id).FirstNotNullAsync();
if (file.AuditDocumentTypeEnum != AuditDocumentType.HistoricalVersion)
{
throw new BusinessValidationFailedException(_localizer["AuditDocument_CanNotSetCurrentVersion"]);
}
var mainFile = await _auditDocumentRepository.Where(x => x.Id == file.MainFileId).FirstNotNullAsync();
var historicalVersionIds= await _auditDocumentRepository.Where(x => x.MainFileId == mainFile.Id&&x.Id!=inDto.Id).OrderBy(x=>x.Version).Select(x=>x.Id).ToListAsync();
historicalVersionIds.Add(mainFile.Id);
await _auditDocumentRepository.UpdatePartialFromQueryAsync(inDto.Id, x => new AuditDocument() {
MainFileId=null,
ParentId= mainFile.ParentId,
AuditDocumentTypeEnum=AuditDocumentType.File,
});
int num = 1;
foreach (var item in historicalVersionIds)
{
await _auditDocumentRepository.UpdatePartialFromQueryAsync(item, x => new AuditDocument()
{
MainFileId = inDto.Id,
ParentId = null,
Version=num,
AuditDocumentTypeEnum= AuditDocumentType.HistoricalVersion
});
num++;
}
await _auditDocumentRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
/// <summary>
/// 设置是否授权
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> SetIsAuthorization(SetIsAuthorizationInDto inDto)
{
var data = await _auditDocumentRepository.Select(x => new DeleteAudit()
{
Id = x.Id,
ParentId = x.ParentId,
MainFileId = x.MainFileId
}).ToListAsync();
List<Guid> allid = new List<Guid>();
findChild(allid, inDto.Ids, data);
if (inDto.IsAuthorization)
{
findParent(allid, inDto.Ids, data);
}
allid= allid.Distinct().ToList();
await _auditDocumentRepository.UpdatePartialFromQueryAsync(t => allid.Contains(t.Id), x => new AuditDocument() {
IsAuthorization = inDto.IsAuthorization
});
await _auditDocumentRepository.SaveChangesAsync();
return ResponseOutput.Ok();
void findParent(List<Guid> allId, List<Guid> current, List<DeleteAudit> data)
{
allId.AddRange(current);
var parent = data.Where(x => current.Contains(x.Id)).Select(x => x.ParentId).Where(x=>x!=null).Select(x=>(Guid)x).ToList();
if (parent.Count() > 0)
{
findParent(allId, parent, data);
}
}
void findChild(List<Guid> allId,List<Guid> current, List<DeleteAudit> data)
{
allId.AddRange(current);
var child = data.Where(x =>(x.ParentId!=null&& current.Contains(x.ParentId.Value))||(x.MainFileId!=null&&current.Contains(x.MainFileId.Value))).Select(x => x.Id).ToList();
if (child.Count() > 0)
{
findChild(allId, child, data);
}
}
}
}
@@ -0,0 +1,167 @@
//--------------------------------------------------------------------
// 此代码由liquid模板自动生成 byzhouhang 20240909
// 生成时间 2025-03-27 06:13:37Z
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using System;
using IRaCIS.Core.Domain.Share;
using System.Collections.Generic;
namespace IRaCIS.Core.Application.ViewModel;
public class DeleteAudit
{
public Guid Id { get; set; }
public AuditDocumentType AuditDocumentTypeEnum { get; set; }
public Guid? ParentId { get; set; }
public Guid? MainFileId { get; set; }
}
public class DeleteAuditDocumentInDto
{
public List<Guid> Ids { get; set; }
}
public class GetAuditDocumentDataInDto:PageInput
{
public Guid? Id { get; set; }
public Guid? SelfId { get; set; }
public bool? IsAuthorization { get; set; }
public string Name { get; set; } = string.Empty;
}
public class GetAuditDocumentDataOutDto
{
public List<AuditDocumentData> Data { get; set; } = new List<AuditDocumentData> { };
}
public class AuditDocumentData : AuditDocumentUpdateDto
{
public DateTime CreateTime { get; set; }
public DateTime UpdateTime { get; set; }
public Guid? MainFileId { get; set; }
public int? Version { get; set; }
public int HistoricalVersionsCount { get; set; }
public List<AuditDocumentData> Children { get; set; }=new List<AuditDocumentData> (){ };
}
public class AuditDocumentView : AuditDocumentAddOrEdit
{
public DateTime CreateTime { get; set; }
public DateTime UpdateTime { get; set; }
}
public class SetIsAuthorizationInDto
{
public List<Guid> Ids { get; set; }
public bool IsAuthorization { get; set; }
}
public class SetCurrentVersionInDto
{
public Guid Id { get; set; }
}
public class GetHistoricalVersionInDto
{
public Guid Id { get; set; }
}
public class GetHistoricalVersionOutDto
{
public AuditDocumentData CurrentData { get; set; }
public List<AuditDocumentData> HistoricalVersionList { get; set; } = new List<AuditDocumentData> { };
}
public class MovieFileOrFolderInDto
{
public List<Guid> Ids { get; set; }
public Guid ParentId { get; set; }
}
public class HistoricalVersionDto: AuditDocumentUpdateDto
{
public bool IsCurrentVersion { get; set; } = false;
public int? Version { get; set; }
public DateTime CreateTime { get; set; }
public DateTime UpdateTime { get; set; }
}
public class AuditDocumentUpdateDto
{
public Guid? Id { get; set; }
public AuditDocumentType AuditDocumentTypeEnum { get; set; }
public string? FileFormat { get; set; }
public string? FilePath { get; set; }
public decimal? FileSize { get; set; }
public bool IsAuthorization { get; set; }
// public Guid? MainFileId { get; set; }
public string Name { get; set; }
public Guid? ParentId { get; set; }
}
public class GetBreadcrumbDataInDto
{
public Guid Id { get; set; }
}
public class AuditDocumentAddOrEdit: AuditDocumentUpdateDto
{
public List<AuditDocumentAddOrEdit> Children { get; set; }=new List<AuditDocumentAddOrEdit>() { };
public bool IsUpdate { get; set; } = true;
}
public class AuditDocumentQuery:PageInput
{
public AuditDocumentType? AuditDocumentTypeEnum { get; set; }
public string? FileFormat { get; set; }
public string? FilePath { get; set; }
public decimal? FileSize { get; set; }
public bool? IsAuthorization { get; set; }
public Guid? MainFileId { get; set; }
public string? Name { get; set; }
public Guid? ParentId { get; set; }
}
@@ -25,6 +25,11 @@ public class SysFileTypeAddOrEdit
public ArchiveType ArchiveTypeEnum { get; set; }
/// <summary>
/// 文档类型
/// </summary>
public SysTemplateType SysTemplateTypeEnum { get; set; }
public bool IsConfirmRecord { get; set; }
public bool IsEnable { get; set; }
@@ -45,6 +50,8 @@ public class SysFileTypeQuery : PageInput
{
public ArchiveType? ArchiveTypeEnum { get; set; }
public SysTemplateType? SysTemplateTypeEnum { get; set; }
public bool? IsConfirmRecord { get; set; }
public bool? IsEnable { get; set; }
@@ -8,6 +8,51 @@ using System.ComponentModel.DataAnnotations;
namespace IRaCIS.Core.Application.Contracts
{
public class SystemDocumentAttachmentView : SystemDocumentAttachmentAddOrEdit
{
public DateTime CreateTime { get; set; }
public DateTime UpdateTime { get; set; }
}
public class SystemDocumentAttachmentAddOrEdit
{
public Guid? Id { get; set; }
public string FileFormat { get; set; }
public string Name { get; set; }
public string FileName { get; set; }
public string FilePath { get; set; }
public decimal? FileSize { get; set; }
public bool OffLine { get; set; }
public Guid SystemDocumentId { get; set; }
}
public class SystemDocumentAttachmentQuery : PageInput
{
public string? FileFormat { get; set; }
public string? FileName { get; set; }
public string? FilePath { get; set; }
public decimal? FileSize { get; set; }
public bool? OffLine { get; set; }
public Guid? SystemDocumentId { get; set; }
}
/// <summary> SystemDocumentView 列表视图模型 </summary>
public class SystemDocumentView : SystemDocumentAddOrEdit
{
@@ -17,6 +62,8 @@ namespace IRaCIS.Core.Application.Contracts
public string FileType { get; set; } = string.Empty;
public int AttachmentCount { get; set; }
public List<NeedConfirmedUserTypeView> NeedConfirmedUserTypeList { get; set; } = new List<NeedConfirmedUserTypeView>();
}
@@ -46,6 +93,10 @@ namespace IRaCIS.Core.Application.Contracts
public class UnionDocumentWithConfirmInfoView : UnionDocumentView
{
public bool IsNeedSendEmial { get; set; }
public DateTime UserCreateTime { get; set; }
public DateTime? ConfirmTime { get; set; }
@@ -58,6 +109,28 @@ namespace IRaCIS.Core.Application.Contracts
public string RealName { get; set; } = string.Empty;
public int AttachmentCount { get; set; }
public DateTime? SuggestFinishTime
{
get
{
if (this.CreateTime > this.UserCreateTime && this.CurrentStaffTrainDays != null)
{
return DateTime.Parse(this.CreateTime.AddDays(this.CurrentStaffTrainDays.Value).ToString("yyyy-MM-dd")+" 22:00:00");
}
if (this.CreateTime < this.UserCreateTime && this.NewStaffTrainDays != null)
{
return DateTime.Parse(this.UserCreateTime.AddDays(this.NewStaffTrainDays.Value).ToString("yyyy-MM-dd") + " 22:00:00");
}
return null;
}
}
public string DocTypeCode { get; set; }
public List<string> UserConfirmedUserTypeList => (DocNeedSignUserTypeList != null && IdentityUserTypeList != null) ? IdentityUserTypeList.Intersect(DocNeedSignUserTypeList).ToList() : new List<string>();
@@ -119,6 +192,15 @@ namespace IRaCIS.Core.Application.Contracts
public bool IsSigned { get; set; }
public Guid? UserTypeId { get; set; }
public DocUserSignType? DocUserSignType { get; set; }
public DateTime? BeginCreateTime { get; set; }
public DateTime? EndCreateTime { get; set; }
}
public class GetNextUnSignDocumentInDto
@@ -170,6 +252,47 @@ namespace IRaCIS.Core.Application.Contracts
public string SignText { get; set; } = string.Empty;
}
public class SystemDocQuery : PageInput
{
public Guid? FileTypeId { get; set; }
public string Name { get; set; } = string.Empty;
public bool? IsSign { get; set; }
public Guid? UserTypeId { get; set; }
public Guid? UserId { get; set; }
public bool? IsConfirmed { get; set; }
/// <summary>
/// 课时状态
/// </summary>
public bool? IsDeleted { get; set; }
/// <summary>
/// 用户名
/// </summary>
public string? UserName { get; set; }
/// <summary>
/// 开始时间
/// </summary>
public DateTime? StartConfirmTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime? EndConfirmTime { get; set; }
public DateTime? BeginCreateTime { get; set; }
public DateTime? EndCreateTime { get; set; }
}
public class DocumentTrialUnionQuery : TrialUserDocUnionQuery
{
@@ -197,6 +320,10 @@ namespace IRaCIS.Core.Application.Contracts
/// 结束时间
/// </summary>
public DateTime? EndConfirmTime { get; set; }
public DateTime? BeginCreateTime { get; set; }
public DateTime? EndCreateTime { get; set; }
}
///<summary> SystemDocumentAddOrEdit 列表查询参数模型</summary>
@@ -213,6 +340,29 @@ namespace IRaCIS.Core.Application.Contracts
public DocUserSignType DocUserSignType { get; set; }
/// <summary>
/// 现有员工培训天数
/// </summary>
public int? CurrentStaffTrainDays { get; set; }
/// <summary>
/// 新员工培训天数
/// </summary>
public int? NewStaffTrainDays { get; set; }
/// <summary>
/// 是否发布
/// </summary>
public bool IsPublish { get; set; } = false;
}
public class PublishSystemDocumentInDto
{
public List<Guid> Ids { get; set; }
}
public class AddOrEditSystemDocument : SystemDocumentAddOrEdit
@@ -27,6 +27,13 @@ namespace IRaCIS.Core.Application.Contracts
Task<PageOutput<UnionDocumentWithConfirmInfoView>> getWaitSignSysDocList(SystemDocumentQuery querySystemDocument);
Task<PageOutput<SystemDocumentAttachmentView>> GetSystemDocumentAttachmentList(SystemDocumentAttachmentQuery inQuery);
Task<IResponseOutput> AddOrUpdateSystemDocumentAttachment(SystemDocumentAttachmentAddOrEdit addOrEditSystemDocumentAttachment);
Task<IResponseOutput> DeleteSystemDocumentAttachment(Guid systemDocumentAttachmentId);
}
@@ -33,6 +33,7 @@ public class SysFileTypeService(IRepository<SysFileType> _sysFileTypeRepository,
var sysFileTypeQueryable = _sysFileTypeRepository
.WhereIf(inQuery.ArchiveTypeEnum != null, t => t.ArchiveTypeEnum == inQuery.ArchiveTypeEnum)
.WhereIf(inQuery.SysTemplateTypeEnum != null, t => t.SysTemplateTypeEnum == inQuery.SysTemplateTypeEnum)
.WhereIf(inQuery.IsConfirmRecord != null, t => t.IsConfirmRecord == inQuery.IsConfirmRecord)
.WhereIf(inQuery.SubIdentificationEnum != null, t => t.SubIdentificationEnum == inQuery.SubIdentificationEnum)
.WhereIf(inQuery.IsEnable != null, t => t.IsEnable == inQuery.IsEnable)
@@ -1,27 +1,82 @@
//--------------------------------------------------------------------
// 此代码由T4模板自动生成 byzhouhang 20210918
// 生成时间 2022-01-05 09:17:03
// 生成时间 2022-01-05 09:17:03
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain;
using Microsoft.AspNetCore.Mvc;
using UserRole = IRaCIS.Core.Domain.Models.UserRole;
using IRaCIS.Core.Application.MassTransit.Consumer;
using MassTransit.Mediator;
using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.Application.Services
{
/// <summary>
/// SystemDocumentService
/// </summary>
/// </summary>
[ApiExplorerSettings(GroupName = "Trial")]
public class SystemDocumentService(IRepository<SystemDocument> _systemDocumentRepository,
IRepository<UserRole> _userRoleRepository,
IScopedMediator _mediatorScoped,
IRepository<SystemDocumentAttachment> _systemDocumentAttachmentRepository,
IRepository<IdentityUser> _identityUserRepository,
IServiceScopeFactory serviceScopeFactory,
IRepository<SystemDocConfirmedIdentityUser> _systemDocConfirmedUserRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ISystemDocumentService
{
/// <summary>
/// 获取系统文档附件
/// </summary>
/// <param name="inQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<PageOutput<SystemDocumentAttachmentView>> GetSystemDocumentAttachmentList(SystemDocumentAttachmentQuery inQuery)
{
var systemDocumentAttachmentQueryable = _systemDocumentAttachmentRepository
.WhereIf(inQuery.SystemDocumentId != null, t => t.SystemDocumentId == inQuery.SystemDocumentId)
.WhereIf(inQuery.OffLine != null, t => t.OffLine == inQuery.OffLine)
.WhereIf(inQuery.FileName != null, t => t.FileName == inQuery.FileName)
.WhereIf(inQuery.FileFormat != null, t => t.FileFormat == inQuery.FileFormat)
.ProjectTo<SystemDocumentAttachmentView>(_mapper.ConfigurationProvider);
var pageList = await systemDocumentAttachmentQueryable.ToPagedListAsync(inQuery);
return pageList;
}
/// <summary>
/// 新增或编辑系统文档附件
/// </summary>
/// <param name="addOrEditSystemDocumentAttachment"></param>
/// <returns></returns>
public async Task<IResponseOutput> AddOrUpdateSystemDocumentAttachment(SystemDocumentAttachmentAddOrEdit addOrEditSystemDocumentAttachment)
{
var entity = await _systemDocumentAttachmentRepository.InsertOrUpdateAsync(addOrEditSystemDocumentAttachment, true);
return ResponseOutput.Ok(entity.Id.ToString());
}
/// <summary>
/// 删除系统文档附件
/// </summary>
/// <param name="systemDocumentAttachmentId"></param>
/// <returns></returns>
[HttpDelete("{systemDocumentAttachmentId:guid}")]
public async Task<IResponseOutput> DeleteSystemDocumentAttachment(Guid systemDocumentAttachmentId)
{
var success = await _systemDocumentAttachmentRepository.DeleteFromQueryAsync(t => t.Id == systemDocumentAttachmentId, true);
return ResponseOutput.Ok();
}
/// <summary>
@@ -35,7 +90,11 @@ namespace IRaCIS.Core.Application.Services
var systemDocumentQueryable = _systemDocumentRepository.AsQueryable(true)
.WhereIf(!string.IsNullOrEmpty(inQuery.Name), t => t.Name.Contains(inQuery.Name))
.WhereIf(inQuery.FileTypeId != null, t => t.FileTypeId == inQuery.FileTypeId)
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
.WhereIf(inQuery.DocUserSignType != null, t => t.DocUserSignType == inQuery.DocUserSignType)
.WhereIf(inQuery.BeginCreateTime != null, t => t.CreateTime >= inQuery.BeginCreateTime)
.WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime)
.WhereIf(inQuery.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId))
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
.ProjectTo<SystemDocumentView>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us, userId = _userInfo.UserRoleId });
return await systemDocumentQueryable.ToPagedListAsync(inQuery);
@@ -71,6 +130,11 @@ namespace IRaCIS.Core.Application.Services
}
// 保存修改前的状态和需要确认的用户类型列表
bool beforeIsPublish = document.IsPublish;
bool beforeIsDeleted = document.IsDeleted;
var beforeUserTypeIds = document.NeedConfirmedUserTypeList.Select(x => x.NeedConfirmUserTypeId).ToList();
_mapper.Map(addOrEditSystemDocument, document);
#region
@@ -94,9 +158,39 @@ namespace IRaCIS.Core.Application.Services
#endregion
var success = await _systemDocumentRepository.SaveChangesAsync();
// 检查是否需要发送邮件给新增的角色
if (beforeIsPublish && document.IsPublish && !beforeIsDeleted && !document.IsDeleted)
{
// 找出新增的用户角色ID
var newUserTypeIds = addOrEditSystemDocument.NeedConfirmedUserTypeIdList
.Where(id => !beforeUserTypeIds.Contains(id))
.ToList();
if (newUserTypeIds.Any()&& newUserTypeIds.Count()>0)
{
// 发送邮件给新增的角色
Console.WriteLine("开始 发送系统文档更新邮件给新增角色");
Console.WriteLine(string.Join(",", newUserTypeIds));
Task.Run(async () =>
{
// 创建独立作用域
using (var scope = serviceScopeFactory.CreateScope())
{
// 从新作用域解析服务
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
// 只发送给新增的角色
await mediator.Publish(new SystemDocumentPublishEvent {
Ids = new List<Guid> { document.Id },
NewUserTypeIds = newUserTypeIds
});
}
});
}
}
return ResponseOutput.Ok(document.Id.ToString());
}
@@ -104,6 +198,51 @@ namespace IRaCIS.Core.Application.Services
}
/// <summary>
/// 发布系统文档
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> PublishSystemDocument(PublishSystemDocumentInDto inDto)
{
await _systemDocumentRepository.BatchUpdateNoTrackingAsync(x => inDto.Ids.Contains(x.Id), x => new SystemDocument()
{
IsPublish = true,
IsDeleted = false,
});
Console.WriteLine("开始 发布系统文档");
Task.Run(async () =>
{
// 创建独立作用域
using (var scope = serviceScopeFactory.CreateScope())
{
// 从新作用域解析服务
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
await mediator.Publish(new SystemDocumentPublishEvent { Ids = inDto.Ids });
}
});
return ResponseOutput.Result(true);
}
/// <summary>
/// 下线系统文档
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> OutLineSystemDocument(PublishSystemDocumentInDto inDto)
{
await _systemDocumentRepository.UpdatePartialFromQueryAsync(x => inDto.Ids.Contains(x.Id), x => new SystemDocument()
{
IsDeleted = true,
});
var result = await _systemDocumentRepository.SaveChangesAsync();
return ResponseOutput.Result(result);
}
[HttpDelete("{systemDocumentId:guid}")]
public async Task<IResponseOutput> AbandonSystemDocumentAsync(Guid systemDocumentId)
{
@@ -160,9 +299,12 @@ namespace IRaCIS.Core.Application.Services
select new UnionDocumentWithConfirmInfoView()
{
AttachmentCount=sysDoc.SystemDocumentAttachmentList.Where(z=>!z.OffLine).Count(),
IsSystemDoc = true,
CurrentStaffTrainDays=sysDoc.CurrentStaffTrainDays,
NewStaffTrainDays = sysDoc.NewStaffTrainDays,
Id = sysDoc.Id,
UserCreateTime= user.CreateTime,
CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted,
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
@@ -178,18 +320,18 @@ namespace IRaCIS.Core.Application.Services
RealName = user.FullName,
UserName = user.UserName,
DocTypeCode=sysDoc.FileType.Code
DocTypeCode = sysDoc.FileType.Code
//UserTypeId = user.UserTypeId,
//UserTypeShortName = user.UserTypeRole.UserTypeShortName
};
var list = await query
//过滤掉删除的,并且没有签名的
var list = await query
//过滤掉删除的,并且没有签名的
.Where(t => !(t.IsDeleted == true && t.ConfirmTime == null))
.WhereIf(inQuery.IsSigned == true, t => t.ConfirmTime != null)
.WhereIf(inQuery.IsSigned == false, t => t.ConfirmTime == null)
.ToPagedListAsync(inQuery,nameof(UnionDocumentWithConfirmInfoView.DocTypeCode));
.ToPagedListAsync(inQuery, nameof(UnionDocumentWithConfirmInfoView.DocTypeCode));
return list;
@@ -8,6 +8,7 @@ using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NPOI.SS.Formula.Functions;
@@ -29,6 +30,7 @@ namespace IRaCIS.Core.Application.Services
IRepository<SystemDocument> _systemDocumentRepository,
IRepository<TrialIdentityUser> _trialIdentityUserRepository,
IRepository<TrialUserRole> _trialUserRoleRepository,
IRepository<IdentityUser> _identityUserRepository,
IRepository<TrialDocConfirmedIdentityUser> _trialDocConfirmedUserRepository,
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ITrialDocumentService
{
@@ -241,7 +243,6 @@ namespace IRaCIS.Core.Application.Services
select new UnionDocumentWithConfirmInfoView()
{
IsSystemDoc = true,
Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted,
@@ -409,6 +410,21 @@ namespace IRaCIS.Core.Application.Services
var result = await unionQuery.ToPagedListAsync(inQuery);
//Concat 不能用导航属性
var sysids = result.CurrentPageData.Where(t => t.IsSystemDoc == true).Select(t => t.Id).ToList();
var sysDataList = await _systemDocumentRepository.Where(x => sysids.Contains(x.Id)).Include(x => x.SystemDocumentAttachmentList).ToListAsync();
result.CurrentPageData.ForEach(x =>
{
if (sysDataList.Any(y => y.Id == x.Id))
{
x.AttachmentCount = sysDataList.Where(y => y.Id == x.Id).Select(x => x.SystemDocumentAttachmentList.Where(z => !z.OffLine).Count()).FirstOrDefault();
}
});
#endregion
#region
@@ -473,12 +489,12 @@ namespace IRaCIS.Core.Application.Services
var trialDocQuery =
from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(t => t.TrialId == inQuery.TrialId)
.Where(t => inQuery.UserTypeId != null ? t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId) : true)
from trialUser in _trialIdentityUserRepository.AsQueryable(false).Where(t => t.TrialId == inQuery.TrialId
&& t.TrialUserRoleList.AsQueryable().Any(t => trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == t.UserRole.UserTypeId))
)
.Where(t => inQuery.UserId != null ? t.IdentityUserId == inQuery.UserId : true)
.Where(t => inQuery.UserTypeId != null ? t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == inQuery.UserTypeId) : true)
from trialUser in _trialIdentityUserRepository.AsQueryable(false).Where(t => t.TrialId == inQuery.TrialId
&& t.TrialUserRoleList.AsQueryable().Any(t => trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == t.UserRole.UserTypeId))
)
.Where(t => inQuery.UserId != null ? t.IdentityUserId == inQuery.UserId : true)
.Where(t => inQuery.UserTypeId != null ? t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == inQuery.UserTypeId) : true)
join confirm in _trialDocConfirmedUserRepository.Where(t => t.TrialDocument.TrialId == inQuery.TrialId) on
new { trialUser.IdentityUserId, TrialDocumentId = trialDoc.Id } equals new { IdentityUserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc
@@ -557,13 +573,27 @@ namespace IRaCIS.Core.Application.Services
.WhereIf(inQuery.FileTypeId != null, t => t.FileTypeId == inQuery.FileTypeId)
.WhereIf(inQuery.IsConfirmed == true, t => t.ConfirmTime != null)
.WhereIf(inQuery.IsConfirmed == false, t => t.ConfirmTime == null)
.WhereIf(inQuery.StartConfirmTime != null, t => t.ConfirmTime >= inQuery.StartConfirmTime.Value)
.WhereIf(inQuery.EndConfirmTime != null, t => t.ConfirmTime <= inQuery.EndConfirmTime.Value)
.WhereIf(inQuery.StartConfirmTime != null, t => t.ConfirmTime >= inQuery.StartConfirmTime.Value)
.WhereIf(inQuery.EndConfirmTime != null, t => t.ConfirmTime <= inQuery.EndConfirmTime.Value)
.WhereIf(inQuery.BeginCreateTime != null, t => t.CreateTime >= inQuery.BeginCreateTime)
.WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime)
.WhereIf(!string.IsNullOrEmpty(inQuery.UserName), t => t.UserName.Contains(inQuery.UserName))
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted);
var result = await unionQuery.ToPagedListAsync(inQuery);
//Concat 不能用导航属性
var sysids = result.CurrentPageData.Where(t => t.IsSystemDoc == true).Select(t => t.Id).ToList();
var sysDataList = await _systemDocumentRepository.Where(x => sysids.Contains(x.Id)).Include(x => x.SystemDocumentAttachmentList).ToListAsync();
result.CurrentPageData.ForEach(x =>
{
if (sysDataList.Any(y => y.Id == x.Id))
{
x.AttachmentCount = sysDataList.Where(y => y.Id == x.Id).Select(x => x.SystemDocumentAttachmentList.Where(z => !z.OffLine).Count()).FirstOrDefault();
}
});
#region
var trialDocIdList = result.CurrentPageData.Where(t => t.IsSystemDoc == false).Select(t => t.Id).ToList();
@@ -749,6 +779,112 @@ namespace IRaCIS.Core.Application.Services
}
/// <summary>
/// 获取系统签署文档签署人下拉框
/// </summary>
/// <returns></returns>
public async Task<IResponseOutput> GetSysDocSignUserList()
{
var list = _systemDocConfirmedUserRepository.Where(t => t.ConfirmTime != null).Select(t => new { t.ConfirmUserId, t.ConfirmUser.UserName, t.ConfirmUser.FullName }).Distinct().ToList();
return ResponseOutput.Ok(list);
}
[HttpPost]
public async Task<IResponseOutput<PageOutput<UnionDocumentWithConfirmInfoView>>> GetSysDocumentConfirmList(SystemDocQuery inQuery)
{
var isInternal = _userInfo.IsZhiZhun;
var systemDocQuery =
from sysDoc in _systemDocumentRepository.AsQueryable(false)
.Where(t => inQuery.UserTypeId != null ? t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId) : true)
from identityUser in _identityUserRepository.AsQueryable(false).Where(t =>t.Status== UserStateEnum.Enable && t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
.Where(t => inQuery.UserId != null ? t.Id == inQuery.UserId : true)
.Where(t => inQuery.UserTypeId != null ? t.UserRoleList.Any(t => t.UserTypeId == inQuery.UserTypeId && t.IsUserRoleDisabled == false) : true)
join confirm in _systemDocConfirmedUserRepository.Where() on new { ConfirmUserId = identityUser.Id, SystemDocumentId = sysDoc.Id } equals new { confirm.ConfirmUserId, confirm.SystemDocumentId } into cc
from confirm in cc.DefaultIfEmpty()
select new UnionDocumentWithConfirmInfoView()
{
IsSystemDoc = true,
Id = sysDoc.Id,
CreateTime = sysDoc.CreateTime,
IsDeleted = sysDoc.IsDeleted,
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
Name = sysDoc.Name,
Path = sysDoc.Path,
FileType = _userInfo.IsEn_Us ? sysDoc.FileType.Value : sysDoc.FileType.ValueCN,
FileTypeId = sysDoc.FileTypeId,
UpdateTime = sysDoc.UpdateTime,
//IsConfirmed = confirm.ConfirmTime != null,
ConfirmUserId = identityUser.Id,
ConfirmTime = confirm.ConfirmTime,
RealName = identityUser.FullName,
UserName = identityUser.UserName,
//UserTypeId = trialUser.UserRole.UserTypeId,
//UserTypeShortName = trialUser.UserRole.UserTypeRole.UserTypeShortName,
FullFilePath = sysDoc.Path
};
var unionQuery = systemDocQuery.IgnoreQueryFilters().Where(t => !(t.IsDeleted == true && t.ConfirmTime == null))
.WhereIf(!string.IsNullOrEmpty(inQuery.Name), t => t.Name.Contains(inQuery.Name))
.WhereIf(inQuery.FileTypeId != null, t => t.FileTypeId == inQuery.FileTypeId)
.WhereIf(inQuery.IsConfirmed == true, t => t.ConfirmTime != null)
.WhereIf(inQuery.IsConfirmed == false, t => t.ConfirmTime == null)
.WhereIf(inQuery.StartConfirmTime != null, t => t.ConfirmTime >= inQuery.StartConfirmTime.Value)
.WhereIf(inQuery.EndConfirmTime != null, t => t.ConfirmTime <= inQuery.EndConfirmTime.Value)
.WhereIf(inQuery.BeginCreateTime != null, t => t.CreateTime >= inQuery.BeginCreateTime)
.WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime)
.WhereIf(!string.IsNullOrEmpty(inQuery.UserName), t => t.UserName.Contains(inQuery.UserName))
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
.WhereIf(isInternal == false, t => t.ConfirmTime != null);
var result = await unionQuery.ToPagedListAsync(inQuery);
#region
var trialDocIdList = result.CurrentPageData.Where(t => t.IsSystemDoc == false).Select(t => t.Id).ToList();
var sysDocIdList = result.CurrentPageData.Where(t => t.IsSystemDoc == true).Select(t => t.Id).ToList();
var identityUserIdList = result.CurrentPageData.Select(t => t.ConfirmUserId).Distinct().ToList();
var sysDocUserTypeList = _systemDocNeedConfirmedUserTypeRepository.Where(t => sysDocIdList.Contains(t.SystemDocumentId)).Select(t => new { t.SystemDocumentId, t.UserTypeRole.UserTypeShortName }).ToList();
var identityUserUserTypeList = _identityUserRepository.Where(t => identityUserIdList.Contains(t.Id)).IgnoreQueryFilters().Select(t => new { IdentityUserId = t.Id, UserTypeList = t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Select(c => c.UserTypeRole.UserTypeShortName).ToList() });
//Concat 不能用导航属性
var sysids = result.CurrentPageData.Where(t => t.IsSystemDoc == true).Select(t => t.Id).ToList();
var sysDataList = await _systemDocumentRepository.Where(x => sysids.Contains(x.Id)).Include(x => x.SystemDocumentAttachmentList).ToListAsync();
foreach (var item in result.CurrentPageData)
{
if (sysDataList.Any(y => y.Id == item.Id))
{
item.AttachmentCount = sysDataList.Where(y => y.Id == item.Id).Select(x => x.SystemDocumentAttachmentList.Where(z => !z.OffLine).Count()).FirstOrDefault();
}
if (item.IsSystemDoc)
{
item.DocNeedSignUserTypeList = sysDocUserTypeList.Where(t => t.SystemDocumentId == item.Id).Select(t => t.UserTypeShortName).ToList();
}
item.IdentityUserTypeList = identityUserUserTypeList.Where(t => t.IdentityUserId == item.ConfirmUserId).SelectMany(c => c.UserTypeList).ToList();
}
#endregion
return ResponseOutput.Ok(result);
}
/// <summary>
/// 项目下面的参与用户下拉
@@ -13,6 +13,7 @@ using System.Threading.Tasks;
using IRaCIS.Core.Infra.EFCore;
using MassTransit;
using IRaCIS.Core.Infrastructure;
using Microsoft.Extensions.Options;
namespace IRaCIS.Core.Application.Service;
/// <summary>
@@ -24,7 +25,7 @@ namespace IRaCIS.Core.Application.Service;
/// <param name="_localizer"></param>
[ApiExplorerSettings(GroupName = "FileRecord")]
public class TrialFileTypeService(IRepository<TrialFileType> _trialFileTypeRepository,
IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
IRepository<TrialFile> _trialFileRepository,
IRepository<SysFileType> _sysFileTypeRepository,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ITrialFileTypeService
@@ -116,6 +117,7 @@ public class TrialFileTypeService(IRepository<TrialFileType> _trialFileTypeRepos
if (!(await _trialFileTypeRepository.AnyAsync(x => x.TrialId == inDto.TrialId)))
{
var trialFileTypeList = await _sysFileTypeRepository
.Where(x=>x.SysTemplateTypeEnum== _verifyConfig.CurrentValue.TemplateType|| x.SysTemplateTypeEnum==SysTemplateType.Both)
.ProjectTo<TrialFileType>(_mapper.ConfigurationProvider)
.ToListAsync();
@@ -15,7 +15,21 @@ namespace IRaCIS.Core.Application.Service
var userId = Guid.Empty;
var isEn_Us = false;
// 在此处拷贝automapper 映射
CreateMap<SystemDocumentAttachment, SystemDocumentAttachmentView>();
CreateMap<SystemDocumentAttachment, SystemDocumentAttachmentAddOrEdit>().ReverseMap();
CreateMap<AuditDocumentData, AuditDocumentAddOrEdit>();
//CreateMap<List<AuditDocumentData>, List<AuditDocumentAddOrEdit>>();
CreateMap<AuditDocument, AuditDocumentView>();
CreateMap<AuditDocument, AuditDocumentUpdateDto>();
CreateMap<AuditDocument, HistoricalVersionDto>();
CreateMap<AuditDocumentUpdateDto, AuditDocumentAddOrEdit>();
CreateMap<AuditDocument, AuditDocumentData>();
CreateMap<AuditDocument, AuditDocumentAddOrEdit>().ReverseMap();
CreateMap<SystemDocument, SystemDocumentView>()
.ForMember(d => d.AttachmentCount, u => u.MapFrom(s => s.SystemDocumentAttachmentList.Count()))
.ForMember(d => d.FileType, u => u.MapFrom(s => isEn_Us ? s.FileType.Value : s.FileType.ValueCN))
.ForMember(d => d.FullFilePath, u => u.MapFrom(s => s.Path));
@@ -81,7 +81,7 @@ namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
public bool IsReading { get; set; }
public bool IsDeleted { get; set; }
public long? FileSize { get; set; }
public Guid? StudyId { get; set; }
@@ -107,8 +107,13 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc.DTO
public string Modalities { get; set; }
public string Description { get; set; }
public int SeriesCount { get; set; }
public int InstanceCount { get; set; }
public int ReadingSeriesCount { get; set; }
public int ReadingInstanceCount { get; set; }
}
public class NoneDicomStudyBasicInfo
@@ -128,6 +133,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc.DTO
public string Description { get; set; } = string.Empty;
public int ReadingFileCount { get; set; }
}
}
@@ -13,6 +13,7 @@ using MassTransit.Initializers;
using Medallion.Threading;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using System.Data;
using System.IO.Compression;
using System.Text;
@@ -62,7 +63,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
//subject 随机阅片 或者无序 有上传 才处理任务编号
if (_visitTaskRepository.Any(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId &&
(t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.SubjectRandom ||
(t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.Random && t.TrialReadingCriterion.ImageUploadEnum != ReadingImageUpload.None))))
(t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.Random && t.TrialReadingCriterion.ImageDownloadEnum != ReadingImageDownload.None))))
{
//找到 非一致性分析,未签名,状态正常的 并且任务名称是TimePoint的 任务
var needDealTaskList = await _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId == _userInfo.UserRoleId
@@ -881,6 +882,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
subjectCode = inQuery.SubjectCode;
}
TaskState? taskState = null;
if (inQuery.VisitTaskId != null)
{
//考虑到一致性分析,必须要这个编号进行过滤
@@ -891,19 +893,25 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
SubjectCode = t.IsAnalysisCreate ? t.BlindSubjectCode : t.Subject.Code,
SubjectId = t.SubjectId,
t.DoctorUserId,
t.IsAnalysisCreate
t.IsAnalysisCreate,
t.TaskState
}).FirstNotNullAsync();
subjectId = taskInfo.SubjectId;
subjectCode = taskInfo.SubjectCode;
doctorUserId = (Guid)taskInfo.DoctorUserId!;
isAnalysisCreate = taskInfo.IsAnalysisCreate;
taskState = taskInfo.TaskState;
}
var query = _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId
&& t.SourceSubjectVisitId != null && t.DoctorUserId == doctorUserId && t.TaskState == TaskState.Effect)
&& t.SourceSubjectVisitId != null && t.DoctorUserId == doctorUserId)
//满足 有序,或者随机只看到当前任务的dicom 非dicom检查
.WhereIf(inQuery.VisitTaskId == null, t => t.TaskState == TaskState.Effect)//从待阅列表进入,要筛选出有效的,任务可能重阅了,也要看到该任务的
.WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
.WhereIf(taskState == TaskState.Effect || taskState == TaskState.Freeze, t => t.TaskState == TaskState.Effect)//subject 随机可能当前阅片人有退回任务,此时传递了任务Id,但是要看整个subject得,要只留生效的
.WhereIf(taskState != null && taskState != TaskState.Effect && taskState != TaskState.Freeze, t => t.Id == inQuery.VisitTaskId) //非生效只查当前任务
.ProjectTo<SubjectCRCImageUploadedDto>(_mapper.ConfigurationProvider);
//这里过滤是否是一致性分析的
@@ -1004,11 +1012,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
u.StudyTime,
u.StudyCode,
SeriesList = u.SeriesList.Select(z => new
SeriesList = u.SeriesList.Where(t => t.IsReading).Select(z => new
{
z.Modality,
InstancePathList = z.DicomInstanceList.Select(k => new
InstancePathList = z.DicomInstanceList.Where(t => t.IsReading).Select(k => new
{
k.Path,
k.FileSize
@@ -1019,13 +1027,14 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => isQueryNoneDicom ? inQuery.NoneDicomStudyIdList.Contains(t.Id) : false)
.Where(t => info.IsImageFilter ? ("|" + info.CriterionModalitys + "|").Contains("|" + t.Modality + "|") : true)
.Where(t => t.IsReading)
.Select(nd => new
{
nd.Modality,
nd.StudyCode,
nd.ImageDate,
FileList = nd.NoneDicomFileList.Select(file => new
FileList = nd.NoneDicomFileList.Where(t => t.IsReading).Select(file => new
{
file.FileName,
file.Path,
@@ -1107,7 +1116,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
HtmlPath = k.HtmlPath,
Path = k.Path,
InstanceNumber = k.InstanceNumber,
FileSize=k.FileSize,
}).ToList()
})
});
@@ -4,7 +4,7 @@ namespace IRaCIS.Core.Application.Contracts
{
public interface IStudyService
{
IResponseOutput<List<RelationStudyDTO>> GetAllRelationStudyList(Guid subjectVisitId);
IResponseOutput<List<RelationStudyDTO>> GetAllRelationStudyList(Guid subjectVisitId,bool? isReading);
Task<PageOutput<UnionStudyViewModel>> GetDicomAndNoneDicomStudyList(StudyQuery studyQuery);
Task<PageOutput<UnionStudyMonitorModel>> GetDicomAndNoneDicomStudyMonitorList(StudyQuery studyQuery);
(List<string> SeriesInstanceUid, List<string> SopInstanceUid) GetHasUploadSeriesAndInstance(Guid studyId);
@@ -137,9 +137,9 @@ namespace IRaCIS.Core.Application.Contracts
await _qCCommon.VerifyIsCRCSubmmitAsync(_subjectVisitRepository, _userInfo, subjectVisitId);
await _noneDicomStudyRepository.DeleteFromQueryAsync(noneDicomStudyId);
await _noneDicomStudyRepository.DeleteFromQueryAsync(noneDicomStudyId,ignoreQueryFilter:true);
await _noneDicomStudyFileRepository.DeleteFromQueryAsync(t => t.NoneDicomStudyId == noneDicomStudyId);
await _noneDicomStudyFileRepository.DeleteFromQueryAsync(t => t.NoneDicomStudyId == noneDicomStudyId, ignoreQueryFilter: true);
//确认需求 不删除
//await _studyMonitorRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == noneDicomStudyId);
@@ -157,13 +157,13 @@ namespace IRaCIS.Core.Application.Contracts
//提交了 但是IQC同意的时候 是可以删除的 | 普通提交后也不能删除
await _qCCommon.VerifyIsCRCSubmmitAsync(_subjectVisitRepository, _userInfo, subjectVisitId);
var noneDicomStudyFile = await _noneDicomStudyFileRepository.FirstOrDefaultAsync(t => t.Id == noneDicomStudyFileId);
var noneDicomStudyFile = await _noneDicomStudyFileRepository.FirstOrDefaultAsync(t => t.Id == noneDicomStudyFileId, true);
var success = await _noneDicomStudyFileRepository.DeleteAsync(noneDicomStudyFile, true);
var success = await _noneDicomStudyFileRepository.DeleteAsync(noneDicomStudyFile,true);
//维护文件数量数字
var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync(t => t.Id == noneDicomStudyFile.NoneDicomStudyId);
noneDicomStudy.FileCount = await _noneDicomStudyFileRepository.CountAsync(t => t.NoneDicomStudyId == noneDicomStudyFile.NoneDicomStudyId);
var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync(t => t.Id == noneDicomStudyFile.NoneDicomStudyId,true);
noneDicomStudy.FileCount = await _noneDicomStudyFileRepository.CountAsync(t => t.NoneDicomStudyId == noneDicomStudyFile.NoneDicomStudyId,true);
await _noneDicomStudyRepository.SaveChangesAsync();
return ResponseOutput.Ok();
@@ -1,5 +1,6 @@
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
@@ -19,8 +20,9 @@ namespace IRaCIS.Core.Application.Services
//医生读片那一块有耦合,关键序列 这里暂时留存
/// <summary> 指定资源Id,获取Dicom检查所属序列信息列表 </summary>
/// <param name="studyId"> Dicom检查的Id </param>
/// <param name="isReading"></param>
[HttpGet, Route("{studyId:guid}")]
public async Task<IResponseOutput<List<DicomSeriesDTO>>> List(Guid studyId)
public async Task<IResponseOutput<List<DicomSeriesDTO>>> List(Guid studyId, bool? isReading)
{
//质控的时候,要标记序列,和instance 删除 ,所以要返回全部,但是 质控通过后,pm 进去看的时候要看过滤后的
@@ -32,14 +34,16 @@ namespace IRaCIS.Core.Application.Services
//断点
var seriesList = await _seriesRepository.Where(s => s.StudyId == studyId).IgnoreQueryFilters()
.WhereIf(isQCFinished, t => t.IsDeleted == false)
.WhereIf(isReading == true, t => t.IsReading == true)
.OrderBy(s => s.SeriesNumber).ThenBy(s => s.SeriesTime).ThenBy(s => s.CreateTime)
.ProjectTo<DicomSeriesDTO>(_mapper.ConfigurationProvider).ToListAsync();
var instanceList = await _instanceRepository.Where(s => s.StudyId == studyId).IgnoreQueryFilters()
.WhereIf(isQCFinished, t => t.IsDeleted == false)
.WhereIf(isReading == true, t => t.IsReading == true)
.OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber)
.ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime)
.Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber, t.HtmlPath, t.IsReading, t.IsDeleted }).ToListAsync();//.GroupBy(u => u.SeriesId);
.Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber, t.HtmlPath, t.IsReading, t.IsDeleted, t.FileSize }).ToListAsync();//.GroupBy(u => u.SeriesId);
foreach (var series in seriesList)
@@ -54,7 +58,8 @@ namespace IRaCIS.Core.Application.Services
Path = k.Path,
InstanceNumber = k.InstanceNumber,
IsReading = k.IsReading,
IsDeleted = k.IsDeleted
IsDeleted = k.IsDeleted,
FileSize = k.FileSize
}).ToList();
@@ -579,7 +579,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
/// <returns></returns>
[HttpGet("{subjectVisitId:guid}")]
[AllowAnonymous]
public IResponseOutput<List<RelationStudyDTO>> GetAllRelationStudyList(Guid subjectVisitId)
public IResponseOutput<List<RelationStudyDTO>> GetAllRelationStudyList(Guid subjectVisitId,bool? isReading)
{
#region
//var studylist = _studyRepository.Where(u => u.SubjectVisitId == subjectVisitId && u.IsDeleted == false).Select(t => new { StudyId = t.Id, t.SubjectId, t.TrialId }).ToList();
@@ -607,10 +607,18 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var studyInfo = _dicomStudyRepository.Where(u => u.SubjectVisitId == subjectVisitId).Select(t => new { t.SubjectId, t.TrialId }).FirstOrDefault().IfNullThrowException();
var query = _dicomStudyRepository.Where(t => t.SubjectVisitId != subjectVisitId && t.TrialId == studyInfo.TrialId && t.SubjectId == studyInfo.SubjectId)
.ProjectTo<RelationStudyDTO>(_mapper.ConfigurationProvider).ToList();
var list = _dicomStudyRepository.Where(t => t.SubjectVisitId != subjectVisitId && t.TrialId == studyInfo.TrialId && t.SubjectId == studyInfo.SubjectId)
.Select(t=> new RelationStudyDTO()
{
StudyId = t.Id,
StudyCode = t.StudyCode,
VisitName = t.SubjectVisit.VisitName,
Modalities = t.Modalities,
Description = t.Description,
SeriesCount = t.SeriesList.Where(t=> isReading==true? t.IsReading==true:true).Count()
}) .ToList();
var list = query.OrderBy(u => u.VisitName).ThenBy(s => s.StudyCode).ToList();
list = list.Where(t=>t.SeriesCount>0).OrderBy(u => u.VisitName).ThenBy(s => s.StudyCode).ToList();
return ResponseOutput.Ok(list);
}
@@ -845,7 +853,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var verifyStudyInfo = _dicomStudyRepository.Where(t => t.TrialId == trialId && t.Id == expectStudyId).ProjectTo<VerifyStudyDto>(_mapper.ConfigurationProvider).FirstOrDefault();
var verifyStudyInfo = _dicomStudyRepository.Where(t => t.TrialId == trialId && t.Id == expectStudyId,false,true).ProjectTo<VerifyStudyDto>(_mapper.ConfigurationProvider).FirstOrDefault();
result.StudyInfo = verifyStudyInfo;
@@ -130,16 +130,20 @@ namespace IRaCIS.Core.Application.Service
.ForMember(d => d.CriterionModalitys, u => u.MapFrom(s => s.TrialReadingCriterion.CriterionModalitys))
.ForMember(d => d.SubjectCode, u => u.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code));
CreateMap<DicomStudy, DicomStudyBasicInfo>();
CreateMap<NoneDicomStudy, NoneDicomStudyBasicInfo>();
CreateMap<DicomStudy, DicomStudyBasicInfo>()
.ForMember(d => d.ReadingSeriesCount, u => u.MapFrom(s => s.SeriesList.Where(t => t.IsReading).Count()))
.ForMember(d => d.ReadingInstanceCount, u => u.MapFrom(s => s.InstanceList.Where(t => t.IsReading && t.DicomSerie.IsReading).Count()));
CreateMap<NoneDicomStudy, NoneDicomStudyBasicInfo>()
.ForMember(d => d.ReadingFileCount, u => u.MapFrom(s => s.NoneDicomFileList.Where(t => t.IsReading).Count()));
CreateMap<VisitTask, SubjectCRCImageUploadedDto>()
.ForMember(d => d.VisitTaskId, u => u.MapFrom(s => s.Id))
.ForMember(d => d.IsImageFilter, u => u.MapFrom(s => s.TrialReadingCriterion.IsImageFilter))
.ForMember(d => d.CriterionModalitys, u => u.MapFrom(s => s.TrialReadingCriterion.CriterionModalitys))
.ForMember(d => d.SubjectCode, u => u.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code))
.ForMember(d => d.DicomStudyList, u => u.MapFrom(s => s.SourceSubjectVisit.StudyList))
.ForMember(d => d.NoneDicomStudyList, u => u.MapFrom(s => s.SourceSubjectVisit.NoneDicomStudyList))
;
.ForMember(d => d.NoneDicomStudyList, u => u.MapFrom(s => s.SourceSubjectVisit.NoneDicomStudyList.Where(t => t.IsReading)));
CreateMap<TrialImageDownload, TrialImageDownloadView>()
.ForMember(d => d.UserFullName, u => u.MapFrom(s => s.CreateUserRole.FullName))
@@ -199,6 +199,8 @@ namespace IRaCIS.Core.Application.Service.Inspection.DTO
public Guid subjectVisitId { get; set; }
public AuditStateEnum auditState { get; set; }
public bool? IsSecondPass { get; set; }
}
public class SetSeriesStateDto
@@ -27,6 +27,7 @@ namespace IRaCIS.Core.Application.ViewModel
public bool IsLoginUncommonly { get; set; }
public bool IsIgnoreUncommonly { get; set; }
public string JsonObj { get; set; }
@@ -43,17 +44,26 @@ namespace IRaCIS.Core.Application.ViewModel
public UserMFAType MFAType { get; set; } = UserMFAType.Login;
}
public class SetIsIgnoreUncommonlyInDto
{
public Guid Id { get; set; }
public bool IsIgnoreUncommonly { get; set; }
}
///<summary>UserLogQuery 列表查询参数模型</summary>
public class UserLogQuery : PageInput
{
public Guid? TrialId { get; set; }
public UserOptType? OptType { get; set; }
public List<UserOptType>? OptTypeList { get; set; }
public string? IP { get; set; }
public string? LoginFaildName { get; set; }
public string? LoginUserName { get; set; }
public DateTime? BeginDate { get; set; }
@@ -510,11 +510,11 @@ namespace IRaCIS.Core.Application.Service
.WhereIf(inQuery.EndLastLoginTime != null, t => t.LastLoginTime <= inQuery.EndLastLoginTime)
.WhereIf(inQuery.BeginLastChangePassWordTime != null, t => t.LastChangePassWordTime >= inQuery.BeginLastChangePassWordTime)
.WhereIf(inQuery.EndLastChangePassWordTime != null, t => t.LastChangePassWordTime <= inQuery.EndLastChangePassWordTime)
.WhereIf(inQuery.UserType != null, t => t.UserRoleList.Any(t => t.UserTypeId == inQuery.UserType))
.WhereIf(inQuery.UserType != null, t => t.UserRoleList.Any(t => t.UserTypeId == inQuery.UserType && t.IsUserRoleDisabled==false))
.WhereIf(inQuery.UserState != null, t => t.Status == inQuery.UserState)
.WhereIf(inQuery.IsTestUser != null, t => t.IsTestUser == inQuery.IsTestUser)
.WhereIf(inQuery.IsZhiZhun != null, t => t.IsZhiZhun == inQuery.IsZhiZhun)
.WhereIf(inQuery.UserCeateSource != null, t => t.UserCeateSource == inQuery.UserCeateSource)
.WhereIf(inQuery.UserCeateSource != null, t => t.UserCeateSource == inQuery.UserCeateSource)
.ProjectTo<UserListDTO>(_mapper.ConfigurationProvider);
return await userQueryable.ToPagedListAsync(inQuery);
@@ -835,7 +835,17 @@ namespace IRaCIS.Core.Application.Service
return ResponseOutput.Ok();
}
/// <summary>
/// 设置是否忽略异地登录
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> SetIsIgnoreUncommonly(SetIsIgnoreUncommonlyInDto inDto)
{
await _userLogRepository.UpdatePartialFromQueryAsync(inDto.Id, x => new UserLog() { IsIgnoreUncommonly = inDto.IsIgnoreUncommonly }, true);
return ResponseOutput.Ok();
}
[HttpPost]
public async Task<PageOutput<UserLogView>> GetUserLogList(UserLogQuery inQuery)
@@ -850,10 +860,11 @@ namespace IRaCIS.Core.Application.Service
.WhereIf(inQuery.TargetIdentityUserId != null, t => t.TargetIdentityUserId == inQuery.TargetIdentityUserId)
.WhereIf(inQuery.TrialId != null, t => t.ActionIdentityUser.UserTrialList.Any(c => c.TrialId == inQuery.TrialId) || t.TargetIdentityUser.UserTrialList.Any(c => c.TrialId == inQuery.TrialId))
.WhereIf(trialCreateTime != null, t => t.CreateTime >= trialCreateTime)
.WhereIf(inQuery.OptType != null, t => t.OptType == inQuery.OptType)
.WhereIf(inQuery.OptTypeList != null && inQuery.OptTypeList.Count > 0, t => inQuery.OptTypeList.Contains(t.OptType))
.WhereIf(inQuery.BeginDate != null, t => t.CreateTime >= inQuery.BeginDate)
.WhereIf(inQuery.EndDate != null, t => t.CreateTime <= inQuery.EndDate)
.WhereIf(inQuery.IsLoginUncommonly != null, t => t.IsLoginUncommonly == inQuery.IsLoginUncommonly)
.WhereIf(inQuery.IsLoginUncommonly != null , t => t.IsLoginUncommonly== inQuery.IsLoginUncommonly)
.WhereIf(!string.IsNullOrEmpty(inQuery.LoginUserName), t => t.ActionUserName.Contains(inQuery.LoginUserName!))
.WhereIf(!string.IsNullOrEmpty(inQuery.LoginFaildName), t => t.ActionUserName.Contains(inQuery.LoginFaildName!))
.WhereIf(!string.IsNullOrEmpty(inQuery.IP), t => t.IP.Contains(inQuery.IP!))
@@ -911,7 +922,7 @@ namespace IRaCIS.Core.Application.Service
var password = loginDto.Password;
var emailConfig = _emailConfig.CurrentValue;
var companyInfo = new SystemEmailSendConfigView() { CompanyName = emailConfig.CompanyName, CompanyNameCN = emailConfig.CompanyNameCN, CompanyShortName = emailConfig.CompanyShortName, CompanyShortNameCN = emailConfig.CompanyShortNameCN };
var companyInfo = new SystemEmailSendConfigView() { CompanyName = emailConfig.CompanyName, CompanyNameCN = emailConfig.CompanyNameCN, CompanyShortName = emailConfig.CompanyShortName, CompanyShortNameCN = emailConfig.CompanyShortNameCN,SystemShortName=emailConfig.SystemShortName };
int maxFailures = _verifyConfig.CurrentValue.LoginMaxFailCount;
@@ -958,42 +969,49 @@ namespace IRaCIS.Core.Application.Service
//账号在系统存在
if (isExistAccount || loginUser != null)
{
var ipinfo = _searcher.Search(_userInfo.IP);
//var ipinfo = _searcher.Search(_userInfo.IP);
var iPRegion = string.Join('|', ipinfo.Split('|').TakeLast(3));
//var iPRegion = string.Join('|', ipinfo.Split('|').TakeLast(3));
string SplitAndConcatenate(string input)
//string SplitAndConcatenate(string input)
//{
// string[] parts = input.Split('|');
// return parts.Length >= 3 ? parts[0] + parts[1] : string.Join("", parts);
//}
var iPRegion = IPCityHelper.GetCityResponse(_userInfo.IP);
//设置本次登录的IP
await _identityUserRepository.BatchUpdateNoTrackingAsync(x => x.Id == existUserLoginInfo.Id, x => new IdentityUser()
{
string[] parts = input.Split('|');
return parts.Length >= 3 ? parts[0] + parts[1] : string.Join("", parts);
LastLoginIP = iPRegion,
LastLoginTime = DateTime.Now
});
//超过90天没修改密码
if (loginUser!= null&&_verifyConfig.CurrentValue.IsNeedChangePassWord && loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-_verifyConfig.CurrentValue.ChangePassWordDays) > loginUser.LastChangePassWordTime.Value)
{
loginUser.NeedChangePassWord = true;
}
if (existUserLoginInfo.LastLoginIP != string.Empty)
{
// 与上一次区域不一致
if (SplitAndConcatenate(existUserLoginInfo.LastLoginIP) != SplitAndConcatenate(iPRegion))
//if (SplitAndConcatenate(existUserLoginInfo.LastLoginIP) != SplitAndConcatenate(iPRegion))
if (existUserLoginInfo.LastLoginIP != iPRegion)
{
isLoginUncommonly = true;
//设置上次登录的IP
await _identityUserRepository.BatchUpdateNoTrackingAsync(x => x.Id == existUserLoginInfo.Id, x => new IdentityUser()
{
LastLoginIP = iPRegion,
LastLoginTime = DateTime.Now
});
if (loginUser != null)
{
//异地登录
loginUser.LoginState = 2;
//超过90天没修改密码
if (_verifyConfig.CurrentValue.IsNeedChangePassWord && loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-_verifyConfig.CurrentValue.ChangePassWordDays) > loginUser.LastChangePassWordTime.Value)
{
loginUser.NeedChangePassWord = true;
}
}
}
}
@@ -1017,14 +1035,7 @@ namespace IRaCIS.Core.Application.Service
}
await _identityUserRepository.BatchUpdateNoTrackingAsync(x => x.Id == loginUser.IdentityUserId, x => new IdentityUser()
{
LastLoginTime = DateTime.Now,
LastLoginIP = _userInfo.IP,
});
//登录成功的,才会算异地登录
if (loginUser.Status == 0)
{
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, ActionUserName = loginUser.UserName, OptType = UserOptType.LoginLockedAccount, IsLoginUncommonly = isLoginUncommonly }, true);
@@ -251,7 +251,13 @@ namespace IRaCIS.Core.Application.Contracts.DTO
}
public class SecondReviewDto
{
public DateTime? SecondReviewTime { get; set; }
public string FullName { get; set; }
public string UserName { get; set; }
public DateTime? SignTime { get; set; }
}
public class TrialVisitQADTO
@@ -270,6 +276,7 @@ namespace IRaCIS.Core.Application.Contracts.DTO
public QARelationInfo RelationInfo { get; set; } = new QARelationInfo();
public List<SecondReviewDto> SecondReviewList { get; set; }
}
@@ -11,6 +11,36 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace IRaCIS.Core.Application.Contracts
{
public class ImageBackQueryDto : PageInput
{
[NotDefault]
public Guid TrialId { get; set; }
public Guid? TrialSiteId { get; set; }
public string? SubjectCode { get; set; } = string.Empty;
public Guid? CreateUserId { get; set; }
public string? VisitName { get; set; }
public ImageBackApplyEnum? ApplyUserRole { get; set; }
public DateTime? ApplyBeginTime { get; set; }
public DateTime? ApplyEndTime { get; set; }
public ImageBackStateEnum? ImageBackState { get; set; }
public DateTime? AuditBeginTime { get; set; }
public DateTime? AuditEndTime { get; set; }
public string[]? VisitPlanArray { get; set; }
}
public class CRCVisitSearchDTO : PageInput
{
@@ -166,13 +196,15 @@ namespace IRaCIS.Core.Application.Contracts
[Comment("阅片任务产生之前 采集影像")]
public CollectImagesType CollectImagesEnum { get; set; }
public List<StudyName> StudyNameList { get; set; }
public List<StudyName> StudyNameList { get; set; }
public List<string> ImageFormatList { get; set; }
public bool IsShowStudyName { get; set; } = false;
public bool IsQCQuestionConfirmed { get; set; }
}
@@ -867,6 +899,8 @@ namespace IRaCIS.Core.Application.Contracts
/*string.Format("{0}分钟", (ReadingDurationTimeSpan)?.TotalMinutes)*/;
}
}
public int? RandomOrder { get; set; }
}
@@ -1687,6 +1721,50 @@ namespace IRaCIS.Core.Application.Contracts
#endregion
public class ImageBackViewModel
{
public Guid Id { get; set; }
public DateTime CreateTime { get; set; }
public string CreateUserName { get; set; }
public string CreateUserFullName { get; set; }
public DateTime? AuditTime { get; set; }
public Guid SubjectVisitId { get; set; }
public ImageBackApplyEnum ApplyUserRole { get; set; }
public ImageBackStateEnum ImageBackState { get; set; }
public DateTime? SubmitTime { get; set; }
public bool IsUrgent { get; set; }
public string VisitName { get; set; } = string.Empty;
public DateTime? EarliestScanDate { get; set; }
public DateTime? LatestScanDate { get; set; }
public decimal VisitNum { get; set; }
public string SubjectCode { get; set; } = String.Empty;
public String TrialSiteCode { get; set; } = String.Empty;
/// <summary>
/// 申请原因
/// </summary>
public string ApplyReason { get; set; } = string.Empty;
/// <summary>
/// 结果备注
/// </summary>
public string ResultRemark { get; set; } = string.Empty;
}
public class QCCRCVisitViewModel : QCVisitBasicListViewModel
@@ -1873,6 +1951,7 @@ namespace IRaCIS.Core.Application.Contracts
public class QCQuestionAnswer
{
public Guid? AnswerId { get; set; }
public Guid Id { get; set; }
public string QuestionName { get; set; } = String.Empty;
public bool IsRequired { get; set; }
@@ -1901,6 +1980,8 @@ namespace IRaCIS.Core.Application.Contracts
// 1代表第一个人QC数据 2 代表第二个人QC数据
public CurrentQC CurrentQCEnum { get; set; }
public DateTime? SecondReviewTime { get; set; }
}
public class ForwardQuery : PageInput
@@ -2054,6 +2135,8 @@ namespace IRaCIS.Core.Application.Contracts
public class QCVisitBasicListViewModel
{
public SecondReviewState SecondReviewState { get; set; }
public bool IsSubjectQuit { get; set; }
public ChallengeStateEnum ChallengeState { get; set; }
public bool? IsConfirmedClinicalData { get; set; }
public bool IsQCConfirmedReupload { get; set; }
@@ -2108,6 +2191,8 @@ namespace IRaCIS.Core.Application.Contracts
public DateTime? ReviewAuditTime { get; set; }
public DateTime? PreliminaryAuditTime { get; set; }
public bool IsImageBackApplying { get; set; }
public DateTime? AuditTime => QCProcessEnum == TrialQCProcess.SingleAudit ? PreliminaryAuditTime : (QCProcessEnum == TrialQCProcess.DoubleAudit ? ReviewAuditTime : null);
}
@@ -35,6 +35,8 @@ namespace IRaCIS.Core.Application.Contracts
public DateTime UpdateTime { get; set; }
public Guid UpdateUserId { get; set; }
public bool IsQuestionQCAuditPassed { get; set; }
}
public class QCQuestionFilterSelect
@@ -13,7 +13,7 @@ namespace IRaCIS.Core.Application.Image.QA
Task<IResponseOutput> QCPassedOrFailed(Guid trialId, Guid subjectVisitId, [FromRoute] AuditStateEnum auditState);
Task<IResponseOutput> SetCheckPass(SetCheckPassDt data);
Task<IResponseOutput> QCSecondReviewPassedOrFailed(Guid trialId, Guid subjectVisitId, bool isSecondPass);
Task<IResponseOutput> AddCheckChallengeReply(CheckChallengeDialogCommand checkDialogCommand);
@@ -121,6 +121,41 @@ namespace IRaCIS.Core.Application.Service
}
return svExpression;
}
public static Expression<Func<SubjectVisitImageBackRecord, bool>> GetSubjectVisitImageBackRecordFilter(string[]? VisitPlanArray)
{
Expression<Func<SubjectVisitImageBackRecord, bool>> svExpression = x => true;
bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0;
if (isNeedVisitSearch)
{
var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray();
var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.'));
if (inPlanArray.Length > 0)
{
svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum));
if (isSelectOutPlan)
{
svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false);
}
}
else if (isSelectOutPlan)
{
svExpression = t => t.SubjectVisit.InPlan == false;
}
}
return svExpression;
@@ -4,8 +4,11 @@ using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using MassTransit.Initializers;
using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using System.Linq;
namespace IRaCIS.Core.Application.Image.QA
{
@@ -22,10 +25,48 @@ namespace IRaCIS.Core.Application.Image.QA
IRepository<DicomSeries> _dicomSeriesRepository,
IRepository<NoneDicomStudy> _noneDicomStudyRepository,
IRepository<QCChallenge> _qcChallengeRepository,
IRepository<SubjectVisitImageBackRecord> _subjectVisitImageBackRecordReposiotry,
IRepository<UserRole> _userRoleReposiotry,
IReadingImageTaskService _IReadingImageTaskService, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IQCListService
{
#region CRC IQC 退
public async Task<IResponseOutput> GetImageBackApplyUserList(Guid trialId)
{
var list = _subjectVisitImageBackRecordReposiotry.Where(t => t.SubjectVisit.TrialId == trialId).Select(t => new { t.CreateUserId, t.CreateUserRole.UserName, t.CreateUserRole.FullName }).Distinct().ToList();
return ResponseOutput.Ok(list);
}
[HttpPost]
public async Task<IResponseOutput<PageOutput<ImageBackViewModel>>> GetImageBackList(ImageBackQueryDto inQuery)
{
var svExpression = QCCommon.GetSubjectVisitImageBackRecordFilter(inQuery.VisitPlanArray);
var query = _subjectVisitImageBackRecordReposiotry.Where(t => t.SubjectVisit.TrialId == inQuery.TrialId)
.WhereIf(inQuery.TrialSiteId != null, t => t.SubjectVisit.TrialSiteId == inQuery.TrialSiteId)
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.SubjectVisit.Subject.Code.Contains(inQuery.SubjectCode))
.WhereIf(!string.IsNullOrEmpty(inQuery.VisitName), t => t.SubjectVisit.VisitName.Contains(inQuery.VisitName))
.WhereIf(inQuery.VisitPlanArray != null && inQuery.VisitPlanArray?.Length > 0, svExpression)
.WhereIf(inQuery.CreateUserId != null, t => t.CreateUserId == inQuery.CreateUserId)
.WhereIf(inQuery.ApplyUserRole != null, t => t.ApplyUserRole == inQuery.ApplyUserRole)
.WhereIf(inQuery.ApplyBeginTime != null, t => t.CreateTime >= inQuery.ApplyBeginTime)
.WhereIf(inQuery.ApplyEndTime != null, t => t.CreateTime <= inQuery.ApplyEndTime)
.WhereIf(inQuery.ImageBackState != null, t => t.ImageBackState == inQuery.ImageBackState)
.WhereIf(inQuery.AuditBeginTime != null, t => t.AuditTime >= inQuery.AuditBeginTime)
.WhereIf(inQuery.AuditEndTime != null, t => t.AuditTime <= inQuery.AuditEndTime)
.ProjectTo<ImageBackViewModel>(_mapper.ConfigurationProvider);
var defalutSortArray = new string[] { nameof(ImageBackViewModel.IsUrgent) + " desc", nameof(ImageBackViewModel.SubjectCode), nameof(ImageBackViewModel.VisitNum) };
var pageList = await query.ToPagedListAsync(inQuery, defalutSortArray);
return ResponseOutput.Ok(pageList);
}
#endregion
@@ -371,16 +412,56 @@ namespace IRaCIS.Core.Application.Image.QA
var qacheckList = await GetQCQuestionAnswerList(subjectVisitId, sv.TrialId, trialQCProcess, currentQCType);
List<SecondReviewDto> secondReviewList = new List<SecondReviewDto>();
if (sv.SecondReviewState != SecondReviewState.None)
{
var trialConfirmTime = _trialRepository.Where(t => t.Id == sv.TrialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
secondReviewList = (from answer in _trialQCQuestionAnswerRepository.Where(t => t.SubjectVisitId == subjectVisitId && t.CurrentQCEnum == CurrentQC.SecondReview).Where(t => t.SecondReviewTime != null)
join userRole in _userRoleReposiotry.Where() on answer.UpdateUserId equals userRole.Id
select new SecondReviewDto { SecondReviewTime = answer.SecondReviewTime, SignTime = answer.UpdateTime, FullName = userRole.FullName, UserName = userRole.UserName })
.Distinct().ToList();
var secondReviewTimeList = secondReviewList.Select(t => t.SecondReviewTime).Distinct().ToList();
//首次加入
if (!secondReviewTimeList.Contains(trialConfirmTime))
{
secondReviewList.Add(new SecondReviewDto() { SecondReviewTime = trialConfirmTime });
}
else
{
if (sv.SecondReviewState == SecondReviewState.WaitAudit)
{
foreach (var item in secondReviewList)
{
if (item.SecondReviewTime == trialConfirmTime)
{
item.SignTime = null;
item.FullName = "";
item.UserName = "";
}
}
}
}
secondReviewList = secondReviewList.OrderByDescending(t => t.SecondReviewTime).ToList();
}
return new TrialVisitQADTO
{
QCQuestionAnswerList = qacheckList,
SecondReviewList = secondReviewList,
IsHaveStudyClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.IsConfirm && x.TrialId == sv.TrialId && x.ClinicalDataLevel == ClinicalLevel.Study),
StudyList = temp.StudyList,
ExistsManual = (await _IReadingImageTaskService.GetManualList(new GetManualListInDto() { TrialId = sv.TrialId })).Count() > 0,
SeriesList = temp.SeriesList,
RelationInfo = await GetVisitQCSubjectInfo(subjectVisitId),
NoneDicomStudyList = await _noneDicomStudyRepository.Where(t => t.SubjectVisitId == subjectVisitId,ignoreQueryFilters:true).ProjectTo<NoneDicomStudyView>(_mapper.ConfigurationProvider).ToListAsync(),
NoneDicomStudyList = await _noneDicomStudyRepository.Where(t => t.SubjectVisitId == subjectVisitId, ignoreQueryFilters: true).ProjectTo<NoneDicomStudyView>(_mapper.ConfigurationProvider).ToListAsync(),
SubjectClinicalData = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId)
.ProjectTo<SubjectClinicalDataDto>(_mapper.ConfigurationProvider, new { subjectVisitId = subjectVisitId, token = _userInfo.UserToken }).FirstOrDefaultAsync()
};
@@ -394,11 +475,53 @@ namespace IRaCIS.Core.Application.Image.QA
[HttpPost]
public async Task<List<QCQuestionAnswer>> GetQCQuestionAnswer(GetQCQuestionAnswerInDto inDto)
{
var questionAnswerlist = await (from data in _trialQCQuestionRepository.Where(x => x.TrialId == inDto.TrialId && x.IsEnable)
join answer in _trialQCQuestionAnswerRepository.Where(x => x.SubjectVisitId == inDto.SubjectVisitId && x.QCProcessEnum == inDto.QCProcessEnum && x.CurrentQCEnum == inDto.CurrentQCEnum).AsQueryable() on data.Id equals answer.TrialQCQuestionConfigureId into answertemp
var subjectVisitId = inDto.SubjectVisitId;
List<QCQuestionAnswer> questionAnswerlist = new List<QCQuestionAnswer>();
//判断当前访视质控是否完成,再判断复审是完成查看,还是添加编辑
var sv = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).FirstNotNullAsync();
var trialConfirmTime = _trialRepository.Where(t => t.Id == sv.TrialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
var secondReviewTime = inDto.SecondReviewTime != null ? (DateTime)inDto.SecondReviewTime : trialConfirmTime == null ? DateTime.Now : (DateTime)trialConfirmTime;
if ((sv.AuditState == AuditStateEnum.QCPassed && inDto.CurrentQCEnum != CurrentQC.SecondReview) || (inDto.CurrentQCEnum == CurrentQC.SecondReview && secondReviewTime.AddSeconds(1) < trialConfirmTime))
{
//之前质控完的,+二次复核完的,都要从答案表中取 二次复核完的还需要加时间
questionAnswerlist = await _trialQCQuestionAnswerRepository.Where(x => x.SubjectVisitId == inDto.SubjectVisitId && x.QCProcessEnum == inDto.QCProcessEnum && x.CurrentQCEnum == inDto.CurrentQCEnum)
.Where(t => inDto.CurrentQCEnum == CurrentQC.SecondReview ? t.SecondReviewTime >= secondReviewTime && t.SecondReviewTime <= secondReviewTime.AddSeconds(1) : true)
.Select(data => new QCQuestionAnswer()
{
AnswerId = data.Id,
Answer = data.Answer,
ShowOrder = data.TrialQCQuestionConfigure.ShowOrder,
QuestionName = data.TrialQCQuestionConfigure.QuestionName,
Id = data.TrialQCQuestionConfigure.Id,
IsRequired = data.TrialQCQuestionConfigure.IsRequired,
ParentId = data.TrialQCQuestionConfigure.ParentId,
ParentTriggerValue = data.TrialQCQuestionConfigure.ParentTriggerValue,
Type = data.TrialQCQuestionConfigure.Type,
TypeValue = data.TrialQCQuestionConfigure.TypeValue
}).OrderBy(t => t.ShowOrder).ToListAsync();
}
else
{
#region
questionAnswerlist = await (from data in _trialQCQuestionRepository.Where(x => x.TrialId == inDto.TrialId && x.IsEnable)
join answer in _trialQCQuestionAnswerRepository.Where(x => x.SubjectVisitId == inDto.SubjectVisitId && x.QCProcessEnum == inDto.QCProcessEnum && x.CurrentQCEnum == inDto.CurrentQCEnum)
.Where(t => inDto.CurrentQCEnum == CurrentQC.SecondReview ? t.SecondReviewTime >= secondReviewTime && t.SecondReviewTime <= secondReviewTime.AddSeconds(1) : true)
on data.Id equals answer.TrialQCQuestionConfigureId into answertemp
from leftanswer in answertemp.DefaultIfEmpty()
select new QCQuestionAnswer()
{
AnswerId = leftanswer.Id,
Answer = leftanswer.Answer,
ShowOrder = data.ShowOrder,
QuestionName = data.QuestionName,
@@ -409,8 +532,19 @@ namespace IRaCIS.Core.Application.Image.QA
Type = data.Type,
TypeValue = data.TypeValue
}).OrderBy(t => t.ShowOrder).ToListAsync();
#endregion
}
var result = questionAnswerlist.Where(x => x.ParentId == null).OrderBy(t=>t.ShowOrder).ToList();
var result = questionAnswerlist.Where(x => x.ParentId == null).OrderBy(t => t.ShowOrder).ToList();
result.ForEach(x =>
{
GetQuestionChild(x, questionAnswerlist);
@@ -534,7 +668,7 @@ namespace IRaCIS.Core.Application.Image.QA
var visit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).FirstNotNullAsync();
var list = await _dicomStudyRepository.Where(s => s.SubjectVisitId == subjectVisitId).IgnoreQueryFilters().ProjectTo<QAStudyInfoDTO>(_mapper.ConfigurationProvider,new { isNeedStat= isNeedStat }).OrderBy(t => t.StudyCode).ToListAsync();
var list = await _dicomStudyRepository.Where(s => s.SubjectVisitId == subjectVisitId).IgnoreQueryFilters().ProjectTo<QAStudyInfoDTO>(_mapper.ConfigurationProvider, new { isNeedStat = isNeedStat }).OrderBy(t => t.StudyCode).ToListAsync();
var config = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => t.Trial).ProjectTo<TrialSubjectAndSVConfig>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
@@ -3,12 +3,14 @@ using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.Inspection.DTO;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using Medallion.Threading;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Cmp;
using System.ComponentModel.DataAnnotations;
using System.Data;
@@ -38,6 +40,8 @@ namespace IRaCIS.Core.Application.Image.QA
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IDistributedLockProvider _distributedLockProvider, IReadingClinicalDataService _readingClinicalDataService,
IOSSService _oSSService,
IRepository<ReadingClinicalData> _readingClinicalDataReposiotry,
IRepository<SubjectVisitImageBackRecord> _subjectVisitImageBackRecordReposiotry,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IWebHostEnvironment _hostEnvironment) : BaseService, IQCOperationService
{
@@ -239,6 +243,186 @@ namespace IRaCIS.Core.Application.Image.QA
#endregion
#region CRC IQC 退
/// <summary>
/// CRC IQC 申请影像回退
/// </summary>
/// <param name="subjectVisitId"></param>
/// <param name="ApplyReason"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
[HttpPut]
public async Task<IResponseOutput> RequestImageBack(Guid subjectVisitId, string ApplyReason)
{
if (_subjectVisitRepository.Any(t => t.Id == subjectVisitId && t.QCChallengeList.Any(t => t.IsClosed == false)))
{
//有未关闭的质疑,不允许在此申请影像回退
throw new BusinessValidationFailedException(_localizer["QCOperation_HaveNotClosedQCChanllenge"]);
}
if (!_subjectVisitRepository.Any(t => t.Id == subjectVisitId && !t.VisitTaskList.Any(u => u.TaskState == TaskState.Effect) && t.SubmitState == SubmitStateEnum.Submitted))
{
//已提交、未生成任务的才允许申请
throw new BusinessValidationFailedException(_localizer["QCOperation_ShouldBeforeCheckPassed"]);
}
if (_subjectVisitImageBackRecordReposiotry.Any(t => t.SubjectVisitId == subjectVisitId && t.ImageBackState == ImageBackStateEnum.None))
{
//已经有在申请的影像回退记录
throw new BusinessValidationFailedException(_localizer["QCOperation_HaveApplyedImageBack"]);
}
if (_qcChallengeRepository.Any(t => t.SubjectVisitId == subjectVisitId && t.IsClosed == false && t.ReuploadEnum == QCChanllengeReuploadEnum.CRCRequestReupload))
{
throw new BusinessValidationFailedException(_localizer["QCOperation_SomeOneHaveApplyedImageBack"]);
}
var sv = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException();
if (sv.RequestBackState == RequestBackStateEnum.CRC_RequestBack)
{
// 该访视已在其他途径申请影像回退中,不允许申请
throw new BusinessValidationFailedException(_localizer["QCOperation_SomeOneHaveApplyedImageBack"]);
}
var newRecord = new SubjectVisitImageBackRecord() { SubjectVisitId = subjectVisitId, ApplyReason = ApplyReason, SubmitTime = sv.SubmitTime, EarliestScanDate = sv.EarliestScanDate, LatestScanDate = sv.LatestScanDate };
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator)
{
newRecord.ApplyUserRole = ImageBackApplyEnum.CRCRequestBack;
}
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.IQC)
{
newRecord.ApplyUserRole = ImageBackApplyEnum.IQCRequestBack;
}
await _subjectVisitImageBackRecordReposiotry.AddAsync(newRecord, true);
return ResponseOutput.Ok();
}
/// <summary>
/// PM 审核CRC IQC 申请影像回退
/// </summary>
/// <param name="iamgeBackRecordId"></param>
/// <param name="isAgree"></param>
/// <param name="resultRemark"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
[HttpPut]
public async Task<IResponseOutput> AuditImageBack(Guid iamgeBackRecordId, bool isAgree, string? resultRemark)
{
var backRecord = (await _subjectVisitImageBackRecordReposiotry.FirstOrDefaultAsync(t => t.Id == iamgeBackRecordId)).IfNullThrowException();
var sv = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == backRecord.SubjectVisitId)).IfNullThrowException();
var subjectVisitId = backRecord.SubjectVisitId;
if (backRecord.ApplyUserRole != ImageBackApplyEnum.CRCRequestBack && backRecord.ApplyUserRole != ImageBackApplyEnum.IQCRequestBack)
{
//当前访视状态不在影像申请回退状态,不允许审核通过
throw new BusinessValidationFailedException(_localizer["QCOperation_NotInRequestImageBackState"]);
}
if (isAgree)
{
if (_subjectVisitRepository.Any(t => t.Id == subjectVisitId && t.QCChallengeList.Any(t => t.IsClosed == false)))
{
//有未关闭的质疑,不允许同意影像回退
throw new BusinessValidationFailedException(_localizer["QCOperation_HaveNotClosedQCChanllenge"]);
}
if (sv.SubmitState == SubmitStateEnum.Submitted && _subjectVisitRepository.Any(t => t.Id == backRecord.SubjectVisitId && !t.VisitTaskList.Any(u => u.TaskState == TaskState.Effect)))
{
backRecord.ImageBackState = ImageBackStateEnum.PMAgreeBack;
}
else
{
//已提交未生成任务的才允许申请
throw new BusinessValidationFailedException(_localizer["QCOperation_ShouldBeforeCheckPassed"]);
}
#region 退
//需要重新产生任务
sv.IsVisitTaskGenerated = false;
sv.IsPMBackOrReReading = true;
sv.AuditState = AuditStateEnum.None;
sv.SubmitState = SubmitStateEnum.ToSubmit;
sv.ReadingStatus = ReadingStatusEnum.ImageNotSubmit;
//回退后,回退状态恢复
sv.RequestBackState = RequestBackStateEnum.NotRequest;
sv.IsCheckBack = false;
sv.CheckBackTime = null;
sv.CheckState = CheckStateEnum.None;
sv.CheckChallengeState = CheckChanllengeTypeEnum.None;
sv.SVENDTC = null;
sv.SVSTDTC = null;
sv.PreliminaryAuditTime = null;
sv.SubmitTime = null;
sv.ReviewAuditTime = null;
sv.CurrentActionUserExpireTime = null;
sv.IsTake = false;
sv.CurrentActionUserId = null;
sv.PreliminaryAuditUserId = null;
sv.ReviewAuditUserId = null;
sv.SecondReviewState = SecondReviewState.None;
if (sv.IsBaseLine)
{
await _readingClinicalDataReposiotry.UpdatePartialFromQueryAsync(t => t.ReadingId == sv.Id && (t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.Subject || t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit), c => new ReadingClinicalData() { IsSign = false, ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded });
}
else
{
await _readingClinicalDataReposiotry.UpdatePartialFromQueryAsync(t => t.ReadingId == sv.Id && t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit, c => new ReadingClinicalData()
{
IsSign = false,
ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded,
IsBlind = null,
IsComplete = null
});
}
await _trialQCQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => t.SubjectVisitId == subjectVisitId);
#endregion
}
else
{
backRecord.ImageBackState = ImageBackStateEnum.PMNotAgreeBack;
}
backRecord.AuditTime = DateTime.Now;
backRecord.ResultRemark = resultRemark ?? string.Empty;
await _subjectVisitRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
#endregion
#region
/// <summary>
@@ -383,6 +567,20 @@ namespace IRaCIS.Core.Application.Image.QA
return ResponseOutput.NotOk(_localizer["QCOperation_Cannotback"]);
}
if (await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).AnyAsync(t => t.SubjectVisitImageBackRecordList.Any(t => t.ImageBackState == ImageBackStateEnum.None)))
{
// 该访视已在其他途径申请影像回退中,不允许申请
throw new BusinessValidationFailedException(_localizer["QCOperation_SomeOneHaveApplyedImageBack"]);
}
if (sv.RequestBackState == RequestBackStateEnum.CRC_RequestBack)
{
// 该访视已在其他途径申请影像回退中,不允许申请
throw new BusinessValidationFailedException(_localizer["QCOperation_SomeOneHaveApplyedImageBack"]);
}
var QCChallengeId = await _qcChallengeRepository.Where(x => x.SubjectVisitId == subjectVisitId).Select(x => x.Id).FirstOrDefaultAsync();
await _checkChallengeDialogRepository.AddAsync(new CheckChallengeDialog()
@@ -394,7 +592,7 @@ namespace IRaCIS.Core.Application.Image.QA
});
if (sv.RequestBackState == RequestBackStateEnum.NotRequest || sv.RequestBackState == RequestBackStateEnum.PM_NotAgree)
if (sv.RequestBackState != RequestBackStateEnum.CRC_RequestBack)
{
sv.RequestBackState = RequestBackStateEnum.CRC_RequestBack;
@@ -468,16 +666,14 @@ namespace IRaCIS.Core.Application.Image.QA
return ResponseOutput.NotOk(_localizer["QCOperation_CannotRollback"]);
}
//sv.CheckChallengeState = (int)CheckChanllengeTypeEnum.None;
//sv.CheckState = CheckStateEnum.None;
//sv.ChallengeState = (int)ChallengeStateEnum.No;
sv.RequestBackState = RequestBackStateEnum.PM_AgressBack;
sv.AuditState = AuditStateEnum.None;
sv.SubmitState = SubmitStateEnum.ToSubmit;
sv.ReadingStatus = ReadingStatusEnum.ImageNotSubmit;
//回退后,回退状态恢复
sv.RequestBackState = RequestBackStateEnum.NotRequest;
sv.IsCheckBack = true;
sv.CheckBackTime = DateTime.Now;
sv.CheckState = CheckStateEnum.None;
@@ -496,6 +692,7 @@ namespace IRaCIS.Core.Application.Image.QA
sv.CurrentActionUserId = null;
sv.PreliminaryAuditUserId = null;
sv.ReviewAuditUserId = null;
sv.SecondReviewState = SecondReviewState.None;
//var success1 = _studyRepository.Delete(t => t.SubjectVisitId == subjectVisitId);
//var succeess2 = _instanceRepository.Delete(t => t.SubjectVisitId == subjectVisitId);
@@ -532,9 +729,17 @@ namespace IRaCIS.Core.Application.Image.QA
//[Authorize(Policy = IRaCISPolicy.IQC)]
public async Task<IResponseOutput> AddOrUpdateQCQuestionAnswerList(QCQuestionAnswerCommand[] qcQuestionAnswerCommands, Guid trialId, Guid subjectVisitId, [FromRoute] TrialQCProcess trialQCProcess, [FromRoute] CurrentQC currentQCType)
{
if (currentQCType == CurrentQC.SecondReview)
{
//二次复核自动领取,如果有人先领取了,那么后续不能操作
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId && t.CurrentActionUserId == null, u => new SubjectVisit() { CurrentActionUserId = _userInfo.UserRoleId, IsTake = true }, true);
}
//验证是否能操作
await VerifyIsCanQCAsync(null, subjectVisitId);
var trialConfirmTime = _trialRepository.Where(t => t.Id == trialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
//更新
if (qcQuestionAnswerCommands.Any(t => t.Id != null))
{
@@ -579,11 +784,13 @@ namespace IRaCIS.Core.Application.Image.QA
{
var addlist = _mapper.Map<List<TrialQCQuestionAnswer>>(qcQuestionAnswerCommands);
addlist.ForEach(t => { t.TrialId = trialId; t.SubjectVisitId = subjectVisitId; t.CurrentQCEnum = currentQCType; t.QCProcessEnum = trialQCProcess; });
addlist.ForEach(t => { t.TrialId = trialId; t.SubjectVisitId = subjectVisitId; t.CurrentQCEnum = currentQCType; t.QCProcessEnum = trialQCProcess; t.SecondReviewTime = currentQCType == CurrentQC.SecondReview ? trialConfirmTime : null; });
await _trialQCQuestionAnswerRepository.AddRangeAsync(addlist);
return ResponseOutput.Result(await _trialQCQuestionAnswerRepository.SaveChangesAsync());
return ResponseOutput.Ok(await _trialQCQuestionAnswerRepository.SaveChangesAsync());
}
@@ -731,7 +938,7 @@ namespace IRaCIS.Core.Application.Image.QA
/// <returns></returns>
[HttpPut]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> SetNodicomStudyState(Guid subjectVisitId, Guid noneDicomStudyId, Guid? noneDicomStudyFileId, int state)
public async Task<IResponseOutput> SetNodicomStudyState(Guid subjectVisitId, Guid noneDicomStudyId, Guid? noneDicomStudyFileId, int state)
{
await VerifyIsCanQCAsync(null, subjectVisitId);
@@ -757,7 +964,7 @@ namespace IRaCIS.Core.Application.Image.QA
else if (state == 5)
{
noneDicomStudy.IsDeleted = false;
}
}
//设置检查下面的文件
@@ -766,6 +973,9 @@ namespace IRaCIS.Core.Application.Image.QA
var noneDicomStudyFile = (await _noneDicomStudyFileRepository.Where(t => t.Id == noneDicomStudyFileId, true).IgnoreQueryFilters().FirstOrDefaultAsync()).IfNullThrowException();
var noneDicomStudy = (await _noneDicomStudyRepository.Where(t => t.Id == noneDicomStudyFile.NoneDicomStudyId, true).IgnoreQueryFilters().FirstOrDefaultAsync()).IfNullThrowException();
if (state == 1)
{
noneDicomStudyFile.IsReading = false;
@@ -777,10 +987,15 @@ namespace IRaCIS.Core.Application.Image.QA
else if (state == 4)
{
noneDicomStudyFile.IsDeleted = true;
noneDicomStudy.FileCount = noneDicomStudy.FileCount - 1;
}
else if (state == 5)
{
noneDicomStudyFile.IsDeleted = false;
noneDicomStudy.FileCount = noneDicomStudy.FileCount + 1;
}
}
@@ -818,7 +1033,7 @@ namespace IRaCIS.Core.Application.Image.QA
{
var studyId = updateModalityCommand.Id;
var study = (await _dicomStudyRepository.FirstOrDefaultAsync(t => t.Id == studyId)).IfNullThrowException();
var study = (await _dicomStudyRepository.FirstOrDefaultAsync(t => t.Id == studyId, true)).IfNullThrowException();
study.BodyPartForEdit = updateModalityCommand.BodyPart;
@@ -890,7 +1105,7 @@ namespace IRaCIS.Core.Application.Image.QA
//---CRC已经提交,不允许删除。
return ResponseOutput.NotOk(_localizer["QCOperation_CrcNoDelete"]);
}
var waitDeleteStudyList = await _dicomStudyRepository.Where(x => ids.Contains(x.Id)).ToListAsync();
var waitDeleteStudyList = await _dicomStudyRepository.Where(x => ids.Contains(x.Id), false, true).ToListAsync();
foreach (var study in waitDeleteStudyList)
{
@@ -907,30 +1122,14 @@ namespace IRaCIS.Core.Application.Image.QA
await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, u => new SCPStudy() { SubjectVisitId = null });
if (fisrtPath.IsNotNullOrEmpty())
{
var prefix = fisrtPath.Substring(1, fisrtPath.LastIndexOf('/') - 1);
var prefix = fisrtPath.Substring(1, fisrtPath.LastIndexOf('/') - 1);
await _oSSService.DeleteFromPrefix(prefix, true);
//var success3 = await _dicomSeriesrepository.DeleteFromQueryAsync(t => t.StudyId == id, true);
//var success4 = await _repository.BatchDeleteAsync<StudyMonitor>(t => t.StudyId == id);
//删除 物理文件
//var instancePathList = await _dicomInstanceRepository.Where(t => t.StudyId == id)
// .Select(t => t.Path).ToListAsync();
//instancePathList.ForEach(path =>
//{
// var physicalPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, path);
// if (System.IO.File.Exists(physicalPath))
// {
// File.Delete(physicalPath);
// }
//});
await _oSSService.DeleteFromPrefix(prefix, false);
await _oSSService.DeleteFromPrefix(prefix, true);
}
}
@@ -986,10 +1185,12 @@ namespace IRaCIS.Core.Application.Image.QA
[HttpPut("{trialId:guid}/{subjectVisitId:guid}")]
//[Authorize(Policy = IRaCISPolicy.IQC)]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> ReplaceQCTaskActionUser(Guid trialId, Guid subjectVisitId)
public async Task<IResponseOutput> ReplaceQCTaskActionUser(Guid trialId, Guid subjectVisitId, Guid? replaceUserRoleId)
{
var dbSubjectVisit = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException();
//await VerifyIsCanQCAsync(dbSubjectVisit);
if (dbSubjectVisit.CurrentActionUserId == null && dbSubjectVisit.IsTake == false)
{
@@ -1000,7 +1201,7 @@ namespace IRaCIS.Core.Application.Image.QA
dbSubjectVisit.IsTake = true;
dbSubjectVisit.CurrentActionUserId = _userInfo.UserRoleId;
dbSubjectVisit.CurrentActionUserId = replaceUserRoleId == null || replaceUserRoleId == Guid.Empty ? _userInfo.UserRoleId : replaceUserRoleId;
dbSubjectVisit.CurrentActionUserExpireTime = DateTime.Now.AddHours(1);
@@ -1071,7 +1272,9 @@ namespace IRaCIS.Core.Application.Image.QA
return new GetNextIQCQualityOutDto() { };
break;
case TrialQCProcess.SingleAudit:
visitList = await _subjectVisitRepository.Where(x => x.SubmitState == SubmitStateEnum.Submitted
visitList = await _subjectVisitRepository
.Where(x => !x.SubjectVisitImageBackRecordList.Any(t => t.ImageBackState == ImageBackStateEnum.None))
.Where(x => x.SubmitState == SubmitStateEnum.Submitted
&& x.TrialId == inDto.TrialId && x.PreliminaryAuditUserId != _userInfo.UserRoleId && (x.CurrentActionUserId == _userInfo.UserRoleId || (x.AuditState != AuditStateEnum.PrimaryQCPassed && !x.IsTake)))
.Where(x => x.QCChallengeList.Count() == 0 || x.QCChallengeList.Where(y => !y.IsClosed).OrderByDescending(x => x.CreateTime).FirstOrDefault().CreateUserId != _userInfo.UserRoleId)
.Include(x => x.Subject).ToListAsync();
@@ -1105,7 +1308,9 @@ namespace IRaCIS.Core.Application.Image.QA
break;
case TrialQCProcess.DoubleAudit:
visitList = await _subjectVisitRepository.Where(x => x.SubmitState == SubmitStateEnum.Submitted && x.TrialId == inDto.TrialId &&
visitList = await _subjectVisitRepository
.Where(x => !x.SubjectVisitImageBackRecordList.Any(t => t.ImageBackState == ImageBackStateEnum.None))
.Where(x => x.SubmitState == SubmitStateEnum.Submitted && x.TrialId == inDto.TrialId &&
((x.CurrentActionUserId == _userInfo.UserRoleId) || (!x.IsTake && x.AuditState != AuditStateEnum.QCPassed && (x.PreliminaryAuditUserId != _userInfo.UserRoleId)))
)
.Where(x => x.QCChallengeList.Count() == 0 || x.QCChallengeList.Where(y => !y.IsClosed).OrderByDescending(x => x.CreateTime).FirstOrDefault().CreateUserId != _userInfo.UserRoleId)
@@ -1164,6 +1369,12 @@ namespace IRaCIS.Core.Application.Image.QA
if (obtaionOrCancel)
{
//复核的时候,指派后,另外一个人进来的时候如果是自己,那么不进行后续流程
if (dbSubjectVisit.CurrentActionUserId == _userInfo.UserRoleId)
{
return ResponseOutput.Ok();
}
if (dbSubjectVisit.CurrentActionUserId != null && dbSubjectVisit.IsTake)
{
//throw new BusinessValidationFailedException("当前访视已被领取,不允许领取");
@@ -1179,6 +1390,11 @@ namespace IRaCIS.Core.Application.Image.QA
return ResponseOutput.NotOk(_localizer["QCOperation_QCConfigFirst"], ApiResponseCodeEnum.NeedTips);
}
if (_subjectVisitImageBackRecordReposiotry.Any(t => t.SubjectVisitId == subjectVisitId && t.ImageBackState == ImageBackStateEnum.None))
{
//已申请的影像回退,不能领取
throw new BusinessValidationFailedException(_localizer["QCOperation_HaveApplyedImageBackCanNotObtain"]);
}
//if (await _subjectVisitRepository.AnyAsync(t => t.IsTake &&
// t.SubjectId != dbSubjectVisit.SubjectId &&
@@ -1190,65 +1406,69 @@ namespace IRaCIS.Core.Application.Image.QA
// return ResponseOutput.NotOk("您已经领取了其他受试者,完成后才允许领取新的受试者");
//}
#region
if (trialConfig.QCProcessEnum == TrialQCProcess.NotAudit)
if (dbSubjectVisit.SecondReviewState == SecondReviewState.None)
{
//---项目配置为不审,没有领取QC Task
return ResponseOutput.NotOk(_localizer["QCOperation_NoQC"]);
}
else if (trialConfig.QCProcessEnum == TrialQCProcess.SingleAudit)
{
if (dbSubjectVisit.PreliminaryAuditUserId == _userInfo.UserRoleId)
#region
if (trialConfig.QCProcessEnum == TrialQCProcess.NotAudit)
{
//---初审已通过,不能继续领取
return ResponseOutput.NotOk(_localizer["QCOperation_InitialAuditPassed"]);
//---项目配置为不审,没有领取QC Task
return ResponseOutput.NotOk(_localizer["QCOperation_NoQC"]);
}
else if (trialConfig.QCProcessEnum == TrialQCProcess.SingleAudit)
{
if (dbSubjectVisit.PreliminaryAuditUserId == _userInfo.UserRoleId)
{
//---初审已通过,不能继续领取
return ResponseOutput.NotOk(_localizer["QCOperation_InitialAuditPassed"]);
}
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.ToAudit)
{
dbSubjectVisit.AuditState = AuditStateEnum.InPrimaryQC;
}
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.InPrimaryQC)
{
//单审QC 释放后 也是可以领取的
}
else
{
// ---项目配置为单审,不满足Submmit State:已提交 或者 Audit State:待审核/审核中, 不允许领取,请刷新界面
return ResponseOutput.NotOk(_localizer["QCOperation_NoSingleAudit"]);
}
}
else if (trialConfig.QCProcessEnum == TrialQCProcess.DoubleAudit)
{
if (dbSubjectVisit.PreliminaryAuditUserId == _userInfo.UserRoleId)
{
//---复审不能和初审是同一个人
return ResponseOutput.NotOk(_localizer["QCOperation_NoSameReviewer"]);
}
//提交 并且初审通过 那么领取后进入 复审中
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.PrimaryQCPassed)
{
dbSubjectVisit.AuditState = AuditStateEnum.InSecondaryQC;
}
else if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.ToAudit)
{
dbSubjectVisit.AuditState = AuditStateEnum.InPrimaryQC;
}
else if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && (dbSubjectVisit.AuditState == AuditStateEnum.InPrimaryQC || dbSubjectVisit.AuditState == AuditStateEnum.InSecondaryQC))
{
//初审中 复审中 领取也是ok的 其他人接着做
}
else
{
//---项目配置为复审,不满足提交状态:已提交 或者 审核状态:待审核/QC中, 不允许领取,请刷新界面
return ResponseOutput.NotOk(_localizer["QCOperation_NoSecondaryAudit"]);
}
}
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.ToAudit)
{
dbSubjectVisit.AuditState = AuditStateEnum.InPrimaryQC;
}
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.InPrimaryQC)
{
//单审QC 释放后 也是可以领取的
}
else
{
// ---项目配置为单审,不满足Submmit State:已提交 或者 Audit State:待审核/审核中, 不允许领取,请刷新界面
return ResponseOutput.NotOk(_localizer["QCOperation_NoSingleAudit"]);
}
}
else if (trialConfig.QCProcessEnum == TrialQCProcess.DoubleAudit)
{
if (dbSubjectVisit.PreliminaryAuditUserId == _userInfo.UserRoleId)
{
//---复审不能和初审是同一个人
return ResponseOutput.NotOk(_localizer["QCOperation_NoSameReviewer"]);
}
//提交 并且初审通过 那么领取后进入 复审中
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.PrimaryQCPassed)
{
dbSubjectVisit.AuditState = AuditStateEnum.InSecondaryQC;
}
else if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.ToAudit)
{
dbSubjectVisit.AuditState = AuditStateEnum.InPrimaryQC;
}
else if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && (dbSubjectVisit.AuditState == AuditStateEnum.InPrimaryQC || dbSubjectVisit.AuditState == AuditStateEnum.InSecondaryQC))
{
//初审中 复审中 领取也是ok的 其他人接着做
}
else
{
//---项目配置为复审,不满足提交状态:已提交 或者 审核状态:待审核/QC中, 不允许领取,请刷新界面
return ResponseOutput.NotOk(_localizer["QCOperation_NoSecondaryAudit"]);
}
#endregion
}
#endregion
dbSubjectVisit.IsTake = true;
@@ -1697,8 +1917,8 @@ namespace IRaCIS.Core.Application.Image.QA
//删除 软删除的物理文件
var instancePathList = await _dicomInstanceRepository.Where(t => (t.DicomSerie.IsDeleted || t.IsDeleted) && t.SubjectVisitId == subjectVisitId, false, true)
.Select(t => t.Path).ToListAsync();
var noneDicomFileList = await _noneDicomStudyFileRepository.Where(t => (t.NoneDicomStudy.IsDeleted ||t.IsDeleted) && t.NoneDicomStudy.SubjectVisitId == subjectVisitId, false, true)
.Select(t => t.Path).ToListAsync();
var noneDicomFileList = await _noneDicomStudyFileRepository.Where(t => (t.NoneDicomStudy.IsDeleted || t.IsDeleted) && t.NoneDicomStudy.SubjectVisitId == subjectVisitId, false, true)
.Select(t => t.Path).ToListAsync();
@@ -1739,13 +1959,14 @@ namespace IRaCIS.Core.Application.Image.QA
//删除影像
await _dicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
await _dicomSeriesRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => (t.DicomSerie.IsDeleted || t.IsDeleted) && t.SubjectVisitId == subjectVisitId);
await _dicomSeriesRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
await _noneDicomStudyFileRepository.BatchDeleteNoTrackingAsync(t => (t.NoneDicomStudy.IsDeleted || t.IsDeleted) && t.NoneDicomStudy.SubjectVisitId == subjectVisitId);
await _noneDicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
await _noneDicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
await _oSSService.DeleteObjects(instancePathList.Select(t => t.TrimStart('/')).ToList());
await _oSSService.DeleteObjects(noneDicomFileList.Select(t => t.TrimStart('/')).ToList());
}
@@ -1800,8 +2021,12 @@ namespace IRaCIS.Core.Application.Image.QA
dbSubjectVisit.ReadingStatus = trialConfig.IsImageConsistencyVerification ? ReadingStatusEnum.ConsistencyCheck : ReadingStatusEnum.TaskAllocate;
//删除影像
await _dicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => (t.DicomSerie.IsDeleted || t.IsDeleted) && t.SubjectVisitId == subjectVisitId);
await _dicomSeriesRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
await _noneDicomStudyFileRepository.BatchDeleteNoTrackingAsync(t => (t.NoneDicomStudy.IsDeleted || t.IsDeleted) && t.NoneDicomStudy.SubjectVisitId == subjectVisitId);
await _noneDicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
await _oSSService.DeleteObjects(instancePathList.Select(t => t.TrimStart('/')).ToList());
await _oSSService.DeleteObjects(noneDicomFileList.Select(t => t.TrimStart('/')).ToList());
}
@@ -1876,8 +2101,46 @@ namespace IRaCIS.Core.Application.Image.QA
}
public async Task<IResponseOutput> QCSecondReviewPassedOrFailed(Guid trialId, Guid subjectVisitId, bool isSecondPass)
{
if (!await _trialUserRoleRepository.AnyAsync(t => t.TrialId == trialId && t.UserId == _userInfo.UserRoleId))
{
//---您已经被移出项目,没有操作权限。
return ResponseOutput.NotOk(_localizer["QCOperation_RemoveItem"]);
}
var sv = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
await VerifyIsCanQCAsync(sv);
var trialConfirmTime = _trialRepository.Where(t => t.Id == sv.TrialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
if (sv.SecondReviewState == SecondReviewState.WaitAudit)
{
if (isSecondPass)
{
sv.SecondReviewState = SecondReviewState.AuditPassed;
sv.IsTake = false;
sv.CurrentActionUserId = null;
sv.CurrentActionUserExpireTime = null;
}
else
{
sv.SecondReviewState = SecondReviewState.AuditFailed;
}
await _trialQCQuestionAnswerRepository.BatchUpdateNoTrackingAsync(t => t.SubjectVisitId == sv.Id && t.CurrentQCEnum == CurrentQC.SecondReview && t.SecondReviewTime == trialConfirmTime, u => new TrialQCQuestionAnswer()
{
UpdateUserId = _userInfo.UserRoleId,
UpdateTime = DateTime.Now
});
}
await _subjectVisitRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
/// <summary>
/// 设置、取消 访视紧急
@@ -2145,6 +2408,19 @@ namespace IRaCIS.Core.Application.Image.QA
{
var qcChallenge = (await _qcChallengeRepository.FirstOrDefaultAsync(t => t.Id == qcChallengeId)).IfNullThrowException();
var sv = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == qcChallenge.SubjectVisitId)).IfNullThrowException();
if (await _subjectVisitRepository.Where(t => t.Id == sv.Id).AnyAsync(t => t.SubjectVisitImageBackRecordList.Any(t => t.ImageBackState == ImageBackStateEnum.None)))
{
// 该访视已在其他途径申请影像回退中,不允许申请
throw new BusinessValidationFailedException(_localizer["QCOperation_SomeOneHaveApplyedImageBack"]);
}
if (sv.RequestBackState == RequestBackStateEnum.CRC_RequestBack)
{
// 该访视已在其他途径申请影像回退中,不允许申请
throw new BusinessValidationFailedException(_localizer["QCOperation_SomeOneHaveApplyedImageBack"]);
}
if (qcChallenge.ReuploadEnum != QCChanllengeReuploadEnum.None && qcChallenge.ReuploadEnum != QCChanllengeReuploadEnum.CRCReuploaded)
{
@@ -472,6 +472,7 @@ namespace IRaCIS.Core.Application.Service
CreateMap<TrialQCQuestion, TrialQCQuestionAddOrEdit>();
CreateMap<TrialQCQuestion, TrialQCQuestionConfigureView>()
.ForMember(d => d.IsQuestionQCAuditPassed, u => u.MapFrom(s => s.TrialQCQuestionAnswerList.Any(c => c.TrialQCQuestionConfigureId == s.Id && c.SubjectVisit.AuditState == AuditStateEnum.QCPassed)))
.ForMember(d => d.ParentShowOrder, u => u.MapFrom(s => s.ParentQCQuestion.ShowOrder));
CreateMap<TrialQCQuestionSelect, TrialQCQuestionConfigureView>();
@@ -528,6 +529,7 @@ namespace IRaCIS.Core.Application.Service
|| t.ReadingClinicalDataList.Any(x => x.ClinicalDataTrialSet.UploadRole == Domain.Share.UploadRole.CRC && x.ReadingClinicalDataPDFList.Count > 0)
|| t.PreviousSurgeryList.Any()))
.ForMember(d => d.DicomStudyCount, u => u.MapFrom(t => t.StudyList.Count()))
.ForMember(d => d.IsImageBackApplying, u => u.MapFrom(t => t.SubjectVisitImageBackRecordList.Any(c => c.ImageBackState == ImageBackStateEnum.None)))
.ForMember(d => d.NoneDicomStudyCount, u => u.MapFrom(t => t.NoneDicomStudyList.Count(t => t.NoneDicomFileList.Any())));
//CRC 上传列表
@@ -555,6 +557,7 @@ namespace IRaCIS.Core.Application.Service
//.ForMember(d => d.VisitNum, u => u.MapFrom(t => t.InPlan ? t.VisitStage.VisitNum : t.VisitNum))
//.ForMember(d => d.VisitDay, u => u.MapFrom(t => t.InPlan ? t.VisitStage.VisitDay : t.VisitDay))
.ForMember(d => d.DicomStudyCount, u => u.MapFrom(t => t.StudyList.Count()))
.ForMember(d => d.IsImageBackApplying, u => u.MapFrom(t => t.SubjectVisitImageBackRecordList.Any(c => c.ImageBackState == ImageBackStateEnum.None)))
.ForMember(d => d.NoneDicomStudyCount, u => u.MapFrom(t => t.NoneDicomStudyList.Count(t => t.NoneDicomFileList.Any())));
//.ForMember(d => d.StudyCount, u => u.MapFrom(s => s.StudyList.Count()));
CreateMap<Subject, QCCRCVisitViewModel>();
@@ -731,12 +734,22 @@ namespace IRaCIS.Core.Application.Service
Guid? visiTaskId = null;
CreateMap<NoneDicomStudy, TaskDicomStudyView>()
.ForMember(d => d.NoneDicomStudyFileList, u => u.MapFrom(s =>
s.TaskNoneDicomFileList.Where(t => visiTaskId != null ? t.VisitTaskId == visiTaskId : true).Where(t => isFilterZip ? !t.FileType.Contains(StaticData.FileType.Zip):true)
.ForMember(d => d.NoneDicomStudyFileList, u => u.MapFrom(s =>
s.TaskNoneDicomFileList.Where(t => visiTaskId != null ? t.VisitTaskId == visiTaskId : true).Where(t => isFilterZip ? !t.FileType.Contains(StaticData.FileType.Zip) : true)
.Where(t => isReading ? t.IsReading && t.IsDeleted == false : true)
.OrderBy(t => t.CreateTime).ThenBy(t => t.FileName)))
.OrderBy(t => t.CreateTime).ThenBy(t => t.FileName)))
.ForMember(d => d.CodeView, u => u.MapFrom(s => s.StudyCode));
CreateMap<SubjectVisitImageBackRecord, ImageBackViewModel>()
.ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.SubjectVisit.Subject.Code))
.ForMember(d => d.VisitNum, u => u.MapFrom(t => t.SubjectVisit.VisitNum))
.ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.SubjectVisit.TrialSite.TrialSiteCode))
.ForMember(d => d.VisitName, u => u.MapFrom(s => s.SubjectVisit.VisitName))
.ForMember(d => d.IsUrgent, u => u.MapFrom(s => s.SubjectVisit.IsUrgent))
.ForMember(d => d.CreateUserName, u => u.MapFrom(s => s.CreateUserRole.UserName))
.ForMember(d => d.CreateUserFullName, u => u.MapFrom(s => s.CreateUserRole.FullName));
}
}
@@ -291,6 +291,23 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
public List<string> SheetNames { get; set; }
}
public class TestOncologyDto
{
public Guid Id { get; set; }
public string TargetLesion { get; set; }
public string NonTargetLesions { get; set; }
public string NewLesion { get; set; }
public string OverallEfficacy { get; set; }
}
/// <summary>
/// 阅片计算Dto
/// </summary>
@@ -877,6 +877,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
public class CopyTableAnswerRowInfo : ReadingTableAnswerRowInfoBase
{
public Guid OriginalId { get; set; }
public LesionType? LesionType { get; set; }
}
public class CopyTableAnswerDto
{
@@ -1852,6 +1854,13 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
public bool IsBaseLine { get; set; }
/// <summary>
/// 阅片版本
/// </summary>
public ReadingVersion ReadingVersionEnum { get; set; }
public List<string> ReadingToolList { get; set; } = new List<string>();
public ReadingCategory ReadingCategory { get; set; }
public decimal VisitNum { get; set; }
@@ -792,6 +792,20 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
/// </summary>
public int? DigitPlaces { get; set; } = 2;
/// <summary>
/// 阅片版本
/// </summary>
public ReadingVersion? ReadingVersionEnum { get; set; }
public ReadingTool? ReadingTool { get; set; }
/// <summary>
/// 阅片工具
/// </summary>
public List<string> ReadingToolList { get; set; } = new List<string>();
}
@@ -12,6 +12,7 @@ namespace IRaCIS.Core.Application.Contracts
{
public interface IReadingImageTaskService
{
Task TriggerJudgeQuestion(Guid visitTaskId);
Task<IResponseOutput> SubmitVisitTaskQuestions(SubmitVisitTaskQuestionsInDto inDto);
Task<IResponseOutput> SubmitJudgeVisitTaskResult(SaveJudgeVisitTaskResult inDto);
@@ -16,6 +16,7 @@ namespace IRaCIS.Core.Application.Service.RC
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository,
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswer,
IRepository<Dictionary> _dictionarRepository,
IRepository<ReadingCriterionPage> _readingCriterionPageRepository,
IRepository<ReadingSystemCriterionDictionary> _readingCriterionDictionaryRepository,
IRepository<ReadingTrialCriterionDictionary> _readingTrialCriterionDictionaryRepository,
@@ -384,7 +385,20 @@ namespace IRaCIS.Core.Application.Service.RC
[HttpPost]
public async Task<IResponseOutput> AddOrUpdateReadingQuestionCriterionTrial(AddOrUpdateReadingQuestionCriterionTrialInDto indto)
{
if (indto.ReadingVersionEnum == null)
{
var dic = await _dictionarRepository.Where(x => x.Parent.Code == "ReadingVersion").ToListAsync();
var maxDic = dic.Select(x => int.Parse(x.Code)).Max();
indto.ReadingVersionEnum=(ReadingVersion)maxDic;
}
indto.ReadingTool = ReadingTool.Dicom;
indto.ReadingToolList = new List<string>()
{
"Length", "Bidirectional", "RectangleROI", "ArrowAnnotate", "CircleROI"
};
var entity = await _readingQuestionCriterionTrialRepository.InsertOrUpdateAsync(indto, true);
return ResponseOutput.Ok(entity.Id.ToString());
}
@@ -654,9 +668,15 @@ namespace IRaCIS.Core.Application.Service.RC
List<ReadingQuestionCriterionTrial> needAddCriterionList = await _readingQuestionCriterionSystemRepository.Where(x => !trialUsrSystemIds.Contains(x.Id) && x.IsEnable && !trialCriterionNames.Contains(x.CriterionName)).ProjectTo<ReadingQuestionCriterionTrial>(_mapper.ConfigurationProvider).ToListAsync();
List<ReadingQuestionTrial> needAddQuestionList = new List<ReadingQuestionTrial>();
var dic = await _dictionarRepository.Where(x => x.Parent.Code == "ReadingVersion").ToListAsync();
var maxDic = dic.Select(x => int.Parse(x.Code)).Max();
needAddCriterionList.ForEach(x =>
{
//x.IsEnable = false;
x.ReadingVersionEnum = (ReadingVersion)maxDic;
x.TrialId = trialId;
x.ReadingQuestionCriterionSystemId = x.Id;
x.Id = NewId.NextGuid();
@@ -22,6 +22,7 @@ namespace IRaCIS.Core.Application.Service
IRepository<ClinicalDataTrialSet> _clinicalDataTrialSetRepository,
IRepository<ClinicalDataSystemSet> _clinicalDataSystemSetRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<CriterionNidusSystem> _criterionNidusSystemRepository,
IRepository<SystemCriterionDictionaryCode> _systemCriterionDictionaryCodeRepository,
IReadingImageTaskService _iReadingImageTaskService,
IRepository<ReadingSystemCriterionDictionary> _readingSystemCriterionDictionaryRepository,
@@ -961,7 +962,12 @@ namespace IRaCIS.Core.Application.Service
{
question.RelevanceId = copyNewQuestionList.Where(y => x.RelevanceId == y.OriginalId).Select(y => y.Id).FirstOrDefault();
}
needAddDatas.Add(question);
if (question.GroupId != null)
{
question.GroupId = copyNewQuestionList.Where(y => x.GroupId == y.OriginalId).Select(y => y.Id).FirstOrDefault();
}
needAddDatas.Add(question);
};
await _readingQuestionSystemRepository.BatchDeleteNoTrackingAsync(x => x.ReadingQuestionCriterionSystemId == inDto.NewSystemCriterionId);
@@ -970,14 +976,24 @@ namespace IRaCIS.Core.Application.Service
#region
var newSystemTableQuestionList = await _readingTableQuestionSystemRepository.Where(x => x.SystemCriterionId == inDto.SourceSystemCriterionId)
.ProjectTo<ReadingTableQuestionSystemData>(_mapper.ConfigurationProvider).ToListAsync();
foreach (var question in newSystemTableQuestionList)
{
question.SystemCriterionId = inDto.NewSystemCriterionId;
question.Id = NewId.NextGuid();
}
var copeNewSystemTableQuestionList = newSystemTableQuestionList.Clone();
var needAddTableDatas = new List<ReadingTableQuestionSystemData>();
foreach (var x in newSystemTableQuestionList)
{
var tableQuestion = x.Clone();
tableQuestion.SystemCriterionId = inDto.NewSystemCriterionId;
tableQuestion.Id = NewId.NextGuid();
if (tableQuestion.ParentId != null)
tableQuestion.ReadingQuestionId = copyNewQuestionList.Where(y => x.ReadingQuestionId == y.OriginalId).Select(y => y.Id).FirstOrDefault();
if (tableQuestion.ParentId != null)
{
tableQuestion.ParentId = copeNewSystemTableQuestionList.Where(y => x.ParentId == y.OriginalId).Select(y => y.Id).FirstOrDefault();
}
@@ -989,7 +1005,11 @@ namespace IRaCIS.Core.Application.Service
{
tableQuestion.DependParentId = copeNewSystemTableQuestionList.Where(y => x.DependParentId == y.OriginalId).Select(y => y.Id).FirstOrDefault();
}
needAddTableDatas.Add(tableQuestion);
if (tableQuestion.ClassifyTableQuestionId != null)
{
tableQuestion.ClassifyTableQuestionId = copeNewSystemTableQuestionList.Where(y => x.ClassifyTableQuestionId == y.OriginalId).Select(y => y.Id).FirstOrDefault();
}
needAddTableDatas.Add(tableQuestion);
}
await _readingTableQuestionSystemRepository.BatchDeleteNoTrackingAsync(x => x.SystemCriterionId == inDto.NewSystemCriterionId);
await _readingTableQuestionSystemRepository.AddRangeAsync(needAddTableDatas);
@@ -1035,7 +1055,17 @@ namespace IRaCIS.Core.Application.Service
#endregion
#region criterionNidus
var criterionNidusSystems = await _criterionNidusSystemRepository.Where(x => x.CriterionId == inDto.SourceSystemCriterionId).ToListAsync();
criterionNidusSystems.ForEach(x =>
{
x.Id = NewId.NextGuid();
x.CriterionId = inDto.NewSystemCriterionId;
});
await _criterionNidusSystemRepository.BatchDeleteNoTrackingAsync(x => x.CriterionId == inDto.NewSystemCriterionId);
await _criterionNidusSystemRepository.AddRangeAsync(criterionNidusSystems);
#endregion
@@ -54,7 +54,7 @@ namespace IRaCIS.Core.Application.Service
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> BatchSubmitGlobalReadingInfo(BatchSubmitGlobalReadingInfo inDto)
{
await VerifyTaskIsSign(inDto.GlobalTaskId);
@@ -94,7 +94,7 @@ namespace IRaCIS.Core.Application.Service
})).ToList();
await _readingGlobalTaskInfoRepository.AddRangeAsync(answers);
await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.Id == inDto.GlobalTaskId, u => new VisitTask() { ReadingTaskState = ReadingTaskState.Reading });
await _visitTaskRepository.UpdatePartialFromEFAutoAsync(inDto.GlobalTaskId, u => new VisitTask() { ReadingTaskState = ReadingTaskState.Reading });
var result = await _readingGlobalTaskInfoRepository.SaveChangesAsync();
return ResponseOutput.Ok(result);
}
@@ -107,7 +107,7 @@ namespace IRaCIS.Core.Application.Service
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> SaveGlobalReadingInfo(SaveGlobalReadingInfoInDto inDto)
{
await VerifyTaskIsSign(inDto.GlobalTaskId);
@@ -301,7 +301,7 @@ namespace IRaCIS.Core.Application.Service
LimitEdit = y.LimitEdit,
MaxAnswerLength = y.MaxAnswerLength,
FileType = y.FileType,
Unit=y.Unit,
Unit = y.Unit,
QuestionGenre = y.QuestionGenre,
ShowOrder = y.ShowOrder,
DictionaryCode = y.DictionaryCode,
@@ -1,4 +1,5 @@
using DocumentFormat.OpenXml.Office2019.Excel.ThreadedComments;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Office2019.Excel.ThreadedComments;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper;
@@ -52,6 +53,7 @@ namespace IRaCIS.Core.Application.Service
IRepository<ReadModule> _readModuleRepository,
IRepository<DicomInstance> _dicomInstanceRepository,
IRepository<OrganInfo> _organInfoRepository,
IRepository<OrganTrialInfo> _organTrialInfoRepository,
IRepository<TrialDocument> _trialDocumentRepository,
ILuganoCalculateService _luganoCalculateService,
IRepository<ReadingCustomTag> _readingCustomTagRepository,
@@ -645,7 +647,7 @@ namespace IRaCIS.Core.Application.Service
IsCurrentTask = x.Id == inDto.VisitTaskId,
IsConvertedTask = x.IsConvertedTask,
IsFirstChangeTask = x.BeforeConvertedTaskId != null,
IsExistUnprocessedFeedback=x.UserFeedBackList.Any(y => y.State == 0),
IsExistUnprocessedFeedback = x.UserFeedBackList.Any(y => y.State == 0),
}).ToListAsync();
@@ -1647,14 +1649,7 @@ namespace IRaCIS.Core.Application.Service
QuestionMark.IsLymph,
};
tableAnswers.ForEach(x =>
{
x.Id = NewId.NextGuid();
x.RowIndex = newRowIndex;
x.VisitTaskId = inDto.VisitTaskId;
x.RowId = rowAnswer.Id;
x.Answer = needSaveMark.Contains(x.QuestionMark) ? x.Answer : string.Empty;
});
switch (taskInfo.TrialReadingCriterion.CriterionType)
{
@@ -1701,7 +1696,27 @@ namespace IRaCIS.Core.Application.Service
x.Answer = needSetNa.Contains(x.QuestionMark) ? "NA" : x.Answer;
});
break;
case CriterionType.mRECISTHCC:
needSaveMark = new List<QuestionMark?>()
{
QuestionMark.Organ,
QuestionMark.Location,
QuestionMark.Part,
QuestionMark.IsLymph,
QuestionMark.TypicalIntrahepaticLesion,
};
break;
}
tableAnswers.ForEach(x =>
{
x.Id = NewId.NextGuid();
x.RowIndex = newRowIndex;
x.VisitTaskId = inDto.VisitTaskId;
x.RowId = rowAnswer.Id;
x.Answer = needSaveMark.Contains(x.QuestionMark) ? x.Answer : string.Empty;
});
await _readingTableAnswerRowInfoRepository.AddAsync(rowAnswer);
await _readingTableQuestionAnswerRepository.AddRangeAsync(_mapper.Map<List<ReadingTableQuestionAnswer>>(tableAnswers));
await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.RowId, x => new ReadingTableAnswerRowInfo()
@@ -2245,6 +2260,7 @@ namespace IRaCIS.Core.Application.Service
}
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).Include(x => x.SourceSubjectVisit).FirstNotNullAsync();
inDto.BlindName = taskinfo.TaskBlindName;
var questionInfo = await _readingQuestionTrialRepository.Where(x => x.Id == inDto.QuestionId).FirstNotNullAsync();
switch (taskinfo.TrialReadingCriterion.CriterionType)
{
// 对于非靶病灶,如果状态选择为显著增大,请验证:
@@ -2391,9 +2407,56 @@ namespace IRaCIS.Core.Application.Service
break;
case CriterionType.mRECISTHCC:
//var orginInfo=await _organTrialInfoRepository.Where(x =>x.TrialCriterionId== taskinfo.TrialReadingCriterionId&& x.OrganInfoId == inDto.OrganInfoId).FirstOrDefaultAsync();
//if (orginInfo != null && orginInfo.TULOCEN == "Liver")
//{
// var otherorganCount=await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && x.Id!=inDto.Id&&x.OrganInfo.TULOCEN == "Liver").CountAsync();
// if (otherorganCount >=2)
// {
// throw new BusinessValidationFailedException(_localizer["ReadingImageTask_HCCOrganRepeat"]);
// }
//}
// 如果当前添加 是 非靶病灶 并且 典型肝内病灶为 是 时 如果 靶病灶的典型肝内病灶 为是的 数量<2 给提示
// 验证去掉
//if (questionInfo.LesionType == LesionType.NonTargetLesions)
//{
// // 非靶病灶
// var tablequestionList = await _readingTableQuestionTrialRepository.Where(x => x.TrialCriterionId == taskinfo.TrialReadingCriterionId && x.ReadingQuestionId == inDto.QuestionId).ToListAsync();
// // 判断表格问题是否为空
// var tableQuestion = tablequestionList.Where(x => x.QuestionMark == QuestionMark.TypicalIntrahepaticLesion).FirstOrDefault();
// if (tableQuestion != null)
// {
// if (inDto.AnswerList.Where(x => x.TableQuestionId == tableQuestion.Id).Select(x => x.Answer).FirstOrDefault().EqEnum(ReadingYesOrNo.Yes))
// {
// var yesString = ((int)(object)ReadingYesOrNo.Yes).ToString();
// var targetList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.ReadingQuestionTrial.LesionType == LesionType.TargetLesion
// && x.LesionAnswerList.Any(y => y.Answer == yesString && y.ReadingTableQuestionTrial.QuestionMark == QuestionMark.TypicalIntrahepaticLesion)
// ).ToListAsync();
// if (targetList.Count() < 2)
// {
// throw new BusinessValidationFailedException(_localizer["ReadingImageTask_PriorityTarget"]);
// }
// }
// }
//}
break;
}
var questionInfo = await _readingQuestionTrialRepository.Where(x => x.Id == inDto.QuestionId).FirstNotNullAsync();
var criterionId = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.TrialReadingCriterionId).FirstOrDefaultAsync();
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == criterionId).FirstNotNullAsync();
var tableQuestionIds = inDto.AnswerList.Select(x => x.TableQuestionId).ToList();
@@ -2971,7 +3034,9 @@ namespace IRaCIS.Core.Application.Service
var subjectTaskList = (await _visitTaskService.GetSubjectReadingIQueryable(new GetReadingIQueryableInDto()
{
TrialId = inDto.TrialId,
SubjectId = inDto.SubjectId,
TrialReadingCriterionId = trialReadingCriterionId!.Value,
SubjectCode = inDto.SubjectCode,
PageIndex = 1,
PageSize = 99999,
@@ -3054,24 +3119,45 @@ namespace IRaCIS.Core.Application.Service
&& x.TrialReadingCriterionId == trialReadingCriterionId
&& x.TaskState == TaskState.Effect)
.Where(x => !cacheSkipIds.Contains(x.Id));
var count = await query.CountAsync();
if (count == 0)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
//如果是随机阅片
Random random = new Random();
var skipcount = 0;
var minRandomOrder = query.Where(t => t.RandomOrder != null).Select(t => t.RandomOrder).MinOrDefault();
//以随机序号优先,阅片中优先先给IR
if (minRandomOrder != null)
{
query = query.Where(x => x.RandomOrder == minRandomOrder);
skipcount = 0;
}
else
{
//没有随机序号的,那么就按照阅片中最新的时间给
var maxReadingTime = query.MaxOrDefault(x => x.FirstReadingTime);
if (maxReadingTime != null)
{
query = query.Where(x => x.FirstReadingTime == maxReadingTime);
skipcount = 0;
}
}
var count = await query.CountAsync();
if (count >= 2)
{
skipcount = random.Next(0, count - 1);
}
var maxReadingTime = query.MaxOrDefault(x => x.FirstReadingTime);
if (maxReadingTime != null)
if (count == 0)
{
query = query.Where(x => x.FirstReadingTime == maxReadingTime);
skipcount = 0;
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
task = await query
.Select(x => new GetReadingTaskDto()
{
@@ -3092,6 +3178,14 @@ namespace IRaCIS.Core.Application.Service
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
else
{
//触发任务随机编号
await _downloadAndUploadService.SubejctRandomReadingTaskNameDeal(task.SubjectId, task.TrialReadingCriterionId);
task.TaskBlindName = await _visitTaskRepository.Where(t => t.Id == task.VisitTaskId).Select(t => t.TaskBlindName).FirstOrDefaultAsync() ?? "";
}
if (task.SubjectCode.IsNullOrEmpty())
{
@@ -3114,9 +3208,11 @@ namespace IRaCIS.Core.Application.Service
x.IsReadingShowPreviousResults,
x.IsReadingShowSubjectInfo,
x.DigitPlaces,
x.ReadingVersionEnum,
x.CriterionType,
x.IseCRFShowInDicomReading,
x.IsReadingTaskViewInOrder,
x.ReadingToolList,
}).FirstNotNullAsync();
task.IsReadingShowPreviousResults = criterionInfo.IsReadingShowPreviousResults;
@@ -3170,8 +3266,10 @@ namespace IRaCIS.Core.Application.Service
task.SubjectCode = blindSubjectCode.IsNullOrEmpty() ? task.SubjectCode : blindSubjectCode;
task.ExistsManual = (await GetManualList(new GetManualListInDto() { TrialId = visitTaskInfo.TrialId })).Count > 0;
task.ReadingTaskState = visitTaskInfo.ReadingTaskState;
task.IsShowStudyName= trialInfo.IsShowStudyName;
task.IsShowStudyName = trialInfo.IsShowStudyName;
task.IsBaseLine = isBaseLine;
task.ReadingVersionEnum = criterionInfo.ReadingVersionEnum;
task.ReadingToolList = criterionInfo.ReadingToolList;
task.IsExistUnprocessedFeedback = await _userFeedBackRepository.AnyAsync(x => x.VisitTaskId == task.VisitTaskId && x.State == 0);
// 添加默认答案
if (inDto.VisitTaskId == null && visitTaskInfo.ReadingTaskState != ReadingTaskState.HaveSigned)
@@ -3204,7 +3302,7 @@ namespace IRaCIS.Core.Application.Service
await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _readingTaskQuestionMarkRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _readingCustomTagRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _visitTaskRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
{
ReadingTaskState = ReadingTaskState.WaitReading
});
@@ -3284,7 +3382,7 @@ namespace IRaCIS.Core.Application.Service
[HttpPost]
public async Task<bool> ResetReadingRestTime(Guid? userRoleId)
{
var roleId = (userRoleId != null && userRoleId != Guid.Empty) ? (Guid) userRoleId : _userInfo.UserRoleId;
var roleId = (userRoleId != null && userRoleId != Guid.Empty) ? (Guid)userRoleId : _userInfo.UserRoleId;
//int readingMinute = 120; // 为60整数
int restMinute = 10; //
@@ -346,7 +346,7 @@ namespace IRaCIS.Core.Application.Service
var relatedVisitTaskIds = JsonConvert.SerializeObject(relatedVisitTaskIdList);
// 这里先保存 签名的时候 会统一创建关系
await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.Id == inDto.OncologyTaskId, u => new VisitTask()
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == inDto.OncologyTaskId, u => new VisitTask()
{
RelatedVisitTaskIds = relatedVisitTaskIds
});
@@ -1,6 +1,8 @@
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using MassTransit;
@@ -25,6 +27,7 @@ namespace IRaCIS.Core.Application.Service
IRepository<DicomInstance> _dicomInstanceRepository,
IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository,
IRepository<ReadingClinicalData> _readingClinicalDataRepository,
IReadingImageTaskService _readingImageTaskService,
IRepository<ReadingPeriodSet> _readingPeriodSetRepository,
IRepository<ReadModule> _readModuleRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService
{
@@ -64,7 +67,7 @@ namespace IRaCIS.Core.Application.Service
var resultlist = await visitQuery.WhereIf(finalVisitNum != null && finalVisitNum != 0, x => x.VisitNum <= finalVisitNum)
.Where(x => x.VisitNum > mixReadVisitNum|| x.VisitNum==thisVisitNum)
.Where(x => !x.IsBaseLine) // 排除基线
//.Where(x => !x.IsBaseLine) // 排除基线
.WhereIf(inDto.ReadingSetType == ReadingSetType.TumorReading, x => readModulequery.Where(y => y.SubjectVisitId == x.Id && y.TrialReadingCriterionId == inDto.TrialReadingCriterionId && y.ReadingSetType == ReadingSetType.ImageReading).Count() > 0)
.WhereIf(inDto.ReadingSetType == ReadingSetType.ImageReading, x => readModulequery.Where(y => y.Id != inDto.Id && y.SubjectVisitId == x.Id && y.TrialReadingCriterionId == inDto.TrialReadingCriterionId && y.ReadingSetType == ReadingSetType.ImageReading).Count() == 0)
.Select(x => new GetSubjectReadVisitsOutDto()
@@ -94,6 +97,29 @@ namespace IRaCIS.Core.Application.Service
throw new BusinessValidationFailedException(_localizer["ReadModule_CRCConfirmCanNtoEdit"]);
}
var readModule = await _readModuleRepository.Where(x => x.Id == inDto.Id).FirstNotNullAsync();
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == readModule.TrialReadingCriterionId).Select(x => new
{
x.ReadingType,
x.IsArbitrationReading,
x.IsReadingPeriod,
x.ArbitrationRule,
x.IsGlobalReading,
x.IsOncologyReading,
}).FirstNotNullAsync();
// 如果生成了 访视级别的阅片期裁判 不让修改
if (criterionInfo.IsArbitrationReading && criterionInfo.IsReadingPeriod && !criterionInfo.IsGlobalReading && criterionInfo.ArbitrationRule == ArbitrationRule.Reading)
{
if (await _visitTaskRepository.AnyAsync(x => x.SourceSubjectVisitId == readModule.SubjectVisitId && x.ReadingCategory == ReadingCategory.Judge))
{
//---当前阅片已生成裁判任务,操作失败。
throw new BusinessValidationFailedException(_localizer["ReadModule_JudgeTaskGenerated"]);
}
}
await _readModuleRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.Id, x => new ReadModule()
{
SubjectVisitId = inDto.SubjectVisitIdId,
@@ -499,8 +525,8 @@ namespace IRaCIS.Core.Application.Service
#region
var subjectVisitQuery = _subjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId).Where(t => t.IsLostVisit == false)
.Where(sv => sv.Subject.FinalSubjectVisitId == null ? true : sv.VisitNum < sv.Subject.LatestSubjectVisit.VisitNum).Select(sv => new ReadModuleView()
var subjectVisitQuery = _subjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId)/*.Where(t => t.IsLostVisit == false)*/
.Where(sv => sv.Subject.FinalSubjectVisitId == null ? true : sv.VisitNum <= sv.Subject.LatestSubjectVisit.VisitNum).Select(sv => new ReadModuleView()
{
Id = sv.Id,
CreateTime = sv.CreateTime,
@@ -885,7 +911,7 @@ namespace IRaCIS.Core.Application.Service
var resultlist = await visitQuery.WhereIf(finalVisitNum != 0, x => x.VisitNum <= finalVisitNum)
.WhereIf(inDto.ReadingSetType == ReadingSetType.TumorReading, x => readModulequery.Where(y => y.SubjectVisitId == x.Id && y.TrialReadingCriterionId == inDto.TrialReadingCriterionId && y.ReadingSetType == ReadingSetType.ImageReading).Count() > 0)
.Where(x => x.VisitNum > maxReadVisitNum)
.Where(x => !x.IsBaseLine) // 排除基线
//.Where(x => !x.IsBaseLine) // 排除基线
.Where(x => readModulequery.Where(y => y.SubjectVisitId == x.Id && y.TrialReadingCriterionId == inDto.TrialReadingCriterionId && y.ReadingSetType == inDto.ReadingSetType).Count() == 0).OrderBy(x => finalVisitNum)
.Select(x => new GetSubjectReadVisitsOutDto()
{
@@ -954,6 +980,8 @@ namespace IRaCIS.Core.Application.Service
&& !x.IsAnalysisCreate && x.TrialReadingCriterionId == dto.TrialReadingCriterionId
).ToListAsync();
// 生成全局阅片任务 具体是否需要生成在_visitTaskHelpeService里面有逻辑判断
foreach (var taskInfo in taskListInfo)
{
await _visitTaskHelpeService.AddTaskAsync(new GenerateTaskCommand()
@@ -974,6 +1002,13 @@ namespace IRaCIS.Core.Application.Service
}
});
}
// 生成裁判任务 是否需要生成函数里面有逻辑判断
if (taskListInfo.Count() > 0)
{
await _readingImageTaskService.TriggerJudgeQuestion(taskListInfo[0].Id);
}
break;
case ModuleTypeEnum.Oncology:
@@ -1066,6 +1101,15 @@ namespace IRaCIS.Core.Application.Service
var readModule = await _readModuleRepository.Where(x => x.Id == readModuleId).FirstNotNullAsync();
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == readModule.TrialReadingCriterionId).Select(x => new
{
x.ReadingType,
x.IsArbitrationReading,
x.IsReadingPeriod,
x.ArbitrationRule,
x.IsGlobalReading,
x.IsOncologyReading,
}).FirstNotNullAsync();
if (await _readingClinicalDataRepository.Where(t => t.ReadingId == readModuleId).AnyAsync(t => t.ReadingClinicalDataState == ReadingClinicalDataStatus.HaveSigned))
{
@@ -1094,6 +1138,17 @@ namespace IRaCIS.Core.Application.Service
throw new BusinessValidationFailedException(_localizer["ReadModule_TaskGenerated"]);
}
// 如果生成了 访视级别的阅片期裁判 不让删除
if (criterionInfo.IsArbitrationReading && criterionInfo.IsReadingPeriod && !criterionInfo.IsGlobalReading && criterionInfo.ArbitrationRule == ArbitrationRule.Reading)
{
if (await _visitTaskRepository.AnyAsync(x => x.SourceSubjectVisitId == readModule.SubjectVisitId && x.ReadingCategory == ReadingCategory.Judge))
{
//---当前阅片已生成裁判任务,操作失败。
throw new BusinessValidationFailedException(_localizer["ReadModule_JudgeTaskGenerated"]);
}
}
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => readModuleId == x.SouceReadModuleId, x => new VisitTask()
{
@@ -1,4 +1,5 @@
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
@@ -17,6 +18,7 @@ namespace IRaCIS.Core.Application.Service
IRepository<ReadModule> _readModuleRepository,
IRepository<VisitStage> _visitStageRepository,
IRepository<Trial> _trialRepository,
IReadingImageTaskService _readingImageTaskService,
IRepository<VisitTask> _visitTaskRepository,
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IVisitTaskHelpeService _visitTaskHelpeService,
@@ -165,6 +167,9 @@ namespace IRaCIS.Core.Application.Service
});
};
await _readModuleRepository.AddRangeAsync(readModules);
await _readModuleRepository.SaveChangesAsync();
// 判断是否要添加肿瘤学或者全局阅片任务
var subjectVisitIds = readModules.Select(x => x.SubjectVisitId).ToList();
@@ -201,6 +206,14 @@ namespace IRaCIS.Core.Application.Service
});
}
}
// 根据SourceSubjectVisitId 分组
var visitTaskid = taskInfoList.GroupBy(x => x.SourceSubjectVisitId).Select(x => x.Max(y => y.Id)).ToList();
// 生成裁判任务 是否需要生成函数里面有逻辑判断
foreach (var item in visitTaskid)
{
await _readingImageTaskService.TriggerJudgeQuestion(item);
}
break;
case ReadingSetType.TumorReading:
@@ -269,7 +282,7 @@ namespace IRaCIS.Core.Application.Service
break;
}
await _readModuleRepository.AddRangeAsync(readModules);
@@ -443,13 +456,13 @@ namespace IRaCIS.Core.Application.Service
List<GetReadingVisitListOutDto> result = await _visitStageRepository.Where(x => x.TrialId == inDto.TrialId)
.WhereIf(inDto.ReadingSetType == ReadingSetType.TumorReading, x => globalVisitNum.Contains(x.VisitNum))
.Where(x => x.VisitNum > 0)// 不能是基线
//.Where(x => x.VisitNum > 0)// 不能是基线
.Where(x => x.VisitNum == thisVisitNum || x.VisitNum >= maxVisitNum).Select(x => new GetReadingVisitListOutDto()
{
VisitName = x.VisitName,
VisitNum = x.VisitNum,
VisitStageId = x.Id,
}).ToListAsync();
}).OrderBy(x=>x.VisitNum).ToListAsync();
return result;
}
@@ -166,7 +166,8 @@ namespace IRaCIS.Core.Application.Service
CreateMap<CopyTableAnswerRowInfo, ReadingTableAnswerRowInfo>().ForMember(dest => dest.CreateUserRole, opt => opt.Ignore());
CreateMap<ReadingTableAnswerRowInfo, CopyTableAnswerRowInfo>()
.ForMember(d => d.OriginalId, u => u.MapFrom(s => s.Id));
.ForMember(d => d.OriginalId, u => u.MapFrom(s => s.Id))
.ForMember(d => d.LesionType, u => u.MapFrom(s => s.ReadingQuestionTrial.LesionType));
//.ForMember(dest => dest.Instance, opt => opt.Ignore())
//.ForMember(dest => dest.ReadingQuestionTrial, opt => opt.Ignore());
@@ -33,6 +33,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
{CriterionType.IVUS,typeof(IVUSCalculateService) },
{CriterionType.OCT,typeof(OCTCalculateService) },
{CriterionType.MRIPDFF,typeof(MRIPDFFCalculateService) },
{CriterionType.mRECISTHCC,typeof(MRECISTHCCCalculateService) },
};
File diff suppressed because it is too large Load Diff
@@ -729,6 +729,21 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
throw new BusinessValidationFailedException(_localizer["MRIPDFF_AllNeedToBeMark"]);
}
try
{
List<QuestionMark?> questionMarkList = new List<QuestionMark?>() { QuestionMark.FirstMeasurement, QuestionMark.SecondMeasurement, QuestionMark.ThirdMeasurement };
var measuredValueList = rowInfo.SelectMany(x => x.TableQuestionList).Where(x =>x.Answer.IsNotNullOrEmpty()&& questionMarkList.Contains(x.QuestionMark)).Select(x => decimal.Parse(x.Answer)).ToList();
if (measuredValueList.Any(x => x > 100))
{
throw new BusinessValidationFailedException(_localizer["MRIPDFF_MeasurementGT100"]);
}
}
catch (Exception)
{
throw new BusinessValidationFailedException(_localizer["MRIPDFF_MeasurementGT100"]);
}
var notableQuestionList = rowInfo.Where(x => x.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsMeasurable && x.Answer.EqEnum(YesOrNoOrNa.No))).ToList();
@@ -828,7 +828,13 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
#region
var needAddList = new List<ReadingTaskQuestionAnswer>();
if (inDto.ComputationTrigger != ComputationTrigger.PatchDataStatistics)
List< ComputationTrigger > computationTriggers = new List<ComputationTrigger>()
{
ComputationTrigger.PatchDataStatistics,
ComputationTrigger.SaveEICRFQuestions,
};
if (!computationTriggers.Contains(inDto.ComputationTrigger))
{
// 计算斑块统计数据
await this.CalculatePatchDataStatistics(inDto);
@@ -114,6 +114,19 @@ namespace IRaCIS.Core.Application.Contracts
{
}
public class ImageBackToBeDoneQuery : PageInput
{
}
public class ImageBackToBeDoneDto: TrialBaseInfoDto
{
public int? ToBeApprovalCount { get; set; }
}
public class ReviewerSelectToBeDoneDto : TrialBaseInfoDto
{
public bool IsUrgent { get; set; }
@@ -402,6 +415,8 @@ namespace IRaCIS.Core.Application.Contracts
public int? PM_ClinicalDataCount { get; set; }
public int? PM_ImageBackApprovalCount { get; set; }
#endregion
#region CRC
@@ -376,6 +376,13 @@ namespace IRaCIS.Core.Application.Contracts
public class GetTrialReadingInfoOutDto
{
public ReadingVersion ReadingVersionEnum { get; set; }
/// <summary>
/// 阅片工具
/// </summary>
public List<string> ReadingToolList { get; set; }
public string TrialModalitys { get; set; }
public bool IsImageFilter { get; set; }
@@ -901,6 +908,8 @@ namespace IRaCIS.Core.Application.Contracts
public class SetCriterionReadingInfoInDto
{
public List<string> ReadingToolList { get; set; } = new List<string>() { };
public bool IsImageFilter { get; set; }
public string CriterionModalitys { get; set; }
@@ -139,5 +139,16 @@ namespace IRaCIS.Core.Application.Contracts.DTO
}
public class TrialSelectUserBasicInfo
{
public Guid UserRoleId { get; set; }
public string FullName { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
}
@@ -261,11 +261,18 @@ namespace IRaCIS.Application.Contracts
#endregion
#region
public List<TrialObjectNameConfig> TrialObjectNameList { get; set; }
/// <summary>
/// 打开失访可读
/// </summary>
public bool IsOpenLostVistRead { get; set; } = false;
#region
public List<TrialObjectNameConfig> TrialObjectNameList { get; set; }
public CollectImagesType CollectImagesEnum { get; set; }
#endregion
public CollectImagesType CollectImagesEnum { get; set; }
}
public class TrialPacsInfo
@@ -16,6 +16,7 @@ namespace IRaCIS.Core.Application
IRepository<SystemDocument> _systemDocumentRepository,
IClinicalAnswerService _clinicalAnswerService,
IRepository<SystemNotice> _systemNoticeRepository,
IRepository<SubjectVisitImageBackRecord> _subjectVisitImageBackRecordReposiotry,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService
{
@@ -213,7 +214,7 @@ namespace IRaCIS.Core.Application
.Where(t => t.Trial.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
.Where(u => u.EnrollStatus == EnrollStatus.HasCommittedToCRO).CountAsync();
return ResponseOutput.Ok(result, new { ToBeApprovalCount = toBeApprovalCount }); ;
return ResponseOutput.Ok(result, new { ToBeApprovalCount = toBeApprovalCount });
}
@@ -259,6 +260,32 @@ namespace IRaCIS.Core.Application
return ResponseOutput.Ok(result, new { ToBeApprovalCount = all.Sum(x => x.ToBeApprovalCount) }); ;
}
[HttpPost]
public async Task<IResponseOutput<PageOutput<ImageBackToBeDoneDto>>> GetPMImageBackToBeDoneList(ImageBackToBeDoneQuery inQuery)
{
var query = _trialRepository.Where(t => t.TrialStatusStr == StaticData.TrialState.TrialOngoing)
.Where(t => t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
.Select(t => new ImageBackToBeDoneDto()
{
TrialId = t.Id,
ResearchProgramNo = t.ResearchProgramNo,
ExperimentName = t.ExperimentName,
TrialCode = t.TrialCode,
ToBeApprovalCount = t.SubjectVisitList.SelectMany(u => u.SubjectVisitImageBackRecordList.Where(t=>t.ImageBackState==ImageBackStateEnum.None)).Count()
}).Where(x => x.ToBeApprovalCount > 0);
var defalutSortArray = new string[] { nameof(ImageBackToBeDoneDto.ToBeApprovalCount) + " desc" };
var result = await query.ToPagedListAsync(inQuery, defalutSortArray);
return ResponseOutput.Ok(result);
}
#endregion
@@ -1223,6 +1250,14 @@ namespace IRaCIS.Core.Application
.Where(t => t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
.Where(t => t.ReadModuleList.Where(u => u.IsCRCConfirm && !u.IsPMConfirm).Count() > 0).CountAsync() : 0,
PM_ImageBackApprovalCount = isPM ? await _trialRepository.Where(t => t.TrialStatusStr == StaticData.TrialState.TrialOngoing)
.Where(t => t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
.Where(t=>t.SubjectVisitList.SelectMany(u=>u.SubjectVisitImageBackRecordList).Any(t=>t.ImageBackState==ImageBackStateEnum.None)).CountAsync():0,
//await _subjectVisitImageBackRecordReposiotry.Where(t => t.SubjectVisit.Trial.TrialStatusStr == StaticData.TrialState.TrialOngoing)
//.Where(t => t.SubjectVisit.Trial.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
//.CountAsync() : 0,
#endregion
#region CRC
@@ -1391,94 +1426,94 @@ namespace IRaCIS.Core.Application
var isIR = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer;
var query = _trialRepository.AsQueryable().IgnoreQueryFilters()
.WhereIf(inQuery.SponsorId != null, o => o.SponsorId == inQuery.SponsorId)
.WhereIf(!string.IsNullOrEmpty(inQuery.Code), o => o.TrialCode.Contains(inQuery.Code))
.WhereIf(!string.IsNullOrEmpty(inQuery.ResearchProgramNo), o => o.ResearchProgramNo.Contains(inQuery.ResearchProgramNo))
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.ExperimentName), o => o.ExperimentName.Contains(inQuery.ExperimentName))
.WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OP,
t => t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.IsDeleted == false
&& t.TrialUserRoleList.Any(t => t.UserId == _userInfo.UserRoleId && t.IsDeleted == false))
&& t.IsDeleted == false)
.WhereIf(inQuery.CriterionType != null, o => o.TrialReadingCriterionList.Any(t => t.CriterionType == inQuery.CriterionType && t.IsSigned && t.IsConfirm))
.WhereIf(!string.IsNullOrEmpty(inQuery.PM_EMail), o => o.TrialIdentityUserList.Any(t => t.IdentityUser.EMail.Contains(inQuery.PM_EMail)))
.Select(t => new TrialToBeDoneDto()
{
TrialId = t.Id,
ResearchProgramNo = t.ResearchProgramNo,
ExperimentName = t.ExperimentName,
TrialCode = t.TrialCode,
CreateTime = t.CreateTime,
Sponsor = _userInfo.IsEn_Us ? t.Sponsor.SponsorName : t.Sponsor.SponsorNameCN,
TrialStatusStr = t.TrialStatusStr,
var query = _trialRepository.AsQueryable().IgnoreQueryFilters()
.WhereIf(inQuery.SponsorId != null, o => o.SponsorId == inQuery.SponsorId)
.WhereIf(!string.IsNullOrEmpty(inQuery.Code), o => o.TrialCode.Contains(inQuery.Code))
.WhereIf(!string.IsNullOrEmpty(inQuery.ResearchProgramNo), o => o.ResearchProgramNo.Contains(inQuery.ResearchProgramNo))
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.ExperimentName), o => o.ExperimentName.Contains(inQuery.ExperimentName))
.WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OP,
t => t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.IsDeleted == false
&& t.TrialUserRoleList.Any(t => t.UserId == _userInfo.UserRoleId && t.IsDeleted == false))
&& t.IsDeleted == false)
.WhereIf(inQuery.CriterionType != null, o => o.TrialReadingCriterionList.Any(t => t.CriterionType == inQuery.CriterionType && t.IsSigned && t.IsConfirm))
.WhereIf(!string.IsNullOrEmpty(inQuery.PM_EMail), o => o.TrialIdentityUserList.Any(t => t.IdentityUser.EMail.Contains(inQuery.PM_EMail)))
.Select(t => new TrialToBeDoneDto()
{
TrialId = t.Id,
ResearchProgramNo = t.ResearchProgramNo,
ExperimentName = t.ExperimentName,
TrialCode = t.TrialCode,
CreateTime = t.CreateTime,
Sponsor = _userInfo.IsEn_Us ? t.Sponsor.SponsorName : t.Sponsor.SponsorNameCN,
TrialStatusStr = t.TrialStatusStr,
ExpetiedTaskCount = isPM ? t.VisitTaskList.Where(t => t.IsUrgent && t.IsAnalysisCreate==false && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze)).Count() : 0,
ExpetiedTaskCount = isPM ? t.VisitTaskList.Where(t => t.IsUrgent && t.IsAnalysisCreate == false && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze)).Count() : 0,
ReReadingApprovalCount = isPM ? t.VisitTaskReReadingList.Where(t => t.OriginalReReadingTask.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed).Count() : 0,
ReReadingApprovalCount = isPM ? t.VisitTaskReReadingList.Where(t => t.OriginalReReadingTask.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed).Count() : 0,
PendingReconciliationCount = isPM ? t.SubjectVisitList.Where(t => t.CheckState == CheckStateEnum.ToCheck).Count() : 0,
PendingReconciliationCount = isPM ? t.SubjectVisitList.Where(t => t.CheckState == CheckStateEnum.ToCheck).Count() : 0,
PendingResponseCount = isPM ? t.SubjectVisitList.Where(u => u.CheckState == CheckStateEnum.CVIng &&
u.CheckChallengeDialogList.OrderByDescending(t => t.CreateTime).First().UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Count() : 0,
PendingResponseCount = isPM ? t.SubjectVisitList.Where(u => u.CheckState == CheckStateEnum.CVIng &&
u.CheckChallengeDialogList.OrderByDescending(t => t.CreateTime).First().UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Count() : 0,
SPM_ReReadingApprovalCount = isSPMOrCPM ? t.VisitTaskReReadingList.Where(t => t.OriginalReReadingTask.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed).Count() : 0,
SPM_ReReadingApprovalCount = isSPMOrCPM ? t.VisitTaskReReadingList.Where(t => t.OriginalReReadingTask.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed).Count() : 0,
SPM_ReviewerSelectApprovalCount = isSPMOrCPM ? t.EnrollList.Where(u => u.EnrollStatus == EnrollStatus.HasCommittedToCRO).Count() : 0,
SPM_ReviewerSelectApprovalCount = isSPMOrCPM ? t.EnrollList.Where(u => u.EnrollStatus == EnrollStatus.HasCommittedToCRO).Count() : 0,
MIM_UrgentCount = isMIM ? t.TaskMedicalReviewList.Where(t => t.IsClosedDialog == false && t.VisitTask.TaskState == TaskState.Effect && t.IsInvalid == false && t.MedicalManagerUserId == _userInfo.UserRoleId)
.Where(u => u.VisitTask.IsUrgent &&
u.AuditState != MedicalReviewAuditState.HaveSigned).Count() : 0,
MIM_UrgentCount = isMIM ? t.TaskMedicalReviewList.Where(t => t.IsClosedDialog == false && t.VisitTask.TaskState == TaskState.Effect && t.IsInvalid == false && t.MedicalManagerUserId == _userInfo.UserRoleId)
.Where(u => u.VisitTask.IsUrgent &&
u.AuditState != MedicalReviewAuditState.HaveSigned).Count() : 0,
MIM_PendingResponseCount = isMIM ? t.TaskMedicalReviewList.Where(t => t.IsClosedDialog == false && t.VisitTask.TaskState == TaskState.Effect && t.IsInvalid == false && t.MedicalManagerUserId == _userInfo.UserRoleId)
.Where(u => u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IndependentReviewer && u.AuditState == MedicalReviewAuditState.Auditing).Count() : 0,
MIM_PendingResponseCount = isMIM ? t.TaskMedicalReviewList.Where(t => t.IsClosedDialog == false && t.VisitTask.TaskState == TaskState.Effect && t.IsInvalid == false && t.MedicalManagerUserId == _userInfo.UserRoleId)
.Where(u => u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IndependentReviewer && u.AuditState == MedicalReviewAuditState.Auditing).Count() : 0,
MIM_PendingReviewCount = isMIM ? t.TaskMedicalReviewList.Where(t => t.IsClosedDialog == false && t.VisitTask.TaskState == TaskState.Effect && t.IsInvalid == false && t.MedicalManagerUserId == _userInfo.UserRoleId)
.Where(u => u.AuditState != MedicalReviewAuditState.HaveSigned && u.LatestReplyUser.UserTypeEnum != UserTypeEnum.IndependentReviewer).Count() : 0,
MIM_PendingReviewCount = isMIM ? t.TaskMedicalReviewList.Where(t => t.IsClosedDialog == false && t.VisitTask.TaskState == TaskState.Effect && t.IsInvalid == false && t.MedicalManagerUserId == _userInfo.UserRoleId)
.Where(u => u.AuditState != MedicalReviewAuditState.HaveSigned && u.LatestReplyUser.UserTypeEnum != UserTypeEnum.IndependentReviewer).Count() : 0,
CRC_UrgentCount = isCRC ? t.SubjectVisitList.Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.UserRoleId) && t.IsUrgent).Count() : 0,
CRC_UrgentCount = isCRC ? t.SubjectVisitList.Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.UserRoleId) && t.IsUrgent).Count() : 0,
CRC_CheckQuestionCount = isCRC ? t.SubjectVisitList.Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.UserRoleId))
.Where(u => u.CheckState == CheckStateEnum.CVIng && u.CheckChallengeState == CheckChanllengeTypeEnum.PMWaitCRCReply).Count() : 0,
CRC_CheckQuestionCount = isCRC ? t.SubjectVisitList.Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.UserRoleId))
.Where(u => u.CheckState == CheckStateEnum.CVIng && u.CheckChallengeState == CheckChanllengeTypeEnum.PMWaitCRCReply).Count() : 0,
CRC_QCQuestionCount = isCRC ? t.SubjectVisitList.Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.UserRoleId)).SelectMany(c => c.QCChallengeList)
.Where(u => u.IsClosed == false && (u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IQC || u.LatestReplyUserId == null)).Count() : 0,
CRC_QCQuestionCount = isCRC ? t.SubjectVisitList.Where(c => c.TrialSite.CRCUserList.Any(u => u.UserId == _userInfo.UserRoleId)).SelectMany(c => c.QCChallengeList)
.Where(u => u.IsClosed == false && (u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IQC || u.LatestReplyUserId == null)).Count() : 0,
//待审核 审核中 加急的数量
IQC_UrgentCount = isIQC ? t.SubjectVisitList.Where(u => u.CurrentActionUserId == _userInfo.UserRoleId && t.QCProcessEnum != TrialQCProcess.NotAudit && t.IsUrgent).Count() : 0,
//待审核 审核中 加急的数量
IQC_UrgentCount = isIQC ? t.SubjectVisitList.Where(u => u.CurrentActionUserId == _userInfo.UserRoleId && t.QCProcessEnum != TrialQCProcess.NotAudit && t.IsUrgent).Count() : 0,
//审核未完成
IQC_AuditToBeDealedCount = isIQC ? t.SubjectVisitList.Where(u => u.CurrentActionUserId == _userInfo.UserRoleId && t.QCProcessEnum != TrialQCProcess.NotAudit).Count() : 0,
//审核未完成
IQC_AuditToBeDealedCount = isIQC ? t.SubjectVisitList.Where(u => u.CurrentActionUserId == _userInfo.UserRoleId && t.QCProcessEnum != TrialQCProcess.NotAudit).Count() : 0,
//质疑待处理
IQC_QuestionToBeDealedCount = isIQC ? t.SubjectVisitList.SelectMany(c => c.QCChallengeList)
.Where(u => u.CreateUserId == _userInfo.UserRoleId && u.IsClosed == false && u.LatestReplyUser.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Count() : 0,
//质疑待处理
IQC_QuestionToBeDealedCount = isIQC ? t.SubjectVisitList.SelectMany(c => c.QCChallengeList)
.Where(u => u.CreateUserId == _userInfo.UserRoleId && u.IsClosed == false && u.LatestReplyUser.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Count() : 0,
//待领取
IQC_ToBeClaimedCount = isIQC ? t.SubjectVisitList.Where(t => t.SubmitState == SubmitStateEnum.Submitted && t.AuditState != AuditStateEnum.QCPassed)
.Where(u => u.CurrentActionUserId == null && (u.PreliminaryAuditUserId == null || (u.PreliminaryAuditUserId != _userInfo.UserRoleId && u.ReviewAuditUserId == null))).Count() : 0,
//待领取
IQC_ToBeClaimedCount = isIQC ? t.SubjectVisitList.Where(t => t.SubmitState == SubmitStateEnum.Submitted && t.AuditState != AuditStateEnum.QCPassed)
.Where(u => u.CurrentActionUserId == null && (u.PreliminaryAuditUserId == null || (u.PreliminaryAuditUserId != _userInfo.UserRoleId && u.ReviewAuditUserId == null))).Count() : 0,
IR_ReadingCriterionList = isIR ? t.TrialReadingCriterionList.Where(t => t.IsConfirm && t.IsSigned).OrderBy(t => t.CriterionName).Select(t => t.CriterionName).ToList() : null,
IR_ReadingCriterionList = isIR ? t.TrialReadingCriterionList.Where(t => t.IsConfirm && t.IsSigned).OrderBy(t => t.CriterionName).Select(t => t.CriterionName).ToList() : null,
IR_PMEmailList = isIR ? t.TrialUserRoleList.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM).OrderBy(t => t.UserRole.IdentityUser.EMail).Select(t => t.UserRole.IdentityUser.EMail).ToList() : null,
IR_PMEmailList = isIR ? t.TrialUserRoleList.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM).OrderBy(t => t.UserRole.IdentityUser.EMail).Select(t => t.UserRole.IdentityUser.EMail).ToList() : null,
IR_TotalReadCount = isIR ? t.VisitTaskList.Where(t => t.DoctorUserId == _userInfo.UserRoleId && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned).Count() : 0,
IR_TotalReadCount = isIR ? t.VisitTaskList.Where(t => t.DoctorUserId == _userInfo.UserRoleId && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned).Count() : 0,
IR_UnReadCount = isIR ? t.VisitTaskList
.Where(c => c.DoctorUserId == _userInfo.UserRoleId && c.ReadingTaskState != ReadingTaskState.HaveSigned && c.TaskState == TaskState.Effect && c.TrialReadingCriterion.IsSigned)
// 前序 不存在 未一致性核查未通过的
.Where(t => !t.Subject.SubjectVisitList.Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum > sv.VisitNum))
//前序 不存在 未生成任务的访视
.Where(t => t.TrialReadingCriterion.IsAutoCreate == false ? !t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(d => d.TrialReadingCriterionId == t.TrialReadingCriterionId).Any(f => f.IsGeneratedTask == false && t.VisitTaskNum > f.SubjectVisit.VisitNum) : true)
IR_UnReadCount = isIR ? t.VisitTaskList
.Where(c => c.DoctorUserId == _userInfo.UserRoleId && c.ReadingTaskState != ReadingTaskState.HaveSigned && c.TaskState == TaskState.Effect && c.TrialReadingCriterion.IsSigned)
// 前序 不存在 未一致性核查未通过的
.Where(t => !t.Subject.SubjectVisitList.Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum > sv.VisitNum))
//前序 不存在 未生成任务的访视
.Where(t => t.TrialReadingCriterion.IsAutoCreate == false ? !t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(d => d.TrialReadingCriterionId == t.TrialReadingCriterionId).Any(f => f.IsGeneratedTask == false && t.VisitTaskNum > f.SubjectVisit.VisitNum) : true)
.Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)).Count() : 0,
.Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)).Count() : 0,
IR_UrgentCount = isIR ? t.VisitTaskList.Where(t => t.SourceSubjectVisit.IsUrgent).Count() : 0,
IR_UrgentCount = isIR ? t.VisitTaskList.Where(t => t.SourceSubjectVisit.IsUrgent).Count() : 0,
});
});
@@ -6,6 +6,7 @@ using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure;
@@ -41,6 +42,7 @@ namespace IRaCIS.Core.Application
IRepository<SystemBasicData> _systemBasicDataRepository,
IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<Enroll> _enrollRepository,
IRepository<TrialQCQuestionAnswer> _qcQuestionAnswerRepository,
IRepository<TrialStateChange> _trialStateChangeRepository,
IRepository<ReadingTableQuestionTrial> _readingTableQuestionTrialRepository,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, ITrialConfigService
@@ -562,6 +564,7 @@ namespace IRaCIS.Core.Application
await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
{
ReadingToolList = inDto.ReadingToolList,
IsImageFilter = inDto.IsImageFilter,
ImageDownloadEnum = inDto.ImageDownloadEnum,
ImageUploadEnum = inDto.ImageUploadEnum,
@@ -836,9 +839,46 @@ namespace IRaCIS.Core.Application
{
await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialUrgentConfirmed = true });
}
else
else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialQCQuestionConfirmUpdate).ToString())
{
var trialConfirmTime = _trialRepository.Where(t => t.Id == signConfirmDTO.TrialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
if (signConfirmDTO.SignCode == ((int)SignEnum.TrialQCQuestionConfirm).ToString())
if (trialConfirmTime != null)
{
//删除复审中间临时数据
await _qcQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => t.SubjectVisit.TrialId == signConfirmDTO.TrialId && t.SubjectVisit.SecondReviewState == SecondReviewState.WaitAudit
&& t.CurrentQCEnum == CurrentQC.SecondReview && t.UpdateTime > trialConfirmTime);
}
await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { QCQuestionConfirmedTime = null, QCQuestionConfirmedUserId = null, IsQCQuestionConfirmed = false });
}
else if (signConfirmDTO.SignCode == ((int)SignEnum.SecondReviewConfirm).ToString())
{
var trialConfirmTime = _trialRepository.Where(t => t.Id == signConfirmDTO.TrialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
if (trialConfirmTime != null)
{
//删除复审中间临时数据--没重置,一直点生成复核任务
await _qcQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => t.SubjectVisit.TrialId == signConfirmDTO.TrialId && t.SubjectVisit.SecondReviewState == SecondReviewState.WaitAudit
&& t.CurrentQCEnum == CurrentQC.SecondReview && t.UpdateTime > trialConfirmTime);
//删除质控中 临时保存的问题答案 (因为添加那里只会新增 和全部更新,如果不处理,那么有新增,也有更新,稽查那里也会有问题)
await _qcQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => t.SubjectVisit.TrialId == signConfirmDTO.TrialId && t.SubjectVisit.AuditState == AuditStateEnum.InPrimaryQC
&& t.CurrentQCEnum == CurrentQC.First);
await _qcQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => t.SubjectVisit.TrialId == signConfirmDTO.TrialId && t.SubjectVisit.AuditState == AuditStateEnum.InSecondaryQC
&& t.CurrentQCEnum == CurrentQC.Second);
//重复二次复核签名
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.TrialId == signConfirmDTO.TrialId && t.AuditState == AuditStateEnum.QCPassed
&& !t.TrialQCQuestionAnswerList.Any(t => t.SecondReviewTime == trialConfirmTime), u => new SubjectVisit() { SecondReviewState = SecondReviewState.WaitAudit });
}
}
else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialQCQuestionConfirm).ToString())
{
var trialConfig = (await _trialRepository
@@ -878,14 +918,14 @@ namespace IRaCIS.Core.Application
throw new BusinessValidationFailedException(_localizer["TrialConfig_AuditQuestionConfirmed"]);
}
await _trialQCQuestionRepository.UpdatePartialFromQueryAsync(t => t.TrialId == signConfirmDTO.TrialId, x => new TrialQCQuestion
await _trialQCQuestionRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == signConfirmDTO.TrialId, x => new TrialQCQuestion
{
IsConfirm = true
});
await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { QCQuestionConfirmedTime = DateTime.Now, QCQuestionConfirmedUserId = _userInfo.UserRoleId, IsQCQuestionConfirmed = true });
await _trialRepository.SaveChangesAsync();
}
await _trialRepository.SaveChangesAsync();
return ResponseOutput.Ok();
@@ -1310,7 +1350,7 @@ namespace IRaCIS.Core.Application
/// <returns></returns>
public async Task<IResponseOutput<List<TrialBodyPartView>>> GetTrialBodyPartList(Guid trialId)
{
var list = await _trialRepository.Where(t => t.Id == trialId).SelectMany(t => t.TrialBodyPartList).Select(t => new TrialBodyPartView() { Code = t.Code, Name = _userInfo.IsEn_Us ? t.Name : t.NameCN, Id = t.Id, IsHandAdd = t.IsHandAdd }).OrderBy(t=>t.Name).ToListAsync();
var list = await _trialRepository.Where(t => t.Id == trialId).SelectMany(t => t.TrialBodyPartList).Select(t => new TrialBodyPartView() { Code = t.Code, Name = _userInfo.IsEn_Us ? t.Name : t.NameCN, Id = t.Id, IsHandAdd = t.IsHandAdd }).OrderBy(t => t.Name).ToListAsync();
return ResponseOutput.Ok(list);
}
@@ -1393,7 +1433,7 @@ namespace IRaCIS.Core.Application
[HttpPost]
public async Task<IResponseOutput> UpdateTrialStudyNameList(UpdateTrialStudyNameListInDto inDto)
{
var trial = await _trialRepository.FirstOrDefaultAsync(x => x.Id == inDto.TrialId);
@@ -6,9 +6,11 @@ using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure.Extention;
using MassTransit.Serialization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Storage.Json;
using NPOI.SS.Formula.Functions;
using System;
namespace IRaCIS.Core.Application.Service
@@ -56,8 +58,8 @@ namespace IRaCIS.Core.Application.Service
IsDeleted = t.IsDeleted,
UserTypeId = t.UserRole.UserTypeRole.Id,
UserTypeShortName = t.UserRole.UserTypeRole.UserTypeShortName,
CreateTime=t.CreateTime,
UpdateTime=t.UpdateTime,
CreateTime = t.CreateTime,
UpdateTime = t.UpdateTime,
}).ToList(),
}).ToPagedListAsync(inQuery);
@@ -315,7 +317,29 @@ namespace IRaCIS.Core.Application.Service
}
public async Task<List<TrialSelectUserBasicInfo>> GetTrialUserRoleList(Guid trialId, Guid? subjectVisitId, UserTypeEnum? userTypeEnum)
{
var isSeconReview = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).AnyAsync(t => t.SecondReviewState == SecondReviewState.WaitAudit);
//复审指派需要过滤初审的人
var firstUserId = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => t.PreliminaryAuditUserId).FirstOrDefaultAsync();
var list = await _trialIdentityUserRepository.Where(t => t.TrialId == trialId)
.SelectMany(t => t.TrialUserRoleList)
.WhereIf(userTypeEnum != null, t => t.UserRole.UserTypeEnum == userTypeEnum)
.Where(t => t.UserRole.Id != _userInfo.UserRoleId)//iQC 指派过滤自己
.WhereIf(firstUserId != null && isSeconReview == false, t => t.UserRole.Id != firstUserId)//iQC 过滤初审的人,复核不过滤
.Select(t => new TrialSelectUserBasicInfo()
{
FullName = t.TrialUser.IdentityUser.FullName,
UserRoleId = t.UserRole.Id,
UserName = t.TrialUser.IdentityUser.UserName,
Phone = t.TrialUser.IdentityUser.Phone,
Email = t.TrialUser.IdentityUser.EMail
})
.ToListAsync();
return list;
}
}
}
@@ -13,6 +13,7 @@ using Microsoft.Extensions.Options;
using NPOI.SS.Formula.Functions;
using Panda.DynamicWebApi.Attributes;
using ZiggyCreatures.Caching.Fusion;
using static IRaCIS.Core.Domain.Share.StaticData;
namespace IRaCIS.Core.Application.Service
{
@@ -105,11 +106,43 @@ namespace IRaCIS.Core.Application.Service
//过滤废除的项目
public async Task<List<TrialSelectDTO>> GetTrialSelect()
{
// SuperAdmin Admin OP
List<int> sap = new List<int>() { (int)UserTypeEnum.SuperAdmin, (int)UserTypeEnum.Admin, (int)UserTypeEnum.OP };
// pm
List<int> pm = new List<int>() { (int)UserTypeEnum.ProjectManager };
// QA EA
List<int> qAEq= new List<int>() { (int)UserTypeEnum.QA, (int)UserTypeEnum.EA };
List<int> other = new List<int>() { };
other.AddRange(sap);
other.AddRange(pm);
other.AddRange(qAEq);
List<string> trialState = new List<string>() { StaticData.TrialState.TrialOngoing, StaticData.TrialState.TrialCompleted, StaticData.TrialState.TrialStopped };
return await _trialRepository.AsQueryable()
.WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OP,
t => t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)) && t.IsDeleted == false)
.Where(t=>t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId))
&& (t.TrialStatusStr != StaticData.TrialState.TrialStopped || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager))
//SuperAdmin Admin OP
.WhereIf(sap.Contains(_userInfo.UserTypeEnumInt),x=> trialState.Contains(x.TrialStatusStr))
// pm
.WhereIf(pm.Contains(_userInfo.UserTypeEnumInt),t=> t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.IsDeleted == false
&& t.TrialUserRoleList.Any(t => t.UserId == _userInfo.UserRoleId && t.IsDeleted == false))
&& t.IsDeleted == false)
// QA EA
.WhereIf(qAEq.Contains(_userInfo.UserTypeEnumInt), t => t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.IsDeleted == false
&& t.TrialUserRoleList.Any(t => t.UserId == _userInfo.UserRoleId && t.IsDeleted == false))
&& t.IsDeleted == false && trialState.Contains(t.TrialStatusStr))
// other
.WhereIf(!other.Contains(_userInfo.UserTypeEnumInt), t => t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.IsDeleted == false
&& t.TrialUserRoleList.Any(t => t.UserId == _userInfo.UserRoleId && t.IsDeleted == false))
&& t.IsDeleted == false&& t.TrialStatusStr == StaticData.TrialState.TrialOngoing)
.ProjectTo<TrialSelectDTO>(_mapper.ConfigurationProvider).ToListAsync();
}
@@ -149,8 +149,8 @@ namespace IRaCIS.Core.Application.Services
public async Task<List<TrialSiteSelect>> 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 })
.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()
.OrderBy(x=>x.SiteName)
.ToList();
@@ -42,7 +42,7 @@ namespace IRaCIS.Core.Application.Service
var instanceList = await _instanceRepository.Where(s => s.StudyId == scpStudyId).OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber)
.ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime)
.Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber }).ToListAsync();//.GroupBy(u => u.SeriesId);
.Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber,t.FileSize }).ToListAsync();//.GroupBy(u => u.SeriesId);
foreach (var series in seriesList)
{
@@ -55,6 +55,7 @@ namespace IRaCIS.Core.Application.Service
//HtmlPath = string.Empty,
Path = k.Path,
InstanceNumber = k.InstanceNumber,
FileSize=k.FileSize,
}).ToList();
}
@@ -233,7 +233,7 @@ namespace IRaCIS.Core.Application.Services
var studyList = await _dicomStudyRepository.Where(t => t.TrialId == trialId && t.SubjectVisitId == sujectVisitId).IgnoreQueryFilters()
.Where(t => isImageFilter ? ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|") : true)
.WhereIf(isReading == 1 || isQCFinished, s=> s.IsDeleted == false)
.WhereIf(isReading == 1 || isQCFinished, s => s.IsDeleted == false)
.Select(k => new VisitStudyDTO()
{
InstanceCount = k.InstanceCount,
@@ -248,7 +248,7 @@ namespace IRaCIS.Core.Application.Services
var instanceList = await _dicomInstanceRepository.Where(t => studyIds.Contains(t.StudyId)).IgnoreQueryFilters()
.WhereIf(isReading == 1, s => s.IsReading && s.IsDeleted == false)
.WhereIf(isQCFinished, t => t.IsDeleted == false)
.Select(t => new { t.SeriesId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.HtmlPath, t.IsReading, t.IsDeleted }).ToListAsync();
.Select(t => new { t.SeriesId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.HtmlPath, t.IsReading, t.IsDeleted, t.FileSize }).ToListAsync();
foreach (var t in studyList)
{
@@ -272,6 +272,7 @@ namespace IRaCIS.Core.Application.Services
InstanceNumber = k.InstanceNumber,
IsReading = k.IsReading,
IsDeleted = k.IsDeleted,
FileSize = k.FileSize,
}).ToList();
series.InstanceCount = series.InstanceInfoList.Count();
@@ -303,7 +304,7 @@ namespace IRaCIS.Core.Application.Services
DicomSeriesDTO series = await _dicomSeriesRepository.Where(s => s.Id == inDto.SeriesId).ProjectTo<DicomSeriesDTO>(_mapper.ConfigurationProvider).FirstNotNullAsync();
var instanceList = await _dicomInstanceRepository.Where(t => t.SeriesId == inDto.SeriesId)
.Select(t => new { t.SeriesId, t.StudyId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath, t.SliceLocation }).ToListAsync();
.Select(t => new { t.SeriesId, t.StudyId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath, t.SliceLocation, t.FileSize }).ToListAsync();
@@ -315,6 +316,7 @@ namespace IRaCIS.Core.Application.Services
HtmlPath = k.HtmlPath,
Path = k.Path,
InstanceNumber = k.InstanceNumber,
FileSize = k.FileSize
}).ToList();
@@ -391,7 +393,7 @@ namespace IRaCIS.Core.Application.Services
var seriesIds = ctseriesIds.Union(ptseriesIds).ToList(); //并集
var instanceList = await _dicomInstanceRepository.Where(t => seriesIds.Contains(t.SeriesId))
.Select(t => new { t.SeriesId, t.StudyId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath }).ToListAsync();
.Select(t => new { t.SeriesId, t.StudyId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath, t.FileSize }).ToListAsync();
var studyIds = instanceList.Select(x => x.StudyId).Distinct().ToList();
@@ -422,7 +424,7 @@ namespace IRaCIS.Core.Application.Services
HtmlPath = k.HtmlPath,
Path = k.Path,
InstanceNumber = k.InstanceNumber,
FileSize = k.FileSize
}).ToList();
@@ -506,7 +508,7 @@ namespace IRaCIS.Core.Application.Services
.Select(k => new VisitStudyDTO()
{
InstanceCount = k.InstanceCount,
StudyName=k.StudyName,
StudyName = k.StudyName,
Modalities = k.Modalities,
//SeriesCount = k.SeriesCount,
StudyCode = k.StudyCode,
@@ -516,7 +518,7 @@ namespace IRaCIS.Core.Application.Services
var studyIds = dicomStudyList.Select(t => t.StudyId).ToList();
var instanceList = await _dicomInstanceRepository.Where(t => studyIds.Contains(t.StudyId) && t.IsReading)
.Select(t => new { t.SeriesId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath, t.IsReading }).ToListAsync();
.Select(t => new { t.SeriesId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath, t.IsReading, t.FileSize }).ToListAsync();
List<DicomSeriesDTO> seriesLists = await _dicomSeriesRepository.Where(s => studyIds.Contains(s.StudyId))
.WhereIf(isManualGenerate == false, t => t.IsReading)
@@ -537,6 +539,7 @@ namespace IRaCIS.Core.Application.Services
HtmlPath = k.HtmlPath,
Path = k.Path,
InstanceNumber = k.InstanceNumber,
FileSize = k.FileSize
}).ToList();
@@ -613,7 +616,7 @@ namespace IRaCIS.Core.Application.Services
var markInstanceIdList = rowInfoList.Where(y => y.InstanceId != null).OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex).Select(y => y.InstanceId!.Value).Distinct().ToList();
item.InstanceInfoList = await _dicomInstanceRepository.Where(t => markInstanceIdList.Contains(t.Id)).Select(k =>
item.InstanceInfoList = await _dicomInstanceRepository.Where(t => markInstanceIdList.Contains(t.Id)).OrderBy(s => s.DicomSerie.SeriesNumber).ThenBy(s => s.DicomSerie.SeriesTime).ThenBy(x => x.InstanceTime).Select(k =>
new InstanceBasicInfo()
{
Id = k.Id,
@@ -623,6 +626,7 @@ namespace IRaCIS.Core.Application.Services
InstanceNumber = k.InstanceNumber,
StudyId = k.StudyId,
SeriesId = k.SeriesId,
FileSize = k.FileSize
}).ToListAsync();
item.InstanceInfoList.ForEach(x =>
@@ -707,7 +711,7 @@ namespace IRaCIS.Core.Application.Services
{
var nodicom = noDicomList.Where(x => x.Id == item.StudyId).First();
var instanceCount = await _noneDicomStudyFileRepository.Where(t=>t.IsReading)
var instanceCount = await _noneDicomStudyFileRepository.Where(t => t.IsReading)
.WhereIf(isExistTaskNoneDicomFile, x => x.OriginNoneDicomStudyId == item.StudyId)
.WhereIf(isExistTaskNoneDicomFile == false, x => x.NoneDicomStudyId == item.StudyId).CountAsync();
@@ -435,7 +435,7 @@ namespace IRaCIS.Core.Application.Service
//变更某一访视计划Item 受试者访视相关字段
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialId && t.VisitStageId == changedItem.Id, k => new SubjectVisit()
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.TrialId == trialId && t.VisitStageId == changedItem.Id, k => new SubjectVisit()
{
IsBaseLine = changedItem.IsBaseLine,
VisitName = changedItem.VisitName,

Some files were not shown because too many files have changed in this diff Show More