Skip to content

Dropping Center Feedback Cron Fixes#397

Merged
belwalshubham merged 3 commits intodevelopfrom
feat/feedback-cron-fixes
Oct 25, 2024
Merged

Dropping Center Feedback Cron Fixes#397
belwalshubham merged 3 commits intodevelopfrom
feat/feedback-cron-fixes

Conversation

@belwalshubham
Copy link
Copy Markdown
Collaborator

@belwalshubham belwalshubham commented Oct 25, 2024

Code Cleanups

Summary by CodeRabbit

  • New Features

    • Enhanced data retrieval for feedback email delivery status in the Dropping Center feedback processes.
    • Improved accuracy in filtering and logging of feedback email delivery statuses.
  • Bug Fixes

    • Corrected field references for feedback email delivery status, ensuring accurate data handling.
  • Refactor

    • Simplified access methods for feedback email delivery status fields, improving code clarity and maintainability.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 25, 2024

Walkthrough

This pull request modifies several files related to the handling of feedback email statuses in the Dropping Center functionality. Key changes include the simplification of field references from Status.Feedback_Email_Delivered:name to Status.Feedback_Email_Delivered across multiple functions. These adjustments affect how data is retrieved and processed, ensuring that the feedback email delivery status is accurately managed without altering the overall logic or structure of the methods involved.

Changes

File Path Change Summary
wp-content/civi-extensions/goonjcustom/Civi/DroppingCenterFeedbackService.php Updated processDroppingCenterStatus method to simplify field reference for Status.Feedback_Email_Delivered.
wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/BiannualDroppingCenterFeedbackCron.php Modified civicrm_api3_goonjcustom_biannual_dropping_center_feedback_cron to change field retrieval method and corrected status filter.
wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/FeedbackDroppingCenterCron.php Altered civicrm_api3_goonjcustom_feedback_dropping_center_cron to use simplified field references in data selection and processing.

Possibly related PRs

  • Feat/dropping center dispatch email #266: The changes in this PR involve modifying the handling of the Status.Feedback_Email_Delivered:name field to Status.Feedback_Email_Delivered, which aligns with the main PR's update to simplify field references in the DroppingCenterFeedbackService class.
  • Dropping Center: Goonj Office Allocation Based on State #281: This PR also deals with the DroppingCenterService class, which is related to the overall management of dropping center statuses, similar to the changes made in the main PR regarding feedback email handling.
  • Send Feedback Email When Dropping Center is Closed or sent every 6 month #393: This PR introduces a feedback email system that is triggered based on the status of the Dropping Center, which is directly related to the changes made in the main PR regarding the processDroppingCenterStatus method in the DroppingCenterFeedbackService class.

Suggested labels

status : reviewed

Suggested reviewers

  • tarunnjoshi
  • pokhiii

🎉 In the code's dance, a change so bright,
Fields simplified, now a clearer sight.
Feedback flows, no longer a name,
In Dropping Centers, it plays the game.
With each update, the logic stays true,
A seamless transition, for me and for you! 🌟


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.

@belwalshubham belwalshubham self-assigned this Oct 25, 2024
@belwalshubham belwalshubham changed the title Feedback Cron Fixes Dropping Center Feedback Cron Fixes Oct 25, 2024
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: 1

🧹 Outside diff range and nitpick comments (5)
wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/FeedbackDroppingCenterCron.php (2)

Line range hint 65-67: Enhance error logging with more context

The current error logging only includes the Dropping Center ID. Consider including more context about the failure to aid in debugging.

- \CRM_Core_Error::debug_log_message('Error processing Dropping Center ID: ' . $meta['Dropping_Center_Meta.Dropping_Center']);
+ \CRM_Core_Error::debug_log_message('Error processing Dropping Center ID: ' . $meta['Dropping_Center_Meta.Dropping_Center'] . 
+   ' - Error: ' . $e->getMessage() . 
+   ' - Initiator ID: ' . $initiatorId);

Line range hint 65-67: Consider transaction handling for batch operations

The foreach loop processes multiple records, but there's no transaction handling. If an error occurs mid-way, some records might be processed while others fail.

Consider wrapping the loop in a transaction to ensure atomic updates:

try {
  $transaction = new CRM_Core_Transaction();
  foreach ($droppingCenterMeta as $meta) {
    // ... existing code ...
  }
  $transaction->commit();
}
catch (Exception $e) {
  $transaction->rollback();
  \CRM_Core_Error::debug_log_message(...);
}
wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/BiannualDroppingCenterFeedbackCron.php (1)

Line range hint 20-63: Consider refactoring for better separation of concerns

The function civicrm_api3_goonjcustom_biannual_dropping_center_feedback_cron handles multiple responsibilities which makes it harder to maintain and test. Consider:

  1. Extracting the dropping center query logic into a separate service
  2. Improving error handling granularity
  3. Adding logging for successful operations

Would you like me to provide a detailed refactoring proposal that separates these concerns into distinct services?

wp-content/civi-extensions/goonjcustom/Civi/DroppingCenterFeedbackService.php (2)

Line range hint 26-43: Consider improving the processDroppingCenterStatus method.

The method could benefit from some improvements:

  1. The status check logic seems counterintuitive - it returns early if status is true, which means the feedback email is only sent when status is false.
  2. Missing PHPDoc description for the $status parameter.
  3. The method is handling multiple responsibilities (getting contact details, sending email, updating status).

Consider refactoring like this:

   /**
    * Send feedback email if it hasn't been sent yet.
    *
    * @param array $meta
    *   Meta data for the Dropping Center.
    * @param string $from
    *   Email address for 'from'.
+   * @param bool $status
+   *   Current feedback email delivery status.
    *
    * @throws \CRM_Core_Exception
    */
   public static function processDroppingCenterStatus($droppingCenterId, $initiatorId, $status, $from) {
+    // Skip if feedback email was already sent
+    if ($status) {
+      return;
+    }
+
     // Get recipient email and name.
     $contactDetails = self::getContactDetails($initiatorId);
-
     if ($contactDetails) {
       $contactEmailId = $contactDetails['email.email'];
       $organizingContactName = $contactDetails['display_name'];
-
-      if ($status) {
-        return;
-      }
-
       self::sendFeedbackEmail($organizingContactName, $droppingCenterId, $contactEmailId, $from);
-
       // Update status if the email is sent.
       EckEntity::update('Dropping_Center_Meta', TRUE)
         ->addValue('Status.Feedback_Email_Delivered', 1)
         ->addWhere('Dropping_Center_Meta.Dropping_Center', '=', $droppingCenterId)
         ->execute();
     }
   }

Let me analyze the search results. I can see that CRM_Utils_Mail::send returns a boolean value indicating success/failure, and several files in the codebase handle this properly:

  1. CollectionCampOutcomeService.php and CollectionCampVolunteerFeedbackService.php check the result and log errors
  2. Email/Send.php throws an API exception on failure
  3. VolunteerFeedbackCollectionCampCron.php checks the result before updating status
  4. ActionSchedule.php returns an error message on failure

The current implementation in DroppingCenterFeedbackService.php doesn't handle the failure case, which could lead to incorrect status updates.

Email sending failures should be handled before updating the status

The status should only be updated when the email is successfully sent. Consider this pattern used elsewhere in the codebase:

- self::sendFeedbackEmail($organizingContactName, $droppingCenterId, $contactEmailId, $from);
- 
- // Update status if the email is sent.
- EckEntity::update('Dropping_Center_Meta', TRUE)
-   ->addValue('Status.Feedback_Email_Delivered', 1)
-   ->addWhere('Dropping_Center_Meta.Dropping_Center', '=', $droppingCenterId)
-   ->execute();

+ $emailSendResult = self::sendFeedbackEmail($organizingContactName, $droppingCenterId, $contactEmailId, $from);
+ if (!$emailSendResult) {
+   \Civi::log()->error('Failed to send dropping center feedback email', [
+     'droppingCenterId' => $droppingCenterId,
+     'contactEmailId' => $contactEmailId
+   ]);
+   return;
+ }
+ 
+ // Update status only if email was sent successfully
+ EckEntity::update('Dropping_Center_Meta', TRUE)
+   ->addValue('Status.Feedback_Email_Delivered', 1)
+   ->addWhere('Dropping_Center_Meta.Dropping_Center', '=', $droppingCenterId)
+   ->execute();
🔗 Analysis chain

Line range hint 26-43: Consider adding error handling for email sending.

The method should handle potential failures in email sending to prevent updating the status when email delivery fails.

Let's check if there's any error handling in the email sending utility:

Consider wrapping the email sending in a try-catch block:

   public static function processDroppingCenterStatus($droppingCenterId, $initiatorId, $status, $from) {
     // Get recipient email and name.
     $contactDetails = self::getContactDetails($initiatorId);
     if ($contactDetails) {
       $contactEmailId = $contactDetails['email.email'];
       $organizingContactName = $contactDetails['display_name'];
-
       if ($status) {
         return;
       }
-
-      self::sendFeedbackEmail($organizingContactName, $droppingCenterId, $contactEmailId, $from);
-
-      // Update status if the email is sent.
-      EckEntity::update('Dropping_Center_Meta', TRUE)
-        ->addValue('Status.Feedback_Email_Delivered', 1)
-        ->addWhere('Dropping_Center_Meta.Dropping_Center', '=', $droppingCenterId)
-        ->execute();
+      try {
+        self::sendFeedbackEmail($organizingContactName, $droppingCenterId, $contactEmailId, $from);
+        
+        // Update status only if email is sent successfully
+        EckEntity::update('Dropping_Center_Meta', TRUE)
+          ->addValue('Status.Feedback_Email_Delivered', 1)
+          ->addWhere('Dropping_Center_Meta.Dropping_Center', '=', $droppingCenterId)
+          ->execute();
+      } catch (\Exception $e) {
+        \Civi::log()->error('Failed to send feedback email: ' . $e->getMessage());
+        throw new \CRM_Core_Exception('Failed to send feedback email');
+      }
     }
   }
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for error handling in CRM_Utils_Mail::send usage
rg -A 5 "CRM_Utils_Mail::send" 

Length of output: 17455

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 27cd74d and b2c12e4.

📒 Files selected for processing (3)
  • wp-content/civi-extensions/goonjcustom/Civi/DroppingCenterFeedbackService.php (1 hunks)
  • wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/BiannualDroppingCenterFeedbackCron.php (1 hunks)
  • wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/FeedbackDroppingCenterCron.php (2 hunks)
🔇 Additional comments (4)
wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/FeedbackDroppingCenterCron.php (2)

50-50: LGTM: Field selection change looks good!

The simplified field reference Status.Feedback_Email_Delivered maintains the same functionality while improving code clarity.


61-61: LGTM: Field access change is consistent!

The simplified field access aligns with the query changes above and maintains consistency across the codebase.

wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/BiannualDroppingCenterFeedbackCron.php (1)

43-46: Verify API field access pattern change

The change from Status.Feedback_Email_Delivered:name to Status.Feedback_Email_Delivered might affect how the data is retrieved. Let's verify this pattern is used consistently across the codebase.

✅ Verification successful

Field access pattern is consistent across the codebase

The change from :name suffix to direct field access for Status.Feedback_Email_Delivered is consistent with all other usages in the codebase. The search results show that:

  • No instances of the old pattern Status.Feedback_Email_Delivered:name exist
  • The new pattern Status.Feedback_Email_Delivered is used consistently across three files:
    • BiannualDroppingCenterFeedbackCron.php
    • FeedbackDroppingCenterCron.php
    • DroppingCenterFeedbackService.php
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining instances of the old pattern
rg "Status\.Feedback_Email_Delivered:name" 

# Search for the new pattern to ensure consistency
rg "Status\.Feedback_Email_Delivered[^:]" 

Length of output: 976

wp-content/civi-extensions/goonjcustom/Civi/DroppingCenterFeedbackService.php (1)

39-39: LGTM: Field reference simplification looks good.

The change from Status.Feedback_Email_Delivered:name to Status.Feedback_Email_Delivered aligns with the standardization across other files.

->execute();

$status = $droppingCenterMeta['Status.Feedback_Email_Delivered:name'];
$status = $droppingCenterMeta[0]['Status.Feedback_Email_Delivered'];
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

Add defensive programming checks

The direct array access $droppingCenterMeta[0] assumes the query always returns results. This could lead to undefined index errors.

Consider adding null checks:

-      $status = $droppingCenterMeta[0]['Status.Feedback_Email_Delivered'];
+      $status = !empty($droppingCenterMeta) ? $droppingCenterMeta[0]['Status.Feedback_Email_Delivered'] : null;
+      if ($status === null) {
+          \CRM_Core_Error::debug_log_message('No meta data found for dropping center ID: ' . $droppingCenterId);
+          continue;
+      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$status = $droppingCenterMeta[0]['Status.Feedback_Email_Delivered'];
$status = !empty($droppingCenterMeta) ? $droppingCenterMeta[0]['Status.Feedback_Email_Delivered'] : null;
if ($status === null) {
\CRM_Core_Error::debug_log_message('No meta data found for dropping center ID: ' . $droppingCenterId);
continue;
}

->execute();

$status = $droppingCenterMeta['Status.Feedback_Email_Delivered:name'];
$status = $droppingCenterMeta[0]['Status.Feedback_Email_Delivered'];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider the null check here

->addWhere('Dropping_Center_Meta.Dropping_Center', '=', $droppingCenterId)
->addWhere('Status.Status:name', '=', 'Parmanently_Closed')
->execute()->single();
->addWhere('Status.Status:name', '=', 'Permanently_Closed')
Copy link
Copy Markdown
Member

@tarunnjoshi tarunnjoshi Oct 25, 2024

Choose a reason for hiding this comment

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

Please refactor this:
Could we add a check here to filter out Status.Feedback_Email_Delivered? By doing this, the API will be optimized to return only the dropping centers that haven't yet received emails, making it more efficient.

->execute();

$status = $droppingCenterMeta['Status.Feedback_Email_Delivered:name'];
$status = !empty($droppingCenterMeta) ? $droppingCenterMeta[0]['Status.Feedback_Email_Delivered'] : null;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If this filtering is handled directly in the API, we can remove the corresponding line here as well as from the service file.

@tarunnjoshi
Copy link
Copy Markdown
Member

Please resolve conflicts before merging the PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants