Skip to content

Commit

Permalink
[EASI-4473] Notification: Data Exchange Approach Completed (#1209)
Browse files Browse the repository at this point in the history
* feat: added feature migration, data models, gql

* chore: updated sql queries

* feat: several major improvements to first semi-functional data exchange approach in-app notification

* chore: updated postman collection to get all notifications

* chore: updated frontend gql and backend gql for user notification preferences

* chore: added simple resolver helper to dispatch emails and email test to validate email templates

* chore: removed resolved question

* chore: Reset all frontend files to main branch as we split the frontend work to EASI-4491

* chore: reran gql gen

* chore: email unit test for data exchange approach completed

* chore: removed unnecessary Scan and Value methods

* chore: added unit test for activity data exchange complete notification

* chore: implemented resolver for data exchange approach completed notification preferences

* fix: updated various test definitions to match new user account preferences spec

* chore: removed outdated comment

* chore: updated postman collection renaming markedCompletedBy -> markedCompleteBy

* chore: converted data exchange approach complete meta to id
  • Loading branch information
OddTomBrooks authored Jul 16, 2024
1 parent 5699c4c commit 3d4e8b1
Show file tree
Hide file tree
Showing 31 changed files with 1,134 additions and 57 deletions.
4 changes: 2 additions & 2 deletions MINT.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -2154,7 +2154,7 @@
"body": {
"mode": "graphql",
"graphql": {
"query": "query currentUser {\n currentUser {\n notifications {\n numUnreadNotifications\n notifications {\n __typename\n id\n isRead\n inAppSent\n emailSent\n activity {\n activityType\n entityID\n actorID\n metaData {\n __typename\n ... on TaggedInPlanDiscussionActivityMeta{\n version\n type\n modelPlanID\n modelPlan{\n modelName\n } \n discussionID\n content\n }\n ... on TaggedInDiscussionReplyActivityMeta {\n version\n type\n modelPlanID\n modelPlan{\n modelName\n } \n discussionID\n replyID\n content\n }\n ... on ModelPlanSharedActivityMeta {\n version\n type\n modelPlanID\n modelPlan{\n modelName\n }\n optionalMessage\n }\n ... on NewDiscussionRepliedActivityMeta {\n version\n type\n discussionID\n replyID\n content\n } \n ... on DailyDigestCompleteActivityMeta{\n version\n type\n modelPlanIDs\n date\n analyzedAudits{\n id\n modelPlanID\n modelName\n date\n changes{\n modelPlan{\n oldName\n statusChanges\n }\n documents{\n count\n }\n crTdls{\n activity\n }\n planSections{\n updated\n readyForReview\n readyForClearance\n }\n modelLeads{\n added{\n id\n commonName\n # userAccount{\n # id\n # email\n # }\n }\n }\n planDiscussions{\n activity\n }\n }\n\n }\n\n }\n ... on NewModelPlanActivityMeta {\n version\n type\n modelPlanID\n modelPlan{\n modelName\n }\n }\n ... on DatesChangedActivityMeta {\n version\n type\n modelPlanID\n modelPlan {\n id\n }\n dateChanges {\n isChanged\n field\n isRange\n oldDate\n newDate\n oldRangeStart\n oldRangeEnd\n newRangeStart\n newRangeEnd\n }\n } \n }\n createdByUserAccount {\n commonName\n }\n }\n createdByUserAccount {\n commonName\n }\n }\n }\n }\n}\n",
"query": "query currentUser {\n currentUser {\n notifications {\n numUnreadNotifications\n notifications {\n __typename\n id\n isRead\n inAppSent\n emailSent\n activity {\n activityType\n entityID\n actorID\n metaData {\n __typename\n ... on TaggedInPlanDiscussionActivityMeta{\n version\n type\n modelPlanID\n modelPlan{\n modelName\n } \n discussionID\n content\n }\n ... on TaggedInDiscussionReplyActivityMeta {\n version\n type\n modelPlanID\n modelPlan{\n modelName\n } \n discussionID\n replyID\n content\n }\n ... on ModelPlanSharedActivityMeta {\n version\n type\n modelPlanID\n modelPlan{\n modelName\n }\n optionalMessage\n }\n ... on NewDiscussionRepliedActivityMeta {\n version\n type\n discussionID\n replyID\n content\n } \n ... on DailyDigestCompleteActivityMeta{\n version\n type\n modelPlanIDs\n date\n analyzedAudits{\n id\n modelPlanID\n modelName\n date\n changes{\n modelPlan{\n oldName\n statusChanges\n }\n documents{\n count\n }\n crTdls{\n activity\n }\n planSections{\n updated\n readyForReview\n readyForClearance\n }\n modelLeads{\n added{\n id\n commonName\n # userAccount{\n # id\n # email\n # }\n }\n }\n planDiscussions{\n activity\n }\n }\n\n }\n\n }\n ... on NewModelPlanActivityMeta {\n version\n type\n modelPlanID\n modelPlan{\n modelName\n }\n }\n ... on DatesChangedActivityMeta {\n version\n type\n modelPlanID\n modelPlan {\n id\n }\n dateChanges {\n isChanged\n field\n isRange\n oldDate\n newDate\n oldRangeStart\n oldRangeEnd\n newRangeStart\n newRangeEnd\n }\n }\n ... on DataExchangeApproachCompletedActivityMeta {\n version\n type\n dataExchangeApproach {\n id\n name\n }\n markedCompleteBy\n } \n }\n createdByUserAccount {\n commonName\n }\n }\n createdByUserAccount {\n commonName\n }\n }\n }\n }\n}\n",
"variables": ""
}
},
Expand Down Expand Up @@ -2194,7 +2194,7 @@
"body": {
"mode": "graphql",
"graphql": {
"query": "query currentUser {\n currentUser {\n notificationPreferences {\n dailyDigestComplete\n\n addedAsCollaborator\n\n taggedInDiscussion\n\n taggedInDiscussionReply\n\n newDiscussionReply\n\n modelPlanShared\n\n newModelPlan\n\n datesChanged\n datesChangedNotificationType\n }\n }\n }\n\n",
"query": "query currentUser {\n currentUser {\n notificationPreferences {\n dailyDigestComplete\n\n addedAsCollaborator\n\n taggedInDiscussion\n\n taggedInDiscussionReply\n\n newDiscussionReply\n\n modelPlanShared\n\n newModelPlan\n\n datesChanged\n datesChangedNotificationType\n\n dataExchangeApproachCompleted\n }\n }\n }\n\n",
"variables": ""
}
},
Expand Down
37 changes: 37 additions & 0 deletions cmd/dbseed/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,43 @@ func (s *Seeder) SeedData() {
},
},
)

// Send a notification for Data Exchange Approach Completed
dataExchangeApproach := models.NewDataExchangeApproach(
"Data Exchange Approach",
planWithDocuments.CreatedBy,
planWithDocuments.ID,
)

dataExchangeApproach.ID = uuid.MustParse("01020304-0506-0708-090a-0b0c0d0e0f10")

// create an actor principal for testing notifications

actorPrincipal := s.getTestPrincipalByUsername("MINT")

// Use a test user to mark the data exchange approach as complete
testUser := s.getTestPrincipalByUsername("BTAL")

err = resolvers.SendDataExchangeApproachCompletedNotification(
s.Config.Context,
s.Config.EmailService,
s.Config.EmailTemplateService,
s.Config.AddressBook,
actorPrincipal.UserAccount.ID,
s.Config.Store,
[]*models.UserAccountAndNotificationPreferences{
{
UserAccount: *testUser.UserAccount,
PreferenceFlags: models.DefaultUserNotificationPreferencesFlags(),
},
},
planWithDocuments,
dataExchangeApproach,
testUser.UserAccount.ID,
)
if err != nil {
panic(fmt.Errorf("failed to send data exchange approach completed notification: %w", err))
}
}

// CreateAnalyzedAuditData uses the seeder to generate analyzed audits. It will make one record for all changes just seeded
Expand Down
29 changes: 28 additions & 1 deletion cmd/test_email/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,25 @@ func main() {

// Running all test functions
sendModelPlanCreatedEmailTest(emailService, templateService)

// Discussion emails
sendPlanDiscussionCreatedTestEmail(emailService, templateService, addressBook)
sendPlanDiscussionTaggedUserTestEmail(emailService, templateService, addressBook)
sendPlanDiscussionTaggedSolutionTestEmail(emailService, templateService, addressBook)

//DiscussionReply email
sendDiscussionReplyOriginatorTestEmail(emailService, templateService, addressBook)

// Model plan emails
sendModelPlanShareTest(emailService, templateService, addressBook)
sendDateChangedEmailsTest(emailService, templateService, addressBook)
sendCollaboratorAddedEmailTest(emailService, templateService, addressBook)
sendDataExchangeApproachCompletedEmailNotificationTest(emailService, templateService, addressBook)
sendFeedbackEmail(emailService, templateService, addressBook)
reportAProblemEmail(emailService, templateService, addressBook)

// Solution emails
sendSolutionSelectedTestEmail(emailService, templateService, addressBook)

}

func noErr(err error) {
Expand Down Expand Up @@ -390,6 +393,30 @@ func sendCollaboratorAddedEmailTest(
noErr(err)
}

func sendDataExchangeApproachCompletedEmailNotificationTest(
emailService oddmail.EmailService,
templateService email.TemplateService,
addressBook email.AddressBook,
) {

modelPlan := models.NewModelPlan(
uuid.Nil,
"Retcon Plan",
)

err := resolvers.SendDataExchangeApproachCompletedEmailNotification(
emailService,
templateService,
addressBook,
modelPlan,
"marty.mcfly@delorean.88",
"Doc Brown",
true,
)

noErr(err)
}

func sendFeedbackEmail(
emailService oddmail.EmailService,
templateService email.TemplateService,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ALTER TYPE ACTIVITY_TYPE
ADD VALUE 'DATA_EXCHANGE_APPROACH_COMPLETED' AFTER 'NEW_MODEL_PLAN';

ALTER TABLE user_notification_preferences
ADD COLUMN data_exchange_approach_completed user_notification_preference_flag[] DEFAULT '{}'::user_notification_preference_flag[];

COMMENT ON COLUMN user_notification_preferences.data_exchange_approach_completed IS 'Notification preference for when a data exchange approach is completed';
15 changes: 15 additions & 0 deletions pkg/email/data_exchange_approach_completed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package email

// DataExchangeApproachCompletedSubjectContent defines the parameters necessary for the corresponding email subject
type DataExchangeApproachCompletedSubjectContent struct {
ModelName string
}

// DataExchangeApproachCompletedBodyContent defines the parameters necessary for the corresponding email body
type DataExchangeApproachCompletedBodyContent struct {
ClientAddress string
ModelName string
ModelID string
MarkedCompletedByUserCommonName string
ShowFooter bool
}
16 changes: 16 additions & 0 deletions pkg/email/template_service_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ var solutionSelectedBodyTemplate string
//go:embed templates/solution_selected_subject.html
var solutionSelectedSubjectTemplate string

// DataExchangeApproachCompletedTemplateName is the template name for the data exchange approach completed email
const DataExchangeApproachCompletedTemplateName string = "data_exchange_approach_completed"

//go:embed templates/data_exchange_approach_completed_body.html
var dataExchangeApproachCompletedBodyTemplate string

//go:embed templates/data_exchange_approach_completed_subject.html
var dataExchangeApproachCompletedSubjectTemplate string

// TemplateServiceImpl is an implementation-specific structure loading all resources necessary for server execution
type TemplateServiceImpl struct {
templateCache *emailTemplates.TemplateCache
Expand Down Expand Up @@ -185,6 +194,7 @@ func (t *TemplateServiceImpl) Load() error {
if err != nil {
return err
}

err = t.loadEmailTemplate(DiscussionReplyCreatedOriginatorTemplateName, discussionReplyCreatedOriginatorSubjectTemplate, discussionReplyCreatedOriginatorBodyTemplate)
if err != nil {
return err
Expand Down Expand Up @@ -224,6 +234,12 @@ func (t *TemplateServiceImpl) Load() error {
if err != nil {
return err
}

err = t.loadEmailTemplate(DataExchangeApproachCompletedTemplateName, dataExchangeApproachCompletedSubjectTemplate, dataExchangeApproachCompletedBodyTemplate)
if err != nil {
return err
}

return nil
}

Expand Down
19 changes: 19 additions & 0 deletions pkg/email/templates/data_exchange_approach_completed_body.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{{template "shared_header.html" "Data exchange approach complete:"}}

<h3>{{.ModelName}}</h3>
<p>Marked complete by {{.MarkedCompletedByUserCommonName}}</p>
<br/>
<p>
<a href="{{.ClientAddress}}/models/{{.ModelID}}/read-view/data-exchange-approach">View data exchange approach</a>
</p>
<br/>

{{if .ShowFooter}}
<hr>
<br/>
<p>
You are currently subscribed to notifications when data exchange approaches are completed. If you no longer wish to receive these email notifications, please <a href="{{.ClientAddress}}/notifications/settings?unsubscribe_email=DATA_EXCHANGE_APPROACH_COMPLETED">unsubscribe</a> or change your <a href="{{.ClientAddress}}/notifications/settings">notification settings</a>.
</p>
{{end}}

{{template "shared_footer.html"}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Data exchange approach complete: {{.ModelName}}
Loading

0 comments on commit 3d4e8b1

Please sign in to comment.