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

CON Reminder Emails #910

Merged
merged 13 commits into from
Jun 8, 2024
Merged

CON Reminder Emails #910

merged 13 commits into from
Jun 8, 2024

Conversation

helloanil
Copy link
Contributor

@helloanil helloanil commented Apr 25, 2024

What Github issue does this PR relate to? Insert link.

#712

What should the reviewer know?

This PR is focusing only on the top 3 priority emails from the reminders list:

  • Send Email Reminders to Users who have not completed their Profile
  • Automatically Remind Approved Mentees Without Mentor Applications to Apply
  • Reminder To Mentors To Follow Up On Long-Term (3+ months) Mentorship
  • Reminder To Mentees To Follow Up On Long-Term (3+ months) Mentorship

The automation part will be done in parallel, by writing a service script either directly in the server, or using a service like val.town

Summary by CodeRabbit

  • New Features

    • Introduced ReminderEmailsModule to manage reminder emails for mentorship activities.
    • Added CronjobAuthGuard to secure routes based on authorization tokens.
    • Implemented services and controllers to handle various reminder emails for mentors and mentees.
    • Integrated Salesforce API to fetch email templates.
  • Tests

    • Added test suites for ReminderEmailsController and ReminderEmailsService.
  • Chores

    • Updated .gitignore to exclude specific infrastructure and script files.

Copy link

coderabbitai bot commented Apr 25, 2024

Walkthrough

The recent update to the NestJS API introduces a new ReminderEmailsModule that handles sending reminder emails to mentors and mentees. This includes adding controllers, services, and guards for the new module. Additionally, the .gitignore file has been updated to exclude specific directories, and new test files have been added to ensure the functionality of the reminder email features.

Changes

File Path Change Summary
.gitignore Added exclusions for infrastructure/.terraform and /reminder-email-scripts/*.
apps/nestjs-api/src/app/app.module.ts Imported and added ReminderEmailsModule to the modules list.
apps/nestjs-api/src/auth/cronjob-auth.guard.ts Introduced CronjobAuthGuard class for route guarding based on authorization token.
apps/nestjs-api/src/reminder-emails/... Added ReminderEmailsController, ReminderEmailsService, and their respective test files.
apps/nestjs-api/src/salesforce-api/... Added SfApiEmailTemplatesService for retrieving email templates from Salesforce and updated SfApiModule to include the new service.

Sequence Diagram(s) (Beta)

sequenceDiagram
    participant Client
    participant ReminderEmailsController
    participant ReminderEmailsService
    participant SfApiEmailTemplatesService
    participant AWS SES

    Client->>+ReminderEmailsController: Request to send reminder email
    ReminderEmailsController->>+ReminderEmailsService: Process request
    ReminderEmailsService->>+SfApiEmailTemplatesService: Retrieve email template
    SfApiEmailTemplatesService-->>-ReminderEmailsService: Email template
    ReminderEmailsService->>+AWS SES: Send email
    AWS SES-->>-ReminderEmailsService: Confirmation
    ReminderEmailsService-->>-ReminderEmailsController: Email sent
    ReminderEmailsController-->>-Client: Response
Loading

Poem

In the code where emails fly,
A module built to reach the sky,
Reminders sent with gentle cheer,
To mentors, mentees far and near.
Salesforce whispers templates sweet,
While guards ensure the code's elite.
A rabbit hops with joyful glee,
For changes made so splendidly. 🐇


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ericbolikowski
Copy link
Contributor

Ready for review?

@helloanil
Copy link
Contributor Author

Ready for review?

@ericbolikowski Yes. Please go ahead and review 🙏

Copy link
Contributor

@ericbolikowski ericbolikowski left a comment

Choose a reason for hiding this comment

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

nice wow wow wee wow GIF

reminder-email-scripts/trigger_reminder_emails.sh Outdated Show resolved Hide resolved
throw new Error(`Email template not found: ${sfEmailTemplateName}`)
}

const sanitizedHtml = template.HtmlValue.replace(
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we could even do some kind of test to check for existence of {{{Recipient.FirstName}}} here? And throw if not present. That is something that I see relatively easily happening because of user error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will actually work on these a bit more when I know the script and automation is working correctly. Can we skip this for now?

},
Subject: { Data: template.Subject },
},
Source: 'career@redi-school.org',
Copy link
Contributor

Choose a reason for hiding this comment

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

Will we get into trouble with Malmö?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Again, I can do the fine tuning once I see everything is working correctly.

Copy link
Contributor

@katamatata katamatata left a comment

Choose a reason for hiding this comment

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

@helloanil, great job! 👏

@helloanil helloanil requested a review from katamatata May 6, 2024 19:02
@katamatata katamatata added this to QA by DevLead, DesignLead & PO in CON: ReDI Connect May 7, 2024
@@ -59,6 +59,7 @@ export class ReminderEmailsService {
Profile_First_Approved_At__c: {
$eq: jsforce.SfDate.toDateLiteral(approvedDate),
},
'Contact__r.ReDI_Active_Mentorship_Matches_Mentee__c': null,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think 0 is better than null here. AFAIK this is a formula field in Salesforce, so it shouldn't take on other types than Number.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

0 actually didn’t work. That was also my first attempt, I was quite surprised why it was not working and while debugging it I sent myself 650 emails and lost some valuable time on the Salesforce Dev Console.

Copy link
Contributor

@katamatata katamatata May 7, 2024

Choose a reason for hiding this comment

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

I think this field has a different purpose. I just checked my CON profile on production. I have an ongoing mentorship with Eric, and this field displays 1.
image

So, it correctly shows the Active_Mentorship_Matches, not the number of applications.

And this is from Eric's mentor CON profile:
image

Maybe creating a custom field on the CON profile to check the mentee applications would be better?

Copy link
Contributor

@katamatata katamatata May 7, 2024

Choose a reason for hiding this comment

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

Just found that the Active_Mentorship_Matches_Mentor__c field counts only accepted applications
image

So, I guess we need to create a similar one, counting all mentee applications.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's a bit of a mess:
image

I didn't find the Roll-Up Summary (COUNT Mentorship Match) for Active_Mentorship_Matches_Mentee__c. We definitely need Ghaid's help to determine how we count the same for mentees and create a new count formula field for our purposes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@katamatata But I tested with using ReDI_Active_Mentorship_Matches_Mentee__c and when I didn't have any applications vs when I had an application (wiithout accepted), it worked.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hey, so Kate and I dug a bit into this.

To summarize: none of the four fields...
ReDl_Active_Mentorship_Matches_Mentee, ReDI_Total_Mentorship_Matches_Mentee_c, Total_Mentorship_Matches_Mentor_c, Active_Mentorship_Matches_Mentor_c
... are referenced in the codebase. It's unclear how three out of four of them are actually updated in Salesforce (since they're just a Number field). Our working theory is that a Salesforce "plugin" called Rollup Helper was doing this job, but checking its config, we can't find configuration that ensures such updates. Also, I remember discussing with Manu that the triggers to update the contents of these fields was brittle to begin with.

Recommendation: only use Active_Mentorship_Matches_Mentor_c in our code. Don't use it to count number of applications a mentee has sent. If using that (or other fields) for some reason works, we should either:

  1. figure out how it works, then use it if its reliability satisfies us
  2. use/configure another field and use that

@helloanil, thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey @ericbolikowski, yeah it's a mess that we have all those fields we don't even know how they work 😄. I'm not sure if I can follow your recommendation though: "Only use in our code, not to count number of applications a mentee has sent." You say "use it in code" but then "don't use it".

If we don't feel safe using this field, I'm happy to follow number 2 and configure another field for this.

…g approved mentees with no mentor applications
@helloanil helloanil changed the title add top 3 prio reminder emails CON Reminder Emails Jun 2, 2024
@helloanil
Copy link
Contributor Author

Hey @ericbolikowski and @katamatata, here are the latest news on this task and I need your help:

I decided to move script file to gitignore for two reasons. I'll create this file manually on the server, alongside the background service that will take care of the automation. I will send you the script code on Slack so you can review it there.

  • It's not gonna be useful in anyone's local, yet it can be even dangerous
  • It includes some stuff that's better not be public

I will start testing this task with two reminders only, which is the top priority ones. (Mentors and Mentees to complete their profile). There are few more reminders ready but I haven't tested them properly yet. They are commented out (see the last commit). Please let's focus on only the first two reminders for now.

@helloanil
Copy link
Contributor Author

Just added another reminder:

  1. Reminder: In-between service for long-term (3+ months) mentorships to check what is going on (3 months after the mentorship match date, with and without logged sessions) - Priority 3

Copy link
Contributor

@katamatata katamatata left a comment

Choose a reason for hiding this comment

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

@helloanil, can you please comment all the functions in reminder-emails.service.spec.ts that are not used by the reminders implemented in this PR (getApprovedMenteesWithNoMentorApplicationsByDays, getUnmatchedMenteesWithApprovedProfiles, getConProfilesWithMentorshipMatchesWithoutMentoringSessions, sendApplyToMentorFirstReminder, sendApplyToMentorSecondReminder, sendMenteesPlatformAndNewMentorsReminder)? They made it harder to review the current implementation, and some of these functions require changes, as we discussed in the previous comments.

I left one comment regarding your email. Otherwise, it looks good to me.

const params = {
Destination: {
ToAddresses: isProductionOrDemonstration()
? ['anilakarsu93@gmail.com']
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this email be changed before deploying?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between b8ba7ae and 04163b5.

Files selected for processing (10)
  • .gitignore (1 hunks)
  • apps/nestjs-api/src/app/app.module.ts (2 hunks)
  • apps/nestjs-api/src/auth/cronjob-auth.guard.ts (1 hunks)
  • apps/nestjs-api/src/reminder-emails/reminder-emails.controller.spec.ts (1 hunks)
  • apps/nestjs-api/src/reminder-emails/reminder-emails.controller.ts (1 hunks)
  • apps/nestjs-api/src/reminder-emails/reminder-emails.module.ts (1 hunks)
  • apps/nestjs-api/src/reminder-emails/reminder-emails.service.spec.ts (1 hunks)
  • apps/nestjs-api/src/reminder-emails/reminder-emails.service.ts (1 hunks)
  • apps/nestjs-api/src/salesforce-api/sf-api-email-templates.service.ts (1 hunks)
  • apps/nestjs-api/src/salesforce-api/sf-api.module.ts (3 hunks)
Files skipped from review due to trivial changes (3)
  • .gitignore
  • apps/nestjs-api/src/reminder-emails/reminder-emails.controller.spec.ts
  • apps/nestjs-api/src/reminder-emails/reminder-emails.service.spec.ts
Additional comments not posted (13)
apps/nestjs-api/src/auth/cronjob-auth.guard.ts (1)

6-17: Implementation of CronjobAuthGuard follows NestJS best practices for guards and securely checks authorization tokens.

apps/nestjs-api/src/reminder-emails/reminder-emails.module.ts (1)

9-18: Configuration of ReminderEmailsModule correctly sets up dependencies and controllers needed for the reminder emails functionality.

apps/nestjs-api/src/salesforce-api/sf-api.module.ts (1)

60-60: The comment about a hack in the exports section should be addressed. If it's no longer necessary, consider removing it.

-    //! TODO: this was hack - remote this export
-    SfApiRepository,
apps/nestjs-api/src/app/app.module.ts (1)

12-12: Integration of ReminderEmailsModule into AppModule looks good and aligns with the PR's objectives.

Also applies to: 61-61

apps/nestjs-api/src/reminder-emails/reminder-emails.controller.ts (4)

1-4: Setup of ReminderEmailsController with necessary imports and guard looks correct.

Also applies to: 6-9


11-32: The method sendMentorCompleteProfileReminders is well-implemented with proper asynchronous handling and conditional logic based on the fetched data.


34-55: The method sendMenteeCompleteProfileReminders mirrors the structure of the mentor reminder method, which maintains consistency in the controller's design.


105-135: Implementation of sendMentorshipFollowUpReminders correctly handles the complex logic of sending emails to both mentors and mentees based on the age of the mentorship match.

apps/nestjs-api/src/reminder-emails/reminder-emails.service.ts (5)

18-33: Initialization of AWS SES in the constructor of ReminderEmailsService is correctly configured with environment-specific parameters.


35-46: The method getDraftingConProfiles uses a clear and concise query to fetch profiles in drafting status, which is crucial for the reminder functionality.


67-130: The method getThreeMonthsOldMentorshipMatches and its transformation logic are well-implemented, ensuring that the necessary data is formatted correctly for the follow-up reminders.


171-223: The sendCompleteProfileReminder method is robust, handling potential errors in fetching the email template and sending emails through SES with appropriate error logging.


318-367: The sendMentorshipFollowUpReminder method is implemented with detailed attention to replacing placeholders in the email template, which is essential for personalized emails.

@helloanil helloanil merged commit ae784db into master Jun 8, 2024
2 checks passed
@helloanil helloanil deleted the connect-reminder-emails branch June 8, 2024 15:05
@katamatata katamatata moved this from QA by DevLead, DesignLead & PO to Done & Deployed in CON: ReDI Connect Jun 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
CON: ReDI Connect
Done & Deployed
Status: Done & Deployed
Development

Successfully merging this pull request may close these issues.

[CON | Automated Messages] Create new reminders for mentors & mentees for Germany and Cyberspace
3 participants