Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2416: portfolio admin notification emails [BOB] #3441

Merged
merged 22 commits into from
Feb 6, 2025

Conversation

dave-kennedy-ecs
Copy link
Contributor

@dave-kennedy-ecs dave-kennedy-ecs commented Feb 1, 2025

Ticket

Resolves #2416

Changes

  • Announce when someone is added as an admin for a portfolio:
    • Email is sent to all admins of a portfolio when someone is invited to become an admin.
      • Email is sent if someone is invited via registrar, in members section, add new member
      • Email is sent if someone is invited via registrar, in members section, edit member, update from basic to admin
      • Email is sent if someone is invited via django admin, portfolio invitations table, add new portfolio invitation (admin role)
      • Email is sent if portfolio invitation (with status invited) is updated in django admin, role updated from member to admin
  • Announce when someone is removed as admin for a portfolio:
    • Email is sent to all admins of a portfolio when someone is removed as an admin.
      • Email is sent if member is removed from portfolio via members section of the registrar
      • Email is sent if member's role is updated from Admin to Basic via members section of the registrar

Context for reviewers

Code Review Notes:
Email sending for both addition and removal notification emails is centralized in utility/email_invitations.py
Template files hold the email content
Logic for when to call which emails is in admin.py (for DJA) and views/portfolios.py
Exception handling is also in these views
Most other code is incidental or minor bug fixes
There are many tests!

Setup

Code Review Verification Steps

As the original developer, I have

Satisfied acceptance criteria and met development standards

  • Met the acceptance criteria, or will meet them in a subsequent PR
  • Created/modified automated tests
  • Update documentation in READMEs and/or onboarding guide

Ensured code standards are met (Original Developer)

  • If any updated dependencies on Pipfile, also update dependencies in requirements.txt.
  • Interactions with external systems are wrapped in try/except
  • Error handling exists for unusual or missing values

Validated user-facing changes (if applicable)

  • Tag @dotgov-designers in this PR's Reviewers for design review. If code is not user-facing, delete design reviewer checklist
  • Verify new pages have been added to .pa11yci file so that they will be tested with our automated accessibility testing
  • Checked keyboard navigability
  • Tested general usability, landmarks, page header structure, and links with a screen reader (such as Voiceover or ANDI)

As a code reviewer, I have

Reviewed, tested, and left feedback about the changes

  • Pulled this branch locally and tested it
  • Verified code meets all checks above. Address any checks that are not satisfied
  • Reviewed this code and left comments. Indicate if comments must be addressed before code is merged
  • Checked that all code is adequately covered by tests
  • Verify migrations are valid and do not conflict with existing migrations

Validated user-facing changes as a developer

Note: Multiple code reviewers can share the checklists above, a second reviewer should not make a duplicate checklist. All checks should be checked before approving, even those labeled N/A.

  • New pages have been added to .pa11yci file so that they will be tested with our automated accessibility testing
  • Checked keyboard navigability
  • Meets all designs and user flows provided by design/product
  • Tested general usability, landmarks, page header structure, and links with a screen reader (such as Voiceover or ANDI)
  • (Rarely needed) Tested as both an analyst and applicant user

As a designer reviewer, I have

Verified that the changes match the design intention

  • Checked that the design translated visually
  • Checked behavior. Comment any found issues or broken flows.
  • Checked different states (empty, one, some, error)
  • Checked for landmarks, page heading structure, and links

Validated user-facing changes as a designer

  • Checked keyboard navigability
  • Tested general usability, landmarks, page header structure, and links with a screen reader (such as Voiceover or ANDI)
  • Tested with multiple browsers (check off which ones were used)
    • Chrome
    • Microsoft Edge
    • FireFox
    • Safari
  • (Rarely needed) Tested as both an analyst and applicant user

References

Screenshots

Copy link

github-actions bot commented Feb 1, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Feb 1, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Feb 1, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Feb 1, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Feb 1, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Feb 1, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Feb 1, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Feb 1, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Feb 1, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Feb 1, 2025

🥳 Successfully deployed to developer sandbox bob.

@dave-kennedy-ecs dave-kennedy-ecs changed the title [DRAFT] #2416: portfolio admin notification emails [BOB] #2416: portfolio admin notification emails [BOB] Feb 1, 2025
Comment on lines -139 to +143
existing_invitations = PortfolioInvitation.objects.exclude(
portfolio=user_portfolio_permission.portfolio
).filter(email=user_portfolio_permission.user.email)
existing_invitations = PortfolioInvitation.objects.filter(email=user_portfolio_permission.user.email).exclude(
Q(portfolio=user_portfolio_permission.portfolio)
| Q(status=PortfolioInvitation.PortfolioInvitationStatus.RETRIEVED)
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this fixes an undocumented bug where retrieved invitations were blocking creation of new invitations

Comment on lines -198 to +201
existing_invitations = PortfolioInvitation.objects.exclude(id=portfolio_invitation.id).filter(
email=portfolio_invitation.email
existing_invitations = PortfolioInvitation.objects.filter(email=portfolio_invitation.email).exclude(
Q(id=portfolio_invitation.id) | Q(status=PortfolioInvitation.PortfolioInvitationStatus.RETRIEVED)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this fixes an undocumented bug where retrieved invitations were blocking creation of new invitations

@Katherine-MN
Copy link
Contributor

Katherine-MN commented Feb 3, 2025

@dave-kennedy-ecs We're bundling the permission emails with the m5 design review next sprint (3281), so design will review these emails then.

Copy link

github-actions bot commented Feb 4, 2025

🥳 Successfully deployed to developer sandbox bob.

@CocoByte CocoByte self-assigned this Feb 5, 2025
Copy link
Contributor

@CocoByte CocoByte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thorough work overall. Just one small question.

@@ -1642,30 +1648,57 @@ def save_model(self, request, obj, form, change):
Emails sent to requested user / email.
When exceptions are raised, return without saving model.
"""
if not change: # Only send email if this is a new PortfolioInvitation (creation)
try:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the way you moved the try statement up

):
messages.warning(
self.request, "Could not send email notification to existing organization admins."
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could be missing something, but don't we need an else after this if-statement? Or does the function somehow terminate before setting the following success message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we don't need an else. In this case, we don't want to raise exceptions when email send attempts fail. But we want views to create messages. So, we are returning a pass/fail boolean from the send_email methods. If it fails, we want to raise a warning. Whether pass or fail, we want to continue after the method completes.

Copy link
Contributor

@CocoByte CocoByte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Copy link

github-actions bot commented Feb 6, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Feb 6, 2025

🥳 Successfully deployed to developer sandbox bob.

@dave-kennedy-ecs dave-kennedy-ecs merged commit 5aebbb4 into main Feb 6, 2025
10 checks passed
@dave-kennedy-ecs dave-kennedy-ecs deleted the bob/2416-portfolio-admin-emails branch February 6, 2025 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dev: Send email to existing admins when an admin is added / removed from a portfolio
3 participants