Skip to content

Send Institution Feedback Cron#515

Merged
belwalshubham merged 3 commits intodevelopfrom
feat/institution-feedback-cron
Nov 30, 2024
Merged

Send Institution Feedback Cron#515
belwalshubham merged 3 commits intodevelopfrom
feat/institution-feedback-cron

Conversation

@belwalshubham
Copy link
Copy Markdown
Collaborator

@belwalshubham belwalshubham commented Nov 29, 2024

Send the feedback email to institution POC on the day of camp

Summary by CodeRabbit

  • New Features

    • Enhanced email notification processes for material management team members, ensuring correct sender information.
    • Introduced an API for managing feedback collection related to institution camps, including automated feedback emails to organizing contacts.
    • Added a new "Volunteer Feedback" tab to the collection camp interface.
  • Bug Fixes

    • Improved error handling for missing recipient emails in logistics communications.

@belwalshubham belwalshubham self-assigned this Nov 29, 2024
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Nov 29, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request introduces enhancements to the InstitutionCollectionCampService class and adds a new API for managing feedback related to institution camps. The InstitutionCollectionCampService class now includes new imports for handling options, relationships, and email functionalities. It updates the email notification methods to improve error handling and ensure proper formatting of emails. Additionally, a new file, InstitutionCampFeedbackCron.php, is created to manage feedback collection, including functions for sending feedback emails and logging errors.

Changes

File Path Change Summary
wp-content/civi-extensions/goonjcustom/Civi/InstitutionCollectionCampService.php Added imports for OptionValue, Relationship, and Email. Updated mailNotificationToMmt and sendLogisticsEmail methods for improved email handling and error logging. New tab configuration for "Volunteer Feedback" added.
wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/InstitutionCampFeedbackCron.php Introduced a new API for feedback collection with functions for cron specification and email sending, including error handling.

Possibly related PRs

Suggested labels

status : ready for review

Suggested reviewers

  • tarunnjoshi

🎉 In the land of code where functions play,
New imports join the email fray!
Feedback flows like a gentle stream,
With error logs, we build our dream.
Camp services now shine so bright,
Sending messages with pure delight! 📧✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1de570f and e2946cb.

📒 Files selected for processing (1)
  • wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/InstitutionCampFeedbackCron.php (1 hunks)

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>, please review it.
    • 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 gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @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 using 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.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration 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.

Copy link
Copy Markdown

@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: 3

🧹 Outside diff range and nitpick comments (9)
wp-content/civi-extensions/goonjcustom/Civi/InstitutionCollectionCampService.php (5)

Line range hint 1-24: Consider splitting this class to follow Single Responsibility Principle

The class handles multiple distinct responsibilities:

  • QR code generation
  • Email notifications
  • Office management
  • UI tabset management
  • Event subscription

This violates the Single Responsibility Principle and makes the code harder to maintain.

Consider splitting this into smaller, focused service classes:

  • InstitutionCampQRService
  • InstitutionCampNotificationService
  • InstitutionCampOfficeService
  • InstitutionCampUIService

Line range hint 266-397: Refactor email-related methods to reduce duplication

The email sending logic is duplicated across multiple methods with similar patterns. This makes maintenance difficult and increases the chance of bugs.

Consider:

  1. Creating a reusable email template system
  2. Extracting common email sending logic into a separate method
  3. Using a configuration file for email subjects and content

Example refactor:

+ private static function sendEmail($recipient, $template, $params) {
+   $from = HelperService::getDefaultFromEmail();
+   $mailParams = [
+     'subject' => $params['subject'],
+     'from' => $from,
+     'toEmail' => $recipient['email'],
+     'replyTo' => $from,
+     'html' => self::renderTemplate($template, $params),
+   ];
+   return \CRM_Utils_Mail::send($mailParams);
+ }

Line range hint 266-284: Improve error handling in email sending logic

The error handling in the email sending logic is inconsistent. Some errors are logged while others are silently ignored.

Consider:

  1. Adding proper error handling for all email operations
  2. Using a consistent logging pattern
  3. Implementing retry logic for failed email attempts

Example improvement:

- if (!$recipientEmail) {
-   \Civi::log()->info("Recipient email missing: $campId");
- }
+ if (!$recipientEmail) {
+   \Civi::log()->error("Failed to send email - Recipient email missing for camp: $campId");
+   throw new \CRM_Core_Exception("Recipient email not found");
+ }

Line range hint 266-397: Break down long methods and improve documentation

The sendLogisticsEmail method is too long (130+ lines) and handles multiple responsibilities. This makes it difficult to understand and maintain.

Consider:

  1. Breaking down the method into smaller, focused methods
  2. Adding proper PHPDoc blocks
  3. Using meaningful variable names

Example refactor:

+ /**
+  * Sends logistics email for self-managed camps
+  *
+  * @param array $camp Camp details
+  * @param string $recipientEmail Recipient's email
+  * @return bool Success status
+  */
+ private static function sendSelfManagedCampEmail($camp, $recipientEmail) {
+   // Implementation
+ }

+ /**
+  * Sends logistics email for regular camps
+  *
+  * @param array $camp Camp details
+  * @param string $recipientEmail Recipient's email
+  * @return bool Success status
+  */
+ private static function sendRegularCampEmail($camp, $recipientEmail) {
+   // Implementation
+ }

Line range hint 398-428: Fix potential XSS vulnerabilities in email templates

The email templates directly inject variables into HTML without proper escaping, which could lead to XSS vulnerabilities.

Apply proper escaping:

- <p>Dear $contactName,</p>
- <p>Thank you for attending the camp <strong>$campCode</strong> at <strong>$campAddress</strong>.
+ <p>Dear <?php echo htmlspecialchars($contactName, ENT_QUOTES, 'UTF-8'); ?></p>
+ <p>Thank you for attending the camp <strong><?php echo htmlspecialchars($campCode, ENT_QUOTES, 'UTF-8'); ?></strong> at <strong><?php echo htmlspecialchars($campAddress, ENT_QUOTES, 'UTF-8'); ?></strong>.
wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/InstitutionCampFeedbackCron.php (4)

109-111: Provide PHPDoc comments for 'sendFeedbackEmail'

The sendFeedbackEmail function lacks a descriptive PHPDoc block. Adding appropriate documentation enhances code maintainability and provides clarity on the function's purpose and parameters.

Example:

/**
 * Generates the HTML content for the feedback email to the organizing contact.
 *
 * @param string $organizingContactName
 *   The name of the organizing contact.
 * @param int $collectionCampId
 *   The ID of the collection camp.
 * @param string $campAddress
 *   The address of the camp.
 *
 * @return string
 *   The HTML content of the feedback email.
 */
function generateFeedbackEmailContent($organizingContactName, $collectionCampId, $campAddress) {
  // ... function content ...
}

118-125: Externalize email content for maintainability and localization

The email subject and body are hardcoded within the code. To facilitate easier updates and support localization, consider using a templating system or storing the content in external configuration files.

For example, use the CiviCRM messaging templates or a template engine to manage email content:

// Example using CiviCRM template
$html = CRM_Core_Smarty::singleton()->fetch('YourTemplate.tpl', $templateVars);

This approach allows non-developers to modify email content without changing the code.


78-79: Standardize variable naming for clarity

The variable $contactEmailId holds an email address rather than an identifier. Renaming it to $contactEmail improves readability and accurately reflects its content.

Apply this diff:

-$contactEmailId = $campAttendedBy['email.email'];
+$contactEmail = $campAttendedBy['email.email'];
 $organizingContactName = $campAttendedBy['display_name'];

 $mailParams = [
   // ... other parameters ...
-  'toEmail' => $contactEmailId,
+  'toEmail' => $contactEmail,
   // ... other parameters ...
 ];

20-22: Remove or properly implement the empty specification function

The _civicrm_api3_goonjcustom_institution_camp_feedback_cron_spec function is currently empty. If no specification is needed, it can be removed. Otherwise, provide proper documentation or validations as required.

If removing:

-function _civicrm_api3_goonjcustom_institution_camp_feedback_cron_spec(&$spec) {
-  // There are no parameters for the Goonjcustom cron.
-}

If keeping, consider adding meaningful content or documentation.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ebc00c1 and 1a1c64d.

📒 Files selected for processing (2)
  • wp-content/civi-extensions/goonjcustom/Civi/InstitutionCollectionCampService.php (1 hunks)
  • wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/InstitutionCampFeedbackCron.php (1 hunks)

Comment on lines +101 to +103
catch (Exception $e) {
\Civi::log()->info("Error processing camp ID $collectionCampId: " . $e->getMessage());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix potential undefined variable in exception handling

In the catch block, the variable $collectionCampId may be undefined if an exception occurs before it is assigned. This could lead to an undefined variable notice or incorrect logging information.

Apply this diff to initialize $collectionCampId before the try block:

+    $collectionCampId = null;
     try {
       $endDate = new DateTime($camp['Institution_Collection_Camp_Intent.Collections_will_end_on_Date_']);
+      $collectionCampId = $camp['id'];
       // ... rest of the code ...
     } catch (Exception $e) {
       \Civi::log()->info("Error processing camp ID $collectionCampId: " . $e->getMessage());
     }

Committable suggestion skipped: line range outside the PR's diff.

$organizingContactName = $campAttendedBy['display_name'];

// Send email if the end date is today or earlier.
if (!$feedbackEmailSent && $endDateFormatted <= $todayFormatted) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Compare DateTime objects directly for accuracy

Comparing dates as formatted strings may lead to subtle bugs due to formatting differences. It's more reliable to compare DateTime objects directly.

Modify the condition to compare DateTime objects:

-$endDateFormatted = $endDate->format('Y-m-d');
-$todayFormatted = $today->format('Y-m-d');
 // ...

-if (!$feedbackEmailSent && $endDateFormatted <= $todayFormatted) {
+if (!$feedbackEmailSent && $endDate <= $today) {

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +112 to +128
function sendFeedbackEmail($organizingContactName, $collectionCampId, $campAddress) {
$homeUrl = \CRM_Utils_System::baseCMSURL();

// URL for the volunteer feedback form.
$campVolunteerFeedback = $homeUrl . 'volunteer-institution-camp-feedback/#?Eck_Collection_Camp1=' . $collectionCampId;

$html = "
<p>Dear $organizingContactName,</p>
<p>Thank you for stepping up and organising the recent collection drive at <strong>$campAddress</strong>! Your time, effort, and enthusiasm made all the difference, and we hope that it was a meaningful effort for you as well.</p>
<p>To help us improve, we’d love to hear your thoughts and experiences. Kindly take a few minutes to fill out our feedback form. Your input will be valuable to us:</p>
<p><a href=\"$campVolunteerFeedback\">Feedback Form Link</a></p>
<p>Feel free to share any highlights, suggestions, or challenges you faced. We're eager to learn how we can make it better together!</p>
<p>We look forward to continuing this journey together!</p>
<p>Warm Regards,<br>Team Goonj</p>";

return $html;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Rename 'sendFeedbackEmail' function for clarity

The function sendFeedbackEmail generates the email content but does not send the email. To adhere to the single responsibility principle and improve code readability, consider renaming the function to better reflect its purpose, such as generateFeedbackEmailContent.

Apply this diff to rename the function:

-function sendFeedbackEmail($organizingContactName, $collectionCampId, $campAddress) {
+function generateFeedbackEmailContent($organizingContactName, $collectionCampId, $campAddress) {
   // ... function content ...
 }

 // Update the function call:
 $mailParams = [
   // ... other parameters ...
-  'html' => sendFeedbackEmail($organizingContactName, $collectionCampId, $campAddress),
+  'html' => generateFeedbackEmailContent($organizingContactName, $collectionCampId, $campAddress),
 ];

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Copy Markdown

@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: 0

🧹 Outside diff range and nitpick comments (2)
wp-content/civi-extensions/goonjcustom/Civi/InstitutionCollectionCampService.php (2)

583-588: Consider refactoring to eliminate duplicate code in tab configurations

The 'template' parameter is the same for all tab configurations. You can reduce code duplication and improve maintainability by setting this default value within the loop instead of repeating it in each configuration.

Apply this diff to refactor the code:

      $tabConfigs = [
          'logistics' => [
              'title' => ts('Logistics'),
              'module' => 'afsearchInstitutionCollectionCampLogistics',
              'directive' => 'afsearch-institution-collection-camp-logistics',
-             'template' => 'CRM/Goonjcustom/Tabs/CollectionCamp.tpl',
          ],
          // ... other tab configurations ...
          'campFeedback' => [
              'title' => ts('Volunteer Feedback'),
              'module' => 'afsearchInstitutionCollectionCampFeedback',
              'directive' => 'afsearch-institution-collection-camp-feedback',
-             'template' => 'CRM/Goonjcustom/Tabs/CollectionCamp.tpl',
          ],
      ];

      foreach ($tabConfigs as $key => $config) {
          $tabs[$key] = [
              'id' => $key,
              'title' => $config['title'],
              'is_active' => 1,
+             'template' => 'CRM/Goonjcustom/Tabs/CollectionCamp.tpl',
              'module' => $config['module'],
              'directive' => $config['directive'],
          ];

          \Civi::service('angularjs.loader')->addModules($config['module']);
      }

583-588: Simplify generation of 'module' and 'directive' values

The 'module' and 'directive' values in your tab configurations follow a consistent pattern based on the key. You can simplify the code and reduce duplication by generating these values dynamically.

Apply this diff to refactor the code:

      $tabConfigs = [
          'logistics' => [
              'title' => ts('Logistics'),
          ],
          // ... other tab configurations ...
          'campFeedback' => [
              'title' => ts('Volunteer Feedback'),
          ],
      ];

      foreach ($tabConfigs as $key => $config) {
+         $moduleName = 'afsearchInstitutionCollectionCamp' . ucfirst($key);
+         $directiveName = 'afsearch-institution-collection-camp-' . $key;

          $tabs[$key] = [
              'id' => $key,
              'title' => $config['title'],
              'is_active' => 1,
              'template' => 'CRM/Goonjcustom/Tabs/CollectionCamp.tpl',
-             'module' => $config['module'],
-             'directive' => $config['directive'],
+             'module' => $moduleName,
+             'directive' => $directiveName,
          ];

          \Civi::service('angularjs.loader')->addModules($tabs[$key]['module']);
      }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1a1c64d and 1de570f.

📒 Files selected for processing (1)
  • wp-content/civi-extensions/goonjcustom/Civi/InstitutionCollectionCampService.php (2 hunks)

@belwalshubham
Copy link
Copy Markdown
Collaborator Author

Self Review Done, Due to Priority Merging this PR for now.

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.

1 participant