diff --git a/api/src/Feature.Notifications/ListRecipients/Endpoint.cs b/api/src/Feature.Notifications/ListRecipients/Endpoint.cs index 8a64462d6..14ee0d0ed 100644 --- a/api/src/Feature.Notifications/ListRecipients/Endpoint.cs +++ b/api/src/Feature.Notifications/ListRecipients/Endpoint.cs @@ -20,289 +20,567 @@ public override void Configure() public override async Task> ExecuteAsync(Request req, CancellationToken ct) { - var sql = """ - WITH "ObserverPSI" AS - (SELECT f."Id" AS "FormId", - f."FormType" AS "FormType", - mo."ObserverId" AS "ObserverId", - mo."Id" AS "MonitoringObserverId", - fs."PollingStationId" AS "PollingStationId", - fs."FollowUpStatus" AS "FollowUpStatus", - COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", - fs."IsCompleted" AS "IsCompleted", - CAST(NULL AS bigint) AS "MediaFilesCount", - CAST(NULL AS bigint) AS "NotesCount", - (CASE - WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'All' - WHEN fs."NumberOfQuestionsAnswered" > 0 THEN 'Some' - WHEN fs."NumberOfQuestionsAnswered" = 0 THEN 'None' - END) "QuestionsAnswered", - (CASE - WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE - ELSE FALSE - END) "HasFlaggedAnswers", - CAST(NULL AS UUID) AS "QuickReportId", - NULL AS "IncidentCategory", - NULL AS "QuickReportFollowUpStatus" - FROM "MonitoringObservers" MO - INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" - INNER JOIN "PollingStationInformation" FS ON MO."Id" = FS."MonitoringObserverId" - INNER JOIN "PollingStationInformationForms" F ON f."ElectionRoundId" = @electionRoundId - WHERE MN."ElectionRoundId" = @electionRoundId - AND MN."NgoId" = @ngoId), - "ObserversFormSubmissions" AS - (SELECT f."Id" AS "FormId", - f."FormType" AS "FormType", - mo."ObserverId" AS "ObserverId", - mo."Id" AS "MonitoringObserverId", - fs."PollingStationId" AS "PollingStationId", - fs."FollowUpStatus" AS "FollowUpStatus", - COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", - fs."IsCompleted" AS "IsCompleted", - - (SELECT COUNT(*) - FROM "Attachments" A - WHERE A."FormId" = fs."FormId" - AND a."MonitoringObserverId" = fs."MonitoringObserverId" - AND fs."PollingStationId" = A."PollingStationId" - AND A."IsDeleted" = FALSE - AND A."IsCompleted" = TRUE) AS "MediaFilesCount", - - (SELECT COUNT(*) - FROM "Notes" N - WHERE N."FormId" = fs."FormId" - AND N."MonitoringObserverId" = fs."MonitoringObserverId" - AND fs."PollingStationId" = N."PollingStationId") AS "NotesCount", - (CASE - WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'All' - WHEN fs."NumberOfQuestionsAnswered" > 0 THEN 'Some' - WHEN fs."NumberOfQuestionsAnswered" = 0 THEN 'None' - END) "QuestionsAnswered", - (CASE - WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE - ELSE FALSE - END) "HasFlaggedAnswers", - CAST(NULL AS UUID) AS "QuickReportId", - NULL AS "IncidentCategory", - NULL AS "QuickReportFollowUpStatus" - FROM "MonitoringObservers" MO - INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" - INNER JOIN "FormSubmissions" FS ON MO."Id" = FS."MonitoringObserverId" - INNER JOIN "Forms" F ON FS."FormId" = F."Id" - WHERE MN."ElectionRoundId" = @electionRoundId - AND MN."NgoId" = @ngoId), - "ObserversQuickReports" AS - (SELECT CAST(NULL AS UUID) AS "FormId", - NULL AS "FormType", - mo."ObserverId" AS "ObserverId", - mo."Id" AS "MonitoringObserverId", - qr."PollingStationId" AS "PollingStationId", - NULL AS "FollowUpStatus", - COALESCE(qr."LastModifiedOn", qr."CreatedOn") AS "LastModifiedOn", - CAST(NULL AS boolean) AS "IsCompleted", - CAST(NULL AS bigint) AS "MediaFilesCount", - CAST(NULL AS bigint) AS "NotesCount", - NULL AS "QuestionsAnswered", - CAST(NULL AS boolean) AS "HasFlaggedAnswers", - qr."Id" AS "QuickReportId", - qr."IncidentCategory" AS "IncidentCategory", - qr."FollowUpStatus" AS "QuickReportFollowUpStatus" - FROM "MonitoringObservers" MO - INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" - INNER JOIN "QuickReports" QR ON MO."Id" = QR."MonitoringObserverId" - WHERE MN."ElectionRoundId" = @electionRoundId - AND MN."NgoId" = @ngoId), - "ObserversActivity" AS - (SELECT * - FROM "ObserversFormSubmissions" - UNION ALL SELECT * - FROM "ObserversQuickReports" - UNION ALL SELECT * - FROM "ObserverPSI") - SELECT COUNT(DISTINCT OA."ObserverId") COUNT - FROM "ObserversActivity" OA - INNER JOIN "MonitoringObservers" mo ON mo."Id" = OA."MonitoringObserverId" - INNER JOIN "AspNetUsers" U ON U."Id" = OA."ObserverId" - LEFT JOIN "PollingStations" ps ON OA."PollingStationId" = ps."Id" - WHERE (@searchText IS NULL - OR @searchText = '' - OR U."DisplayName" ILIKE @searchText - OR U."Email" ILIKE @searchText - OR u."PhoneNumber" ILIKE @searchText - OR mo."Id"::text ILIKE @searchText) - AND (@tagsFilter IS NULL OR cardinality(@tagsFilter) = 0 OR mo."Tags" && @tagsFilter) - AND (@monitoringObserverStatus IS NULL OR mo."Status" = @monitoringObserverStatus) - AND (@formType IS NULL OR OA."FormType" = @formType) - AND (@level1 IS NULL OR ps."Level1" = @level1) - AND (@level2 IS NULL OR ps."Level2" = @level2) - AND (@level3 IS NULL OR ps."Level3" = @level3) - AND (@level4 IS NULL OR ps."Level4" = @level4) - AND (@level5 IS NULL OR ps."Level5" = @level5) - AND (@pollingStationNumber IS NULL OR ps."Number" = @pollingStationNumber) - AND (@hasFlaggedAnswers IS NULL OR OA."HasFlaggedAnswers" = @hasFlaggedAnswers) - AND (@submissionsFollowUpStatus IS NULL OR OA."FollowUpStatus" = @submissionsFollowUpStatus) - AND (@formId IS NULL OR OA."FormId" = @formId) - AND (@questionsAnswered IS NULL OR OA."QuestionsAnswered" = @questionsAnswered) - AND (@hasAttachments IS NULL OR (@hasAttachments = TRUE AND OA."MediaFilesCount" > 0) OR (@hasAttachments = FALSE AND OA."MediaFilesCount" = 0)) - AND (@hasNotes IS NULL OR (OA."NotesCount" = 0 AND @hasNotes = FALSE) OR (OA."NotesCount" > 0 AND @hasNotes = TRUE)) - AND (@fromDate IS NULL OR OA."LastModifiedOn" >= @fromDate::timestamp) - AND (@toDate IS NULL OR OA."LastModifiedOn" <= @toDate::timestamp) - AND (@hasQuickReports IS NULL OR (@hasQuickReports = TRUE AND OA."QuickReportId" IS NOT NULL) OR (@hasQuickReports = FALSE AND OA."QuickReportId" IS NULL)) - AND (@quickReportFollowUpStatus IS NULL OR OA."QuickReportFollowUpStatus" = @quickReportFollowUpStatus) - AND (@quickReportIncidentCategory IS NULL OR OA."IncidentCategory" = @quickReportIncidentCategory); - - ------------------------------------------------------------------------------------------------- - WITH "ObserverPSI" AS - (SELECT f."Id" AS "FormId", - f."FormType" AS "FormType", - mo."ObserverId" AS "ObserverId", - mo."Id" AS "MonitoringObserverId", - fs."PollingStationId" AS "PollingStationId", - fs."FollowUpStatus" AS "FollowUpStatus", - COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", - fs."IsCompleted" AS "IsCompleted", - CAST(NULL AS bigint) AS "MediaFilesCount", - CAST(NULL AS bigint) AS "NotesCount", - (CASE - WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'All' - WHEN fs."NumberOfQuestionsAnswered" > 0 THEN 'Some' - WHEN fs."NumberOfQuestionsAnswered" = 0 THEN 'None' - END) "QuestionsAnswered", - (CASE - WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE - ELSE FALSE - END) "HasFlaggedAnswers", - CAST(NULL AS UUID) AS "QuickReportId", - NULL AS "IncidentCategory", - NULL AS "QuickReportFollowUpStatus" - FROM "MonitoringObservers" MO - INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" - INNER JOIN "PollingStationInformation" FS ON MO."Id" = FS."MonitoringObserverId" - INNER JOIN "PollingStationInformationForms" F ON f."ElectionRoundId" = @electionRoundId - WHERE MN."ElectionRoundId" = @electionRoundId - AND MN."NgoId" = @ngoId), - "ObserversFormSubmissions" AS - (SELECT f."Id" AS "FormId", - f."FormType" AS "FormType", - mo."ObserverId" AS "ObserverId", - mo."Id" AS "MonitoringObserverId", - fs."PollingStationId" AS "PollingStationId", - fs."FollowUpStatus" AS "FollowUpStatus", - COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", - fs."IsCompleted" AS "IsCompleted", - - (SELECT COUNT(*) - FROM "Attachments" A - WHERE A."FormId" = fs."FormId" - AND a."MonitoringObserverId" = fs."MonitoringObserverId" - AND fs."PollingStationId" = A."PollingStationId" - AND A."IsDeleted" = FALSE - AND A."IsCompleted" = TRUE) AS "MediaFilesCount", - - (SELECT COUNT(*) - FROM "Notes" N - WHERE N."FormId" = fs."FormId" - AND N."MonitoringObserverId" = fs."MonitoringObserverId" - AND fs."PollingStationId" = N."PollingStationId") AS "NotesCount", - (CASE - WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'ALL' - WHEN fs."NumberOfQuestionsAnswered" > 0 THEN 'SOME' - WHEN fs."NumberOfQuestionsAnswered" = 0 THEN 'NONE' - END) "QuestionsAnswered", - (CASE - WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE - ELSE FALSE - END) "HasFlaggedAnswers", - CAST(NULL AS UUID) AS "QuickReportId", - NULL AS "IncidentCategory", - NULL AS "QuickReportFollowUpStatus" - FROM "MonitoringObservers" MO - INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" - INNER JOIN "FormSubmissions" FS ON MO."Id" = FS."MonitoringObserverId" - INNER JOIN "Forms" F ON FS."FormId" = F."Id" - WHERE MN."ElectionRoundId" = @electionRoundId - AND MN."NgoId" = @ngoId), - "ObserversQuickReports" AS - (SELECT CAST(NULL AS UUID) AS "FormId", - NULL AS "FormType", - mo."ObserverId" AS "ObserverId", - mo."Id" AS "MonitoringObserverId", - qr."PollingStationId" AS "PollingStationId", - NULL AS "FollowUpStatus", - COALESCE(qr."LastModifiedOn", qr."CreatedOn") AS "LastModifiedOn", - CAST(NULL AS boolean) AS "IsCompleted", - CAST(NULL AS bigint) AS "MediaFilesCount", - CAST(NULL AS bigint) AS "NotesCount", - NULL AS "QuestionsAnswered", - CAST(NULL AS boolean) AS "HasFlaggedAnswers", - qr."Id" AS "QuickReportId", - qr."IncidentCategory" AS "IncidentCategory", - qr."FollowUpStatus" AS "QuickReportFollowUpStatus" - FROM "MonitoringObservers" MO - INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" - INNER JOIN "QuickReports" QR ON MO."Id" = QR."MonitoringObserverId" - WHERE MN."ElectionRoundId" = @electionRoundId - AND MN."NgoId" = @ngoId), - "ObserversActivity" AS - (SELECT * - FROM "ObserversFormSubmissions" - UNION ALL SELECT * - FROM "ObserversQuickReports" - UNION ALL SELECT * - FROM "ObserverPSI"), - "FilteredObservers" AS - (SELECT DISTINCT OA."MonitoringObserverId", - U."DisplayName" "ObserverName", - U."PhoneNumber", - U."Email", - MO."Tags", - MO."Status" - FROM "ObserversActivity" OA - INNER JOIN "MonitoringObservers" mo ON mo."Id" = OA."MonitoringObserverId" - INNER JOIN "AspNetUsers" U ON U."Id" = OA."ObserverId" - LEFT JOIN "PollingStations" ps ON OA."PollingStationId" = ps."Id" - WHERE (@searchText IS NULL - OR @searchText = '' - OR (U."DisplayName") ILIKE @searchText - OR U."Email" ILIKE @searchText - OR u."PhoneNumber" ILIKE @searchText - OR mo."Id"::text ILIKE @searchText) - AND (@tagsFilter IS NULL OR cardinality(@tagsFilter) = 0 OR mo."Tags" && @tagsFilter) - AND (@monitoringObserverStatus IS NULL OR mo."Status" = @monitoringObserverStatus) - AND (@formType IS NULL OR OA."FormType" = @formType) - AND (@level1 IS NULL OR ps."Level1" = @level1) - AND (@level2 IS NULL OR ps."Level2" = @level2) - AND (@level3 IS NULL OR ps."Level3" = @level3) - AND (@level4 IS NULL OR ps."Level4" = @level4) - AND (@level5 IS NULL OR ps."Level5" = @level5) - AND (@pollingStationNumber IS NULL OR ps."Number" = @pollingStationNumber) - AND (@hasFlaggedAnswers IS NULL OR OA."HasFlaggedAnswers" = @hasFlaggedAnswers) - AND (@submissionsFollowUpStatus IS NULL OR OA."FollowUpStatus" = @submissionsFollowUpStatus) - AND (@formId IS NULL OR OA."FormId" = @formId) - AND (@questionsAnswered IS NULL OR OA."QuestionsAnswered" = @questionsAnswered) - AND (@hasAttachments IS NULL OR (@hasAttachments = TRUE AND OA."MediaFilesCount" > 0) OR (@hasAttachments = FALSE AND OA."MediaFilesCount" = 0)) - AND (@hasNotes IS NULL OR (OA."NotesCount" = 0 AND @hasNotes = FALSE) OR (OA."NotesCount" > 0 AND @hasNotes = TRUE)) - AND (@fromDate IS NULL OR OA."LastModifiedOn" >= @fromDate::timestamp) - AND (@toDate IS NULL OR OA."LastModifiedOn" <= @toDate::timestamp) - AND (@hasQuickReports IS NULL OR (@hasQuickReports = TRUE AND OA."QuickReportId" IS NOT NULL) - OR (@hasQuickReports = FALSE AND OA."QuickReportId" IS NULL)) - AND (@quickReportFollowUpStatus IS NULL OR OA."QuickReportFollowUpStatus" = @quickReportFollowUpStatus) - AND (@quickReportIncidentCategory IS NULL OR OA."IncidentCategory" = @quickReportIncidentCategory)) - SELECT * - FROM "FilteredObservers" - ORDER BY CASE - WHEN @sortExpression = 'ObserverName ASC' THEN "ObserverName" END ASC, - CASE WHEN @sortExpression = 'ObserverName DESC' THEN "ObserverName" END DESC, - CASE WHEN @sortExpression = 'PhoneNumber ASC' THEN "PhoneNumber" END ASC, - CASE WHEN @sortExpression = 'PhoneNumber DESC' THEN "PhoneNumber" END DESC, - CASE WHEN @sortExpression = 'Email ASC' THEN "Email" END ASC, - CASE WHEN @sortExpression = 'Email DESC' THEN "Email" END DESC, - CASE WHEN @sortExpression = 'Tags ASC' THEN "Tags" END ASC, - CASE WHEN @sortExpression = 'Tags DESC' THEN "Tags" END DESC, - CASE WHEN @sortExpression = 'Status ASC' THEN "Status" END ASC, - CASE WHEN @sortExpression = 'Status DESC' THEN "Status" END DESC - OFFSET @offset ROWS FETCH NEXT @pageSize ROWS ONLY; - """; + var sql = + """ + WITH + "ObserverPSI" AS ( + SELECT + F."Id" AS "FormId", + F."FormType" AS "FormType", + MO."Id" AS "MonitoringObserverId", + FS."PollingStationId" AS "PollingStationId", + FS."FollowUpStatus" AS "FollowUpStatus", + COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", + FS."IsCompleted" AS "IsCompleted", + CAST(NULL AS BIGINT) AS "MediaFilesCount", + CAST(NULL AS BIGINT) AS "NotesCount", + ( + CASE + WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'All' + WHEN FS."NumberOfQuestionsAnswered" > 0 THEN 'Some' + WHEN FS."NumberOfQuestionsAnswered" = 0 THEN 'None' + END + ) "QuestionsAnswered", + ( + CASE + WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE + ELSE FALSE + END + ) "HasFlaggedAnswers", + CAST(NULL AS UUID) AS "QuickReportId", + NULL AS "IncidentCategory", + NULL AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "PollingStationInformation" FS ON MO."Id" = FS."MonitoringObserverId" + INNER JOIN "PollingStationInformationForms" F ON F."ElectionRoundId" = @ELECTIONROUNDID + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversFormSubmissions" AS ( + SELECT + AF."FormId" AS "FormId", + AF."FormType" AS "FormType", + MO."Id" AS "MonitoringObserverId", + FS."PollingStationId" AS "PollingStationId", + FS."FollowUpStatus" AS "FollowUpStatus", + COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", + FS."IsCompleted" AS "IsCompleted", + ( + SELECT + COUNT(*) + FROM + "Attachments" A + WHERE + A."FormId" = FS."FormId" + AND A."MonitoringObserverId" = FS."MonitoringObserverId" + AND FS."PollingStationId" = A."PollingStationId" + AND A."IsDeleted" = FALSE + AND A."IsCompleted" = TRUE + ) AS "MediaFilesCount", + ( + SELECT + COUNT(*) + FROM + "Notes" N + WHERE + N."FormId" = FS."FormId" + AND N."MonitoringObserverId" = FS."MonitoringObserverId" + AND FS."PollingStationId" = N."PollingStationId" + ) AS "NotesCount", + ( + CASE + WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'All' + WHEN FS."NumberOfQuestionsAnswered" > 0 THEN 'Some' + WHEN FS."NumberOfQuestionsAnswered" = 0 THEN 'None' + END + ) "QuestionsAnswered", + ( + CASE + WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE + ELSE FALSE + END + ) "HasFlaggedAnswers", + CAST(NULL AS UUID) AS "QuickReportId", + NULL AS "IncidentCategory", + NULL AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "FormSubmissions" FS ON MO."Id" = FS."MonitoringObserverId" + INNER JOIN "GetAvailableForms" (@ELECTIONROUNDID, @NGOID, 'Coalition') AF ON AF."FormId" = FS."FormId" + INNER JOIN "Forms" F ON F."Id" = AF."FormId" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversQuickReports" AS ( + SELECT + CAST(NULL AS UUID) AS "FormId", + NULL AS "FormType", + MO."Id" AS "MonitoringObserverId", + QR."PollingStationId" AS "PollingStationId", + NULL AS "FollowUpStatus", + COALESCE(QR."LastModifiedOn", QR."CreatedOn") AS "LastModifiedOn", + CAST(NULL AS BOOLEAN) AS "IsCompleted", + CAST(NULL AS BIGINT) AS "MediaFilesCount", + CAST(NULL AS BIGINT) AS "NotesCount", + NULL AS "QuestionsAnswered", + CAST(NULL AS BOOLEAN) AS "HasFlaggedAnswers", + QR."Id" AS "QuickReportId", + QR."IncidentCategory" AS "IncidentCategory", + QR."FollowUpStatus" AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "QuickReports" QR ON MO."Id" = QR."MonitoringObserverId" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversActivity" AS ( + SELECT + * + FROM + "ObserversFormSubmissions" + UNION ALL + SELECT + * + FROM + "ObserversQuickReports" + UNION ALL + SELECT + * + FROM + "ObserverPSI" + ) + SELECT + COUNT(DISTINCT MO."Id") COUNT + FROM + "MonitoringObservers" MO + INNER JOIN "AspNetUsers" U ON U."Id" = MO."ObserverId" + INNER JOIN "MonitoringNgos" MN ON MO."MonitoringNgoId" = MN."Id" + LEFT JOIN "ObserversActivity" OA ON MO."Id" = OA."MonitoringObserverId" + LEFT JOIN "PollingStations" PS ON OA."PollingStationId" = PS."Id" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + AND ( + @SEARCHTEXT IS NULL + OR @SEARCHTEXT = '' + OR U."DisplayName" ILIKE @SEARCHTEXT + OR U."Email" ILIKE @SEARCHTEXT + OR U."PhoneNumber" ILIKE @SEARCHTEXT + OR MO."Id"::TEXT ILIKE @SEARCHTEXT + ) + AND ( + @TAGSFILTER IS NULL + OR CARDINALITY(@TAGSFILTER) = 0 + OR MO."Tags" && @TAGSFILTER + ) + AND ( + @MONITORINGOBSERVERSTATUS IS NULL + OR MO."Status" = @MONITORINGOBSERVERSTATUS + ) + AND ( + @FORMTYPE IS NULL + OR OA."FormType" = @FORMTYPE + ) + AND ( + @LEVEL1 IS NULL + OR PS."Level1" = @LEVEL1 + ) + AND ( + @LEVEL2 IS NULL + OR PS."Level2" = @LEVEL2 + ) + AND ( + @LEVEL3 IS NULL + OR PS."Level3" = @LEVEL3 + ) + AND ( + @LEVEL4 IS NULL + OR PS."Level4" = @LEVEL4 + ) + AND ( + @LEVEL5 IS NULL + OR PS."Level5" = @LEVEL5 + ) + AND ( + @POLLINGSTATIONNUMBER IS NULL + OR PS."Number" = @POLLINGSTATIONNUMBER + ) + AND ( + @HASFLAGGEDANSWERS IS NULL + OR OA."HasFlaggedAnswers" = @HASFLAGGEDANSWERS + ) + AND ( + @SUBMISSIONSFOLLOWUPSTATUS IS NULL + OR OA."FollowUpStatus" = @SUBMISSIONSFOLLOWUPSTATUS + ) + AND ( + @FORMID IS NULL + OR OA."FormId" = @FORMID + ) + AND ( + @QUESTIONSANSWERED IS NULL + OR OA."QuestionsAnswered" = @QUESTIONSANSWERED + ) + AND ( + @HASATTACHMENTS IS NULL + OR ( + @HASATTACHMENTS = TRUE + AND OA."MediaFilesCount" > 0 + ) + OR ( + @HASATTACHMENTS = FALSE + AND OA."MediaFilesCount" = 0 + ) + ) + AND ( + @HASNOTES IS NULL + OR ( + OA."NotesCount" = 0 + AND @HASNOTES = FALSE + ) + OR ( + OA."NotesCount" > 0 + AND @HASNOTES = TRUE + ) + ) + AND ( + @FROMDATE IS NULL + OR OA."LastModifiedOn" >= @FROMDATE::TIMESTAMP + ) + AND ( + @TODATE IS NULL + OR OA."LastModifiedOn" <= @TODATE::TIMESTAMP + ) + AND ( + @HASQUICKREPORTS IS NULL + OR ( + @HASQUICKREPORTS = TRUE + AND OA."QuickReportId" IS NOT NULL + ) + OR ( + @HASQUICKREPORTS = FALSE + AND OA."QuickReportId" IS NULL + ) + ) + AND ( + @QUICKREPORTFOLLOWUPSTATUS IS NULL + OR OA."QuickReportFollowUpStatus" = @QUICKREPORTFOLLOWUPSTATUS + ) + AND ( + @QUICKREPORTINCIDENTCATEGORY IS NULL + OR OA."IncidentCategory" = @QUICKREPORTINCIDENTCATEGORY + ); + + ------------------------------------------------------------------------------------------------- + WITH + "ObserverPSI" AS ( + SELECT + F."Id" AS "FormId", + F."FormType" AS "FormType", + MO."Id" AS "MonitoringObserverId", + FS."PollingStationId" AS "PollingStationId", + FS."FollowUpStatus" AS "FollowUpStatus", + COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", + FS."IsCompleted" AS "IsCompleted", + CAST(NULL AS BIGINT) AS "MediaFilesCount", + CAST(NULL AS BIGINT) AS "NotesCount", + ( + CASE + WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'All' + WHEN FS."NumberOfQuestionsAnswered" > 0 THEN 'Some' + WHEN FS."NumberOfQuestionsAnswered" = 0 THEN 'None' + END + ) "QuestionsAnswered", + ( + CASE + WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE + ELSE FALSE + END + ) "HasFlaggedAnswers", + CAST(NULL AS UUID) AS "QuickReportId", + NULL AS "IncidentCategory", + NULL AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "PollingStationInformation" FS ON MO."Id" = FS."MonitoringObserverId" + INNER JOIN "PollingStationInformationForms" F ON F."ElectionRoundId" = @ELECTIONROUNDID + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversFormSubmissions" AS ( + SELECT + AF."FormId" AS "FormId", + AF."FormType" AS "FormType", + MO."Id" AS "MonitoringObserverId", + FS."PollingStationId" AS "PollingStationId", + FS."FollowUpStatus" AS "FollowUpStatus", + COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", + FS."IsCompleted" AS "IsCompleted", + ( + SELECT + COUNT(*) + FROM + "Attachments" A + WHERE + A."FormId" = FS."FormId" + AND A."MonitoringObserverId" = FS."MonitoringObserverId" + AND FS."PollingStationId" = A."PollingStationId" + AND A."IsDeleted" = FALSE + AND A."IsCompleted" = TRUE + ) AS "MediaFilesCount", + ( + SELECT + COUNT(*) + FROM + "Notes" N + WHERE + N."FormId" = FS."FormId" + AND N."MonitoringObserverId" = FS."MonitoringObserverId" + AND FS."PollingStationId" = N."PollingStationId" + ) AS "NotesCount", + ( + CASE + WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'ALL' + WHEN FS."NumberOfQuestionsAnswered" > 0 THEN 'SOME' + WHEN FS."NumberOfQuestionsAnswered" = 0 THEN 'NONE' + END + ) "QuestionsAnswered", + ( + CASE + WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE + ELSE FALSE + END + ) "HasFlaggedAnswers", + CAST(NULL AS UUID) AS "QuickReportId", + NULL AS "IncidentCategory", + NULL AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "FormSubmissions" FS ON MO."Id" = FS."MonitoringObserverId" + INNER JOIN "GetAvailableForms" (@ELECTIONROUNDID, @NGOID, 'Coalition') AF ON AF."FormId" = FS."FormId" + INNER JOIN "Forms" F ON AF."FormId" = F."Id" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversQuickReports" AS ( + SELECT + CAST(NULL AS UUID) AS "FormId", + NULL AS "FormType", + MO."Id" AS "MonitoringObserverId", + QR."PollingStationId" AS "PollingStationId", + NULL AS "FollowUpStatus", + COALESCE(QR."LastModifiedOn", QR."CreatedOn") AS "LastModifiedOn", + CAST(NULL AS BOOLEAN) AS "IsCompleted", + CAST(NULL AS BIGINT) AS "MediaFilesCount", + CAST(NULL AS BIGINT) AS "NotesCount", + NULL AS "QuestionsAnswered", + CAST(NULL AS BOOLEAN) AS "HasFlaggedAnswers", + QR."Id" AS "QuickReportId", + QR."IncidentCategory" AS "IncidentCategory", + QR."FollowUpStatus" AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "QuickReports" QR ON MO."Id" = QR."MonitoringObserverId" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversActivity" AS ( + SELECT + * + FROM + "ObserversFormSubmissions" + UNION ALL + SELECT + * + FROM + "ObserversQuickReports" + UNION ALL + SELECT + * + FROM + "ObserverPSI" + ), + "FilteredObservers" AS ( + SELECT DISTINCT + MO."Id" AS "MonitoringObserverId", + U."DisplayName" "ObserverName", + U."PhoneNumber", + U."Email", + MO."Tags", + MO."Status" + FROM + "MonitoringObservers" MO + INNER JOIN "AspNetUsers" U ON U."Id" = MO."ObserverId" + INNER JOIN "MonitoringNgos" MN ON MO."MonitoringNgoId" = MN."Id" + LEFT JOIN "ObserversActivity" OA ON MO."Id" = OA."MonitoringObserverId" + LEFT JOIN "PollingStations" PS ON OA."PollingStationId" = PS."Id" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + AND ( + @SEARCHTEXT IS NULL + OR @SEARCHTEXT = '' + OR (U."DisplayName") ILIKE @SEARCHTEXT + OR U."Email" ILIKE @SEARCHTEXT + OR U."PhoneNumber" ILIKE @SEARCHTEXT + OR MO."Id"::TEXT ILIKE @SEARCHTEXT + ) + AND ( + @TAGSFILTER IS NULL + OR CARDINALITY(@TAGSFILTER) = 0 + OR MO."Tags" && @TAGSFILTER + ) + AND ( + @MONITORINGOBSERVERSTATUS IS NULL + OR MO."Status" = @MONITORINGOBSERVERSTATUS + ) + AND ( + @FORMTYPE IS NULL + OR OA."FormType" = @FORMTYPE + ) + AND ( + @LEVEL1 IS NULL + OR PS."Level1" = @LEVEL1 + ) + AND ( + @LEVEL2 IS NULL + OR PS."Level2" = @LEVEL2 + ) + AND ( + @LEVEL3 IS NULL + OR PS."Level3" = @LEVEL3 + ) + AND ( + @LEVEL4 IS NULL + OR PS."Level4" = @LEVEL4 + ) + AND ( + @LEVEL5 IS NULL + OR PS."Level5" = @LEVEL5 + ) + AND ( + @POLLINGSTATIONNUMBER IS NULL + OR PS."Number" = @POLLINGSTATIONNUMBER + ) + AND ( + @HASFLAGGEDANSWERS IS NULL + OR OA."HasFlaggedAnswers" = @HASFLAGGEDANSWERS + ) + AND ( + @SUBMISSIONSFOLLOWUPSTATUS IS NULL + OR OA."FollowUpStatus" = @SUBMISSIONSFOLLOWUPSTATUS + ) + AND ( + @FORMID IS NULL + OR OA."FormId" = @FORMID + ) + AND ( + @QUESTIONSANSWERED IS NULL + OR OA."QuestionsAnswered" = @QUESTIONSANSWERED + ) + AND ( + @HASATTACHMENTS IS NULL + OR ( + @HASATTACHMENTS = TRUE + AND OA."MediaFilesCount" > 0 + ) + OR ( + @HASATTACHMENTS = FALSE + AND OA."MediaFilesCount" = 0 + ) + ) + AND ( + @HASNOTES IS NULL + OR ( + OA."NotesCount" = 0 + AND @HASNOTES = FALSE + ) + OR ( + OA."NotesCount" > 0 + AND @HASNOTES = TRUE + ) + ) + AND ( + @FROMDATE IS NULL + OR OA."LastModifiedOn" >= @FROMDATE::TIMESTAMP + ) + AND ( + @TODATE IS NULL + OR OA."LastModifiedOn" <= @TODATE::TIMESTAMP + ) + AND ( + @HASQUICKREPORTS IS NULL + OR ( + @HASQUICKREPORTS = TRUE + AND OA."QuickReportId" IS NOT NULL + ) + OR ( + @HASQUICKREPORTS = FALSE + AND OA."QuickReportId" IS NULL + ) + ) + AND ( + @QUICKREPORTFOLLOWUPSTATUS IS NULL + OR OA."QuickReportFollowUpStatus" = @QUICKREPORTFOLLOWUPSTATUS + ) + AND ( + @QUICKREPORTINCIDENTCATEGORY IS NULL + OR OA."IncidentCategory" = @QUICKREPORTINCIDENTCATEGORY + ) + ) + SELECT + * + FROM + "FilteredObservers" + ORDER BY + CASE + WHEN @SORTEXPRESSION = 'ObserverName ASC' THEN "ObserverName" + END ASC, + CASE + WHEN @SORTEXPRESSION = 'ObserverName DESC' THEN "ObserverName" + END DESC, + CASE + WHEN @SORTEXPRESSION = 'PhoneNumber ASC' THEN "PhoneNumber" + END ASC, + CASE + WHEN @SORTEXPRESSION = 'PhoneNumber DESC' THEN "PhoneNumber" + END DESC, + CASE + WHEN @SORTEXPRESSION = 'Email ASC' THEN "Email" + END ASC, + CASE + WHEN @SORTEXPRESSION = 'Email DESC' THEN "Email" + END DESC, + CASE + WHEN @SORTEXPRESSION = 'Tags ASC' THEN "Tags" + END ASC, + CASE + WHEN @SORTEXPRESSION = 'Tags DESC' THEN "Tags" + END DESC, + CASE + WHEN @SORTEXPRESSION = 'Status ASC' THEN "Status" + END ASC, + CASE + WHEN @SORTEXPRESSION = 'Status DESC' THEN "Status" + END DESC + OFFSET + @OFFSET ROWS + FETCH NEXT + @PAGESIZE ROWS ONLY; + """; var queryArgs = new { diff --git a/api/src/Feature.Notifications/ListSent/Endpoint.cs b/api/src/Feature.Notifications/ListSent/Endpoint.cs index 68286bfb0..498a50b5c 100644 --- a/api/src/Feature.Notifications/ListSent/Endpoint.cs +++ b/api/src/Feature.Notifications/ListSent/Endpoint.cs @@ -49,7 +49,7 @@ public override async Task> ExecuteAsync(Reques MN."NgoId" = @ngoId AND N."ElectionRoundId" = @electionRoundId GROUP BY - N."Id", N."Title", N."Body", N."CreatedOn", U."FirstName", U."LastName" + N."Id", N."Title", N."Body", N."CreatedOn", U."DisplayName" ORDER BY N."CreatedOn" DESC OFFSET @offset ROWS FETCH NEXT @pageSize ROWS ONLY; diff --git a/api/src/Feature.Notifications/Send/Endpoint.cs b/api/src/Feature.Notifications/Send/Endpoint.cs index 1d328c298..fcd872af1 100644 --- a/api/src/Feature.Notifications/Send/Endpoint.cs +++ b/api/src/Feature.Notifications/Send/Endpoint.cs @@ -26,169 +26,529 @@ public override void Configure() public override async Task, ProblemHttpResult>> ExecuteAsync(Request req, CancellationToken ct) { - var sql = """ - WITH "ObserverPSI" AS - (SELECT f."Id" AS "FormId", - f."FormType" AS "FormType", - mo."ObserverId" AS "ObserverId", - mo."Id" AS "MonitoringObserverId", - fs."PollingStationId" AS "PollingStationId", - fs."FollowUpStatus" AS "FollowUpStatus", - COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", - fs."IsCompleted" AS "IsCompleted", - CAST(NULL AS bigint) AS "MediaFilesCount", - CAST(NULL AS bigint) AS "NotesCount", - (CASE - WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'All' - WHEN fs."NumberOfQuestionsAnswered" > 0 THEN 'Some' - WHEN fs."NumberOfQuestionsAnswered" = 0 THEN 'None' - END) "QuestionsAnswered", - (CASE - WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE - ELSE FALSE - END) "HasFlaggedAnswers", - CAST(NULL AS UUID) AS "QuickReportId", - NULL AS "IncidentCategory", - NULL AS "QuickReportFollowUpStatus" - FROM "MonitoringObservers" MO - INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" - INNER JOIN "PollingStationInformation" FS ON MO."Id" = FS."MonitoringObserverId" - INNER JOIN "PollingStationInformationForms" F ON f."ElectionRoundId" = @electionRoundId - WHERE MN."ElectionRoundId" = @electionRoundId - AND MN."NgoId" = @ngoId), - "ObserversFormSubmissions" AS - (SELECT f."Id" AS "FormId", - f."FormType" AS "FormType", - mo."ObserverId" AS "ObserverId", - mo."Id" AS "MonitoringObserverId", - fs."PollingStationId" AS "PollingStationId", - fs."FollowUpStatus" AS "FollowUpStatus", - COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", - fs."IsCompleted" AS "IsCompleted", - - (SELECT COUNT(*) - FROM "Attachments" A - WHERE A."FormId" = fs."FormId" - AND a."MonitoringObserverId" = fs."MonitoringObserverId" - AND fs."PollingStationId" = A."PollingStationId" - AND A."IsDeleted" = FALSE - AND A."IsCompleted" = TRUE) AS "MediaFilesCount", - - (SELECT COUNT(*) - FROM "Notes" N - WHERE N."FormId" = fs."FormId" - AND N."MonitoringObserverId" = fs."MonitoringObserverId" - AND fs."PollingStationId" = N."PollingStationId") AS "NotesCount", - (CASE - WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'ALL' - WHEN fs."NumberOfQuestionsAnswered" > 0 THEN 'SOME' - WHEN fs."NumberOfQuestionsAnswered" = 0 THEN 'NONE' - END) "QuestionsAnswered", - (CASE - WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE - ELSE FALSE - END) "HasFlaggedAnswers", - CAST(NULL AS UUID) AS "QuickReportId", - NULL AS "IncidentCategory", - NULL AS "QuickReportFollowUpStatus" - FROM "MonitoringObservers" MO - INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" - INNER JOIN "FormSubmissions" FS ON MO."Id" = FS."MonitoringObserverId" - INNER JOIN "Forms" F ON FS."FormId" = F."Id" - WHERE MN."ElectionRoundId" = @electionRoundId - AND MN."NgoId" = @ngoId), - "ObserversQuickReports" AS - (SELECT CAST(NULL AS UUID) AS "FormId", - NULL AS "FormType", - mo."ObserverId" AS "ObserverId", - mo."Id" AS "MonitoringObserverId", - qr."PollingStationId" AS "PollingStationId", - NULL AS "FollowUpStatus", - COALESCE(qr."LastModifiedOn", qr."CreatedOn") AS "LastModifiedOn", - CAST(NULL AS boolean) AS "IsCompleted", - CAST(NULL AS bigint) AS "MediaFilesCount", - CAST(NULL AS bigint) AS "NotesCount", - NULL AS "QuestionsAnswered", - CAST(NULL AS boolean) AS "HasFlaggedAnswers", - qr."Id" AS "QuickReportId", - qr."IncidentCategory" AS "IncidentCategory", - qr."FollowUpStatus" AS "QuickReportFollowUpStatus" - FROM "MonitoringObservers" MO - INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" - INNER JOIN "QuickReports" QR ON MO."Id" = QR."MonitoringObserverId" - WHERE MN."ElectionRoundId" = @electionRoundId - AND MN."NgoId" = @ngoId), - "ObserversActivity" AS - (SELECT * - FROM "ObserversFormSubmissions" - UNION ALL SELECT * - FROM "ObserversQuickReports" - UNION ALL SELECT * - FROM "ObserverPSI") - SELECT DISTINCT OA."MonitoringObserverId", - NT."Token" - FROM "ObserversActivity" OA - INNER JOIN "MonitoringObservers" mo ON mo."Id" = OA."MonitoringObserverId" - INNER JOIN "AspNetUsers" U ON U."Id" = OA."ObserverId" - LEFT JOIN "PollingStations" ps ON OA."PollingStationId" = ps."Id" - LEFT JOIN "NotificationTokens" NT ON NT."ObserverId" = OA."ObserverId" - WHERE (@searchText IS NULL - OR @searchText = '' - OR U."DisplayName" ILIKE @searchText - OR U."Email" ILIKE @searchText - OR u."PhoneNumber" ILIKE @searchText - OR mo."Id"::text ILIKE @searchText) - AND (@tagsFilter IS NULL - OR cardinality(@tagsFilter) = 0 - OR mo."Tags" && @tagsFilter) - AND (@monitoringObserverStatus IS NULL - OR mo."Status" = @monitoringObserverStatus) - AND (@formType IS NULL - OR OA."FormType" = @formType) - AND (@level1 IS NULL - OR ps."Level1" = @level1) - AND (@level2 IS NULL - OR ps."Level2" = @level2) - AND (@level3 IS NULL - OR ps."Level3" = @level3) - AND (@level4 IS NULL - OR ps."Level4" = @level4) - AND (@level5 IS NULL - OR ps."Level5" = @level5) - AND (@pollingStationNumber IS NULL - OR ps."Number" = @pollingStationNumber) - AND (@hasFlaggedAnswers IS NULL - OR OA."HasFlaggedAnswers" = @hasFlaggedAnswers) - AND (@submissionsFollowUpStatus IS NULL - OR OA."FollowUpStatus" = @submissionsFollowUpStatus) - AND (@formId IS NULL - OR OA."FormId" = @formId) - AND (@questionsAnswered IS NULL - OR OA."QuestionsAnswered" = @questionsAnswered) - AND (@hasAttachments IS NULL - OR (@hasAttachments = TRUE - AND OA."MediaFilesCount" > 0) - OR (@hasAttachments = FALSE - AND OA."MediaFilesCount" = 0)) - AND (@hasNotes IS NULL - OR (OA."NotesCount" = 0 - AND @hasNotes = FALSE) - OR (OA."NotesCount" > 0 - AND @hasNotes = TRUE)) - AND (@fromDate IS NULL - OR OA."LastModifiedOn" >= @fromDate::timestamp) - AND (@toDate IS NULL - OR OA."LastModifiedOn" <= @toDate::timestamp) - AND (@hasQuickReports IS NULL - OR (@hasQuickReports = TRUE - AND OA."QuickReportId" IS NOT NULL) - OR (@hasQuickReports = FALSE - AND OA."QuickReportId" IS NULL)) - AND (@quickReportFollowUpStatus IS NULL - OR OA."QuickReportFollowUpStatus" = @quickReportFollowUpStatus) - AND (@quickReportIncidentCategory IS NULL - OR OA."IncidentCategory" = @quickReportIncidentCategory) - """; + var sql = + """ + WITH + "ObserverPSI" AS ( + SELECT + F."Id" AS "FormId", + F."FormType" AS "FormType", + MO."Id" AS "MonitoringObserverId", + FS."PollingStationId" AS "PollingStationId", + FS."FollowUpStatus" AS "FollowUpStatus", + COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", + FS."IsCompleted" AS "IsCompleted", + CAST(NULL AS BIGINT) AS "MediaFilesCount", + CAST(NULL AS BIGINT) AS "NotesCount", + ( + CASE + WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'All' + WHEN FS."NumberOfQuestionsAnswered" > 0 THEN 'Some' + WHEN FS."NumberOfQuestionsAnswered" = 0 THEN 'None' + END + ) "QuestionsAnswered", + ( + CASE + WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE + ELSE FALSE + END + ) "HasFlaggedAnswers", + CAST(NULL AS UUID) AS "QuickReportId", + NULL AS "IncidentCategory", + NULL AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "PollingStationInformation" FS ON MO."Id" = FS."MonitoringObserverId" + INNER JOIN "PollingStationInformationForms" F ON F."ElectionRoundId" = @ELECTIONROUNDID + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversFormSubmissions" AS ( + SELECT + AF."FormId" AS "FormId", + AF."FormType" AS "FormType", + MO."Id" AS "MonitoringObserverId", + FS."PollingStationId" AS "PollingStationId", + FS."FollowUpStatus" AS "FollowUpStatus", + COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", + FS."IsCompleted" AS "IsCompleted", + ( + SELECT + COUNT(*) + FROM + "Attachments" A + WHERE + A."FormId" = FS."FormId" + AND A."MonitoringObserverId" = FS."MonitoringObserverId" + AND FS."PollingStationId" = A."PollingStationId" + AND A."IsDeleted" = FALSE + AND A."IsCompleted" = TRUE + ) AS "MediaFilesCount", + ( + SELECT + COUNT(*) + FROM + "Notes" N + WHERE + N."FormId" = FS."FormId" + AND N."MonitoringObserverId" = FS."MonitoringObserverId" + AND FS."PollingStationId" = N."PollingStationId" + ) AS "NotesCount", + ( + CASE + WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'All' + WHEN FS."NumberOfQuestionsAnswered" > 0 THEN 'Some' + WHEN FS."NumberOfQuestionsAnswered" = 0 THEN 'None' + END + ) "QuestionsAnswered", + ( + CASE + WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE + ELSE FALSE + END + ) "HasFlaggedAnswers", + CAST(NULL AS UUID) AS "QuickReportId", + NULL AS "IncidentCategory", + NULL AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "FormSubmissions" FS ON MO."Id" = FS."MonitoringObserverId" + INNER JOIN "GetAvailableForms" (@ELECTIONROUNDID, @NGOID, 'Coalition') AF ON AF."FormId" = FS."FormId" + INNER JOIN "Forms" F ON F."Id" = AF."FormId" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversQuickReports" AS ( + SELECT + CAST(NULL AS UUID) AS "FormId", + NULL AS "FormType", + MO."Id" AS "MonitoringObserverId", + QR."PollingStationId" AS "PollingStationId", + NULL AS "FollowUpStatus", + COALESCE(QR."LastModifiedOn", QR."CreatedOn") AS "LastModifiedOn", + CAST(NULL AS BOOLEAN) AS "IsCompleted", + CAST(NULL AS BIGINT) AS "MediaFilesCount", + CAST(NULL AS BIGINT) AS "NotesCount", + NULL AS "QuestionsAnswered", + CAST(NULL AS BOOLEAN) AS "HasFlaggedAnswers", + QR."Id" AS "QuickReportId", + QR."IncidentCategory" AS "IncidentCategory", + QR."FollowUpStatus" AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "QuickReports" QR ON MO."Id" = QR."MonitoringObserverId" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversActivity" AS ( + SELECT + * + FROM + "ObserversFormSubmissions" + UNION ALL + SELECT + * + FROM + "ObserversQuickReports" + UNION ALL + SELECT + * + FROM + "ObserverPSI" + ) + SELECT + COUNT(DISTINCT MO."Id") COUNT + FROM + "MonitoringObservers" MO + INNER JOIN "AspNetUsers" U ON U."Id" = MO."ObserverId" + INNER JOIN "MonitoringNgos" MN ON MO."MonitoringNgoId" = MN."Id" + LEFT JOIN "ObserversActivity" OA ON MO."Id" = OA."MonitoringObserverId" + LEFT JOIN "PollingStations" PS ON OA."PollingStationId" = PS."Id" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + AND ( + @SEARCHTEXT IS NULL + OR @SEARCHTEXT = '' + OR U."DisplayName" ILIKE @SEARCHTEXT + OR U."Email" ILIKE @SEARCHTEXT + OR U."PhoneNumber" ILIKE @SEARCHTEXT + OR MO."Id"::TEXT ILIKE @SEARCHTEXT + ) + AND ( + @TAGSFILTER IS NULL + OR CARDINALITY(@TAGSFILTER) = 0 + OR MO."Tags" && @TAGSFILTER + ) + AND ( + @MONITORINGOBSERVERSTATUS IS NULL + OR MO."Status" = @MONITORINGOBSERVERSTATUS + ) + AND ( + @FORMTYPE IS NULL + OR OA."FormType" = @FORMTYPE + ) + AND ( + @LEVEL1 IS NULL + OR PS."Level1" = @LEVEL1 + ) + AND ( + @LEVEL2 IS NULL + OR PS."Level2" = @LEVEL2 + ) + AND ( + @LEVEL3 IS NULL + OR PS."Level3" = @LEVEL3 + ) + AND ( + @LEVEL4 IS NULL + OR PS."Level4" = @LEVEL4 + ) + AND ( + @LEVEL5 IS NULL + OR PS."Level5" = @LEVEL5 + ) + AND ( + @POLLINGSTATIONNUMBER IS NULL + OR PS."Number" = @POLLINGSTATIONNUMBER + ) + AND ( + @HASFLAGGEDANSWERS IS NULL + OR OA."HasFlaggedAnswers" = @HASFLAGGEDANSWERS + ) + AND ( + @SUBMISSIONSFOLLOWUPSTATUS IS NULL + OR OA."FollowUpStatus" = @SUBMISSIONSFOLLOWUPSTATUS + ) + AND ( + @FORMID IS NULL + OR OA."FormId" = @FORMID + ) + AND ( + @QUESTIONSANSWERED IS NULL + OR OA."QuestionsAnswered" = @QUESTIONSANSWERED + ) + AND ( + @HASATTACHMENTS IS NULL + OR ( + @HASATTACHMENTS = TRUE + AND OA."MediaFilesCount" > 0 + ) + OR ( + @HASATTACHMENTS = FALSE + AND OA."MediaFilesCount" = 0 + ) + ) + AND ( + @HASNOTES IS NULL + OR ( + OA."NotesCount" = 0 + AND @HASNOTES = FALSE + ) + OR ( + OA."NotesCount" > 0 + AND @HASNOTES = TRUE + ) + ) + AND ( + @FROMDATE IS NULL + OR OA."LastModifiedOn" >= @FROMDATE::TIMESTAMP + ) + AND ( + @TODATE IS NULL + OR OA."LastModifiedOn" <= @TODATE::TIMESTAMP + ) + AND ( + @HASQUICKREPORTS IS NULL + OR ( + @HASQUICKREPORTS = TRUE + AND OA."QuickReportId" IS NOT NULL + ) + OR ( + @HASQUICKREPORTS = FALSE + AND OA."QuickReportId" IS NULL + ) + ) + AND ( + @QUICKREPORTFOLLOWUPSTATUS IS NULL + OR OA."QuickReportFollowUpStatus" = @QUICKREPORTFOLLOWUPSTATUS + ) + AND ( + @QUICKREPORTINCIDENTCATEGORY IS NULL + OR OA."IncidentCategory" = @QUICKREPORTINCIDENTCATEGORY + ); + + ------------------------------------------------------------------------------------------------- + WITH + "ObserverPSI" AS ( + SELECT + F."Id" AS "FormId", + F."FormType" AS "FormType", + MO."Id" AS "MonitoringObserverId", + FS."PollingStationId" AS "PollingStationId", + FS."FollowUpStatus" AS "FollowUpStatus", + COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", + FS."IsCompleted" AS "IsCompleted", + CAST(NULL AS BIGINT) AS "MediaFilesCount", + CAST(NULL AS BIGINT) AS "NotesCount", + ( + CASE + WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'All' + WHEN FS."NumberOfQuestionsAnswered" > 0 THEN 'Some' + WHEN FS."NumberOfQuestionsAnswered" = 0 THEN 'None' + END + ) "QuestionsAnswered", + ( + CASE + WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE + ELSE FALSE + END + ) "HasFlaggedAnswers", + CAST(NULL AS UUID) AS "QuickReportId", + NULL AS "IncidentCategory", + NULL AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "PollingStationInformation" FS ON MO."Id" = FS."MonitoringObserverId" + INNER JOIN "PollingStationInformationForms" F ON F."ElectionRoundId" = @ELECTIONROUNDID + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversFormSubmissions" AS ( + SELECT + AF."FormId" AS "FormId", + AF."FormType" AS "FormType", + MO."Id" AS "MonitoringObserverId", + FS."PollingStationId" AS "PollingStationId", + FS."FollowUpStatus" AS "FollowUpStatus", + COALESCE(FS."LastModifiedOn", FS."CreatedOn") AS "LastModifiedOn", + FS."IsCompleted" AS "IsCompleted", + ( + SELECT + COUNT(*) + FROM + "Attachments" A + WHERE + A."FormId" = FS."FormId" + AND A."MonitoringObserverId" = FS."MonitoringObserverId" + AND FS."PollingStationId" = A."PollingStationId" + AND A."IsDeleted" = FALSE + AND A."IsCompleted" = TRUE + ) AS "MediaFilesCount", + ( + SELECT + COUNT(*) + FROM + "Notes" N + WHERE + N."FormId" = FS."FormId" + AND N."MonitoringObserverId" = FS."MonitoringObserverId" + AND FS."PollingStationId" = N."PollingStationId" + ) AS "NotesCount", + ( + CASE + WHEN FS."NumberOfQuestionsAnswered" = F."NumberOfQuestions" THEN 'ALL' + WHEN FS."NumberOfQuestionsAnswered" > 0 THEN 'SOME' + WHEN FS."NumberOfQuestionsAnswered" = 0 THEN 'NONE' + END + ) "QuestionsAnswered", + ( + CASE + WHEN FS."NumberOfFlaggedAnswers" > 0 THEN TRUE + ELSE FALSE + END + ) "HasFlaggedAnswers", + CAST(NULL AS UUID) AS "QuickReportId", + NULL AS "IncidentCategory", + NULL AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "FormSubmissions" FS ON MO."Id" = FS."MonitoringObserverId" + INNER JOIN "GetAvailableForms" (@ELECTIONROUNDID, @NGOID, 'Coalition') AF ON AF."FormId" = FS."FormId" + INNER JOIN "Forms" F ON AF."FormId" = F."Id" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversQuickReports" AS ( + SELECT + CAST(NULL AS UUID) AS "FormId", + NULL AS "FormType", + MO."Id" AS "MonitoringObserverId", + QR."PollingStationId" AS "PollingStationId", + NULL AS "FollowUpStatus", + COALESCE(QR."LastModifiedOn", QR."CreatedOn") AS "LastModifiedOn", + CAST(NULL AS BOOLEAN) AS "IsCompleted", + CAST(NULL AS BIGINT) AS "MediaFilesCount", + CAST(NULL AS BIGINT) AS "NotesCount", + NULL AS "QuestionsAnswered", + CAST(NULL AS BOOLEAN) AS "HasFlaggedAnswers", + QR."Id" AS "QuickReportId", + QR."IncidentCategory" AS "IncidentCategory", + QR."FollowUpStatus" AS "QuickReportFollowUpStatus" + FROM + "MonitoringObservers" MO + INNER JOIN "MonitoringNgos" MN ON MN."Id" = MO."MonitoringNgoId" + INNER JOIN "QuickReports" QR ON MO."Id" = QR."MonitoringObserverId" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + ), + "ObserversActivity" AS ( + SELECT + * + FROM + "ObserversFormSubmissions" + UNION ALL + SELECT + * + FROM + "ObserversQuickReports" + UNION ALL + SELECT + * + FROM + "ObserverPSI" + ), + "FilteredObservers" AS ( + SELECT DISTINCT + MO."Id" AS "MonitoringObserverId", + NT."Token" + FROM + "MonitoringObservers" MO + INNER JOIN "AspNetUsers" U ON U."Id" = MO."ObserverId" + INNER JOIN "MonitoringNgos" MN ON MO."MonitoringNgoId" = MN."Id" + LEFT JOIN "ObserversActivity" OA ON MO."Id" = OA."MonitoringObserverId" + LEFT JOIN "PollingStations" PS ON OA."PollingStationId" = PS."Id" + LEFT JOIN "NotificationTokens" NT ON NT."ObserverId" = Mo."ObserverId" + WHERE + MN."ElectionRoundId" = @ELECTIONROUNDID + AND MN."NgoId" = @NGOID + AND ( + @SEARCHTEXT IS NULL + OR @SEARCHTEXT = '' + OR (U."DisplayName") ILIKE @SEARCHTEXT + OR U."Email" ILIKE @SEARCHTEXT + OR U."PhoneNumber" ILIKE @SEARCHTEXT + OR MO."Id"::TEXT ILIKE @SEARCHTEXT + ) + AND ( + @TAGSFILTER IS NULL + OR CARDINALITY(@TAGSFILTER) = 0 + OR MO."Tags" && @TAGSFILTER + ) + AND ( + @MONITORINGOBSERVERSTATUS IS NULL + OR MO."Status" = @MONITORINGOBSERVERSTATUS + ) + AND ( + @FORMTYPE IS NULL + OR OA."FormType" = @FORMTYPE + ) + AND ( + @LEVEL1 IS NULL + OR PS."Level1" = @LEVEL1 + ) + AND ( + @LEVEL2 IS NULL + OR PS."Level2" = @LEVEL2 + ) + AND ( + @LEVEL3 IS NULL + OR PS."Level3" = @LEVEL3 + ) + AND ( + @LEVEL4 IS NULL + OR PS."Level4" = @LEVEL4 + ) + AND ( + @LEVEL5 IS NULL + OR PS."Level5" = @LEVEL5 + ) + AND ( + @POLLINGSTATIONNUMBER IS NULL + OR PS."Number" = @POLLINGSTATIONNUMBER + ) + AND ( + @HASFLAGGEDANSWERS IS NULL + OR OA."HasFlaggedAnswers" = @HASFLAGGEDANSWERS + ) + AND ( + @SUBMISSIONSFOLLOWUPSTATUS IS NULL + OR OA."FollowUpStatus" = @SUBMISSIONSFOLLOWUPSTATUS + ) + AND ( + @FORMID IS NULL + OR OA."FormId" = @FORMID + ) + AND ( + @QUESTIONSANSWERED IS NULL + OR OA."QuestionsAnswered" = @QUESTIONSANSWERED + ) + AND ( + @HASATTACHMENTS IS NULL + OR ( + @HASATTACHMENTS = TRUE + AND OA."MediaFilesCount" > 0 + ) + OR ( + @HASATTACHMENTS = FALSE + AND OA."MediaFilesCount" = 0 + ) + ) + AND ( + @HASNOTES IS NULL + OR ( + OA."NotesCount" = 0 + AND @HASNOTES = FALSE + ) + OR ( + OA."NotesCount" > 0 + AND @HASNOTES = TRUE + ) + ) + AND ( + @FROMDATE IS NULL + OR OA."LastModifiedOn" >= @FROMDATE::TIMESTAMP + ) + AND ( + @TODATE IS NULL + OR OA."LastModifiedOn" <= @TODATE::TIMESTAMP + ) + AND ( + @HASQUICKREPORTS IS NULL + OR ( + @HASQUICKREPORTS = TRUE + AND OA."QuickReportId" IS NOT NULL + ) + OR ( + @HASQUICKREPORTS = FALSE + AND OA."QuickReportId" IS NULL + ) + ) + AND ( + @QUICKREPORTFOLLOWUPSTATUS IS NULL + OR OA."QuickReportFollowUpStatus" = @QUICKREPORTFOLLOWUPSTATUS + ) + AND ( + @QUICKREPORTINCIDENTCATEGORY IS NULL + OR OA."IncidentCategory" = @QUICKREPORTINCIDENTCATEGORY + ) + ) + SELECT + * + FROM + "FilteredObservers" + """; var queryArgs = new {