Skip to content

Add Cron to send Reschedule email volunteer induction status is not Visited#459

Merged
nishant22029 merged 3 commits intodevelopfrom
feat/create-cron-to-send-reschedule-mail
Nov 16, 2024
Merged

Add Cron to send Reschedule email volunteer induction status is not Visited#459
nishant22029 merged 3 commits intodevelopfrom
feat/create-cron-to-send-reschedule-mail

Conversation

@nishant22029
Copy link
Copy Markdown
Collaborator

@nishant22029 nishant22029 commented Nov 15, 2024

  • Implemented a new cron job to send reschedule induction emails.
  • Added logic to mark a volunteer as "No Show" if they receive a reschedule email but fail to schedule an induction slot.
  • Enhanced checks to mark a volunteer as "No Show" if they do not attend after rescheduling their slot.

Summary by CodeRabbit

  • New Features

    • Introduced a method to send reschedule emails for induction activities.
    • Added a cron job API for managing unscheduled induction activities and sending follow-up emails.
  • Improvements

    • Enhanced logic for handling email notifications related to induction activities.
    • Improved error handling for email sending operations, ensuring better reliability.
    • Updated status management for induction activities based on email interactions.

@nishant22029 nishant22029 self-assigned this Nov 15, 2024
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Nov 15, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The changes in this pull request enhance the InductionService class and introduce a new API for managing induction rescheduling. Key modifications include the addition of methods for sending reschedule emails and handling email activities, as well as the creation of a cron job for sending follow-up emails for unscheduled induction activities. These updates improve the logic and control flow related to email notifications and the management of induction activities.

Changes

File Change Summary
wp-content/civi-extensions/goonjcustom/Civi/InductionService.php - Added methods: sendInductionRescheduleEmail() and handleRescheduleEmailActivity($contactId, $activityId).
- Modified sendFollowUpEmails to include checks for reschedule email activities.
wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/InductionRescheduleCron.php - Introduced functions: _civicrm_api3_goonjcustom_induction_reschedule_cron_spec(&$spec) and civicrm_api3_goonjcustom_induction_reschedule_cron($params) for handling induction rescheduling via a cron job.

Possibly related PRs

Suggested labels

status : ready for review

Suggested reviewers

  • tarunnjoshi

🎉 In the land of code, where functions play,
New methods sprouted, brightening the way.
With logs to guide us through each twist and turn,
Inductions now flourish, as we all learn.
So here’s to the changes, both big and small,
In the realm of Civi, we’re improving it all! 🚀


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.

@nishant22029 nishant22029 marked this pull request as draft November 15, 2024 09:47
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: 4

🧹 Outside diff range and nitpick comments (6)
wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/InductionRescheduleCron.php (4)

3-5: Remove unused imports

The Activity and MessageTemplate classes are imported but never used in this file. Consider removing these unused imports to maintain clean and clear code.

-use Civi\Api4\Activity;
-use Civi\Api4\MessageTemplate;
 use Civi\InductionService;

7-18: Fix documentation inconsistency

The API specification documentation refers to "InductionSlotBookingRescheduleMail" but the actual function is named "induction_reschedule_cron". Please update the documentation to match the actual implementation.

 /**
- * Goonjcustom.InductionSlotBookingRescheduleMail API specification (optional)
+ * Goonjcustom.InductionRescheduleCron API specification (optional)
  * This is used for documentation and validation.
  *

20-26: Fix documentation inconsistency

The function documentation refers to "induction_slot_booking_follow_up_cron" but the actual function is "induction_reschedule_cron". Please update the documentation to match the implementation.


37-47: Consider architectural improvements

A few suggestions to improve the implementation:

  1. The function mixes cron job scheduling with email sending logic. Consider separating these concerns:

    • Create a dedicated CronJob class to handle scheduling
    • Move email sending logic to a separate service
  2. Error handling could be more specific:

    • Catch specific exceptions rather than generic Exception
    • Add different error responses for different failure scenarios
    • Include more context in error messages
  3. Consider adding parameter validation even though no parameters are required currently:

    • Validate $params array
    • Add type hints

Here's a suggested refactor:

-function civicrm_api3_goonjcustom_induction_reschedule_cron($params) {
+function civicrm_api3_goonjcustom_induction_reschedule_cron(array $params): array {
     $returnValues = [];
     try {
-        InductionService::sendInductionRescheduleEmail();
+        // Validate parameters
+        if (!empty($params)) {
+            throw new InvalidArgumentException('This API endpoint does not accept any parameters');
+        }
+        
+        // Execute cron job
+        $cronJob = new InductionRescheduleCronJob();
+        $cronJob->execute();
+        
     } catch (Exception $e) {
-        \Civi::log()->error('Error in induction reschedule cron: ' . $e->getMessage());
+        $context = [
+            'error' => $e->getMessage(),
+            'trace' => $e->getTraceAsString(),
+        ];
+        \Civi::log()->error('Error in induction reschedule cron', $context);
         return civicrm_api3_create_error($e->getMessage());
     }
wp-content/civi-extensions/goonjcustom/Civi/InductionService.php (2)

601-707: Add missing PHPDoc for new methods

The newly added methods sendInductionRescheduleEmail and handleRescheduleEmailActivity lack PHPDoc comments. Including method documentation enhances code readability and provides valuable context for other developers and tools.

Apply this diff to add the missing documentation:

+/**
+ * Sends reschedule emails to volunteers whose induction status is 'Not Visited'.
+ * Updates the status to 'To be scheduled' or 'No_show' based on email activity.
+ */
public static function sendInductionRescheduleEmail() {

+/**
+ * Handles reschedule email activity for a volunteer.
+ * Updates the induction activity status to 'No_show' if a reschedule email was sent.
+ *
+ * @param int $contactId
+ *   The contact ID of the volunteer.
+ * @param int $activityId
+ *   The ID of the induction activity.
+ * @return bool
+ *   TRUE if the status was updated, FALSE otherwise.
+ */
public static function handleRescheduleEmailActivity($contactId, $activityId) {

678-707: Optimize email activity retrieval for performance

In the handleRescheduleEmailActivity method, retrieving all email activities without limiting the results can lead to performance issues, especially with a large dataset. Introduce a limit to the query to optimize performance.

Apply this diff to limit the query result:

$emailActivities = Activity::get(FALSE)
  ->addWhere('activity_type_id:name', '=', 'Email')
  ->addWhere('subject', '=', $template['msg_subject'])
  ->addWhere('source_contact_id', '=', $contactId)
+ ->setLimit(1)
  ->execute();

This ensures that only the first relevant email activity is retrieved, improving the method's efficiency.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 8853cdb and e5664df.

📒 Files selected for processing (2)
  • wp-content/civi-extensions/goonjcustom/Civi/InductionService.php (5 hunks)
  • wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/InductionRescheduleCron.php (1 hunks)
🔇 Additional comments (1)
wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/InductionRescheduleCron.php (1)

37-47: Verify implementation completeness

The current implementation seems to be missing some functionality described in the PR objectives:

  1. Logic to mark volunteers as "No Show" if they:

    • Receive a reschedule email but don't schedule an induction slot
    • Fail to attend their induction after rescheduling
  2. Checks for volunteer status being "Not Visited"

Please verify if these features are implemented in the InductionService::sendInductionRescheduleEmail() method.

return FALSE;
}

\Civi::log()->info('check4');

This comment was marked as off-topic.

Comment on lines +495 to +504
\Civi::log()->info('unscheduledInductionActivities', ['unscheduledInductionActivities'=>$unscheduledInductionActivities]);

// Process each activity in the batch
foreach ($unscheduledInductionActivities as $activity) {
// Check if a reschedule email has already been sent and handled
if (self::handleRescheduleEmailActivity($activity['source_contact_id'], $activity['id'])) {
\Civi::log()->info('Skipping follow-up email due to existing reschedule email activity');
continue;
}

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

Eliminate duplicate code by refactoring common logic

The methods sendFollowUpEmails (lines 495-504) and sendInductionRescheduleEmail (lines 606-673) share similar logic for fetching activities, checking email sent status, and sending emails. This duplication violates the DRY (Don't Repeat Yourself) principle and makes the code harder to maintain. Refactor the common functionality into a shared private method to enhance code readability and maintainability.

Here is how you can refactor the code:

  1. Create a private method to handle email sending logic:
private static function processInductionEmails($activityTypeName, $statusName, $templateTitle, $statusUpdate) {
  // Common logic for fetching activities, checking emails, and sending emails
}
  1. Modify sendFollowUpEmails method:
public static function sendFollowUpEmails() {
- // Existing implementation
+ self::processInductionEmails('Induction', 'To be scheduled', 'Induction_slot_booking_follow_up_email%', 'No_show');
}
  1. Modify sendInductionRescheduleEmail method:
public static function sendInductionRescheduleEmail() {
- // Existing implementation
+ self::processInductionEmails('Induction', 'Not Visited', 'Induction_reschedule_slot_booking%', 'To be scheduled');
}

This approach consolidates the shared logic, reduces code duplication, and adheres to best practices.

Also applies to: 606-673

Comment on lines +703 to +707
}

// Return false if no reschedule email activity exists or update failed
return false;
}
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

Correct inconsistent return value in handleRescheduleEmailActivity

The method handleRescheduleEmailActivity does not return a consistent boolean value. If the update fails, it currently returns false, but if the update succeeds, it returns true. However, if no email activity exists, it also returns false. This can be confusing for callers of the method.

Adjust the return statements to consistently reflect the outcome:

if (!empty($emailActivity)) {
  // Update status
  if ($updateResult) {
    return true;
  } else {
    return false;
  }
} else {
- return false;
+ // No email activity found
+ return null;
}

Alternatively, document the possible return values and their meanings in the method's PHPDoc to clarify the behavior.

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

Comment on lines +622 to +673
$notVisitedInductionActivities = Activity::get(FALSE)
->addSelect('id', 'source_contact_id', 'created_date')
->addWhere('activity_type_id:name', '=', 'Induction')
->addWhere('status_id:name', '=', 'Not Visited')
->addWhere('modified_date', '<', date('Y-m-d H:i:s', $rescheduleEmailTimestamp))
->setLimit($batchSize)
->setOffset($offset)
->execute();

\Civi::log()->info('notVisitedInductionActivities', ['notVisitedInductionActivities'=>$notVisitedInductionActivities]);

// // Process each activity in the batch
foreach ($notVisitedInductionActivities as $activity) {
// Check if a follow-up email has already been sent to avoid duplication.
$emailActivities = Activity::get(FALSE)
->addWhere('activity_type_id:name', '=', 'Email')
->addWhere('subject', '=', $template['msg_subject'])
->addWhere('source_contact_id', '=', $activity['source_contact_id'])
->execute();

\Civi::log()->info('emailActivities', ['emailActivities'=>$emailActivities]);

$emailActivity = $emailActivities->first();

if (!$emailActivity) {
\Civi::log()->info('activity', ['activity'=>$activity]);

$updateResult = Activity::update(FALSE)
->addValue('status_id:name', 'To be scheduled')
->addWhere('id', '=', $activity['id'])
->execute();
$emailParams = [
'contact_id' => $activity['source_contact_id'],
'template_id' => $template['id'],
];
civicrm_api3('Email', 'send', $emailParams);
}

if (!empty($emailActivity)){
\Civi::log()->info('check email sent for rescheduling');
$updateResult = Activity::update(FALSE)
->addValue('status_id:name', 'No_show')
->addWhere('id', '=', $activity['id'])
->execute();
}
}

// Move to the next batch by increasing the offset
$offset += $batchSize;

} while (count($notVisitedInductionActivities) === $batchSize);
}
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

Ensure consistent status updates and avoid logical errors

In the sendInductionRescheduleEmail method, the status updates for induction activities might lead to unexpected behavior. Specifically, the condition on lines 660-666 updates the status to 'No_show' even if an email was already sent. This could result in volunteers being incorrectly marked as 'No_show'.

Consider revising the logic to accurately reflect the volunteer's status:

if (!$emailActivity) {
  // Send reschedule email and update status to 'To be scheduled'
  // Existing code
} else {
-  // Update status to 'No_show'
-  $updateResult = Activity::update(FALSE)
-    ->addValue('status_id:name', 'No_show')
-    ->addWhere('id', '=', $activity['id'])
-    ->execute();
+  \Civi::log()->info('Reschedule email already sent; no action needed.');
}

This change prevents unintentional status updates and ensures that volunteers are not incorrectly marked as 'No_show'.

📝 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
$notVisitedInductionActivities = Activity::get(FALSE)
->addSelect('id', 'source_contact_id', 'created_date')
->addWhere('activity_type_id:name', '=', 'Induction')
->addWhere('status_id:name', '=', 'Not Visited')
->addWhere('modified_date', '<', date('Y-m-d H:i:s', $rescheduleEmailTimestamp))
->setLimit($batchSize)
->setOffset($offset)
->execute();
\Civi::log()->info('notVisitedInductionActivities', ['notVisitedInductionActivities'=>$notVisitedInductionActivities]);
// // Process each activity in the batch
foreach ($notVisitedInductionActivities as $activity) {
// Check if a follow-up email has already been sent to avoid duplication.
$emailActivities = Activity::get(FALSE)
->addWhere('activity_type_id:name', '=', 'Email')
->addWhere('subject', '=', $template['msg_subject'])
->addWhere('source_contact_id', '=', $activity['source_contact_id'])
->execute();
\Civi::log()->info('emailActivities', ['emailActivities'=>$emailActivities]);
$emailActivity = $emailActivities->first();
if (!$emailActivity) {
\Civi::log()->info('activity', ['activity'=>$activity]);
$updateResult = Activity::update(FALSE)
->addValue('status_id:name', 'To be scheduled')
->addWhere('id', '=', $activity['id'])
->execute();
$emailParams = [
'contact_id' => $activity['source_contact_id'],
'template_id' => $template['id'],
];
civicrm_api3('Email', 'send', $emailParams);
}
if (!empty($emailActivity)){
\Civi::log()->info('check email sent for rescheduling');
$updateResult = Activity::update(FALSE)
->addValue('status_id:name', 'No_show')
->addWhere('id', '=', $activity['id'])
->execute();
}
}
// Move to the next batch by increasing the offset
$offset += $batchSize;
} while (count($notVisitedInductionActivities) === $batchSize);
}
$notVisitedInductionActivities = Activity::get(FALSE)
->addSelect('id', 'source_contact_id', 'created_date')
->addWhere('activity_type_id:name', '=', 'Induction')
->addWhere('status_id:name', '=', 'Not Visited')
->addWhere('modified_date', '<', date('Y-m-d H:i:s', $rescheduleEmailTimestamp))
->setLimit($batchSize)
->setOffset($offset)
->execute();
\Civi::log()->info('notVisitedInductionActivities', ['notVisitedInductionActivities'=>$notVisitedInductionActivities]);
// // Process each activity in the batch
foreach ($notVisitedInductionActivities as $activity) {
// Check if a follow-up email has already been sent to avoid duplication.
$emailActivities = Activity::get(FALSE)
->addWhere('activity_type_id:name', '=', 'Email')
->addWhere('subject', '=', $template['msg_subject'])
->addWhere('source_contact_id', '=', $activity['source_contact_id'])
->execute();
\Civi::log()->info('emailActivities', ['emailActivities'=>$emailActivities]);
$emailActivity = $emailActivities->first();
if (!$emailActivity) {
\Civi::log()->info('activity', ['activity'=>$activity]);
$updateResult = Activity::update(FALSE)
->addValue('status_id:name', 'To be scheduled')
->addWhere('id', '=', $activity['id'])
->execute();
$emailParams = [
'contact_id' => $activity['source_contact_id'],
'template_id' => $template['id'],
];
civicrm_api3('Email', 'send', $emailParams);
}
if (!empty($emailActivity)){
\Civi::log()->info('Reschedule email already sent; no action needed.');
}
}
// Move to the next batch by increasing the offset
$offset += $batchSize;
} while (count($notVisitedInductionActivities) === $batchSize);
}

@nishant22029 nishant22029 marked this pull request as ready for review November 15, 2024 13:42
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 (3)
wp-content/civi-extensions/goonjcustom/Civi/InductionService.php (3)

496-503: Consider extracting email activity check into a reusable method.

The email activity check logic is duplicated across multiple methods. Consider extracting it into a private method for better maintainability.

+ private static function hasEmailActivityBeenSent($contactId, $templateSubject) {
+   $emailActivities = Activity::get(FALSE)
+     ->addWhere('activity_type_id:name', '=', 'Email')
+     ->addWhere('subject', '=', $templateSubject)
+     ->addWhere('source_contact_id', '=', $contactId)
+     ->execute();
+   return !empty($emailActivities->first());
+ }

671-703: Improve return value consistency in handleRescheduleEmailActivity.

The method's return values could be more explicit about the different scenarios.

 public static function handleRescheduleEmailActivity($contactId, $activityId) {
+  try {
     $template = MessageTemplate::get(FALSE)
       ->addSelect('id', 'msg_subject')
       ->addWhere('msg_title', 'LIKE', 'Induction_reschedule_slot_booking%')
       ->execute()->single();
+
+    if (!$template) {
+      \Civi::log()->warning('Reschedule email template not found');
+      return false;
+    }

     $emailActivities = Activity::get(FALSE)
       ->addWhere('activity_type_id:name', '=', 'Email')
       ->addWhere('subject', '=', $template['msg_subject'])
       ->addWhere('source_contact_id', '=', $contactId)
       ->execute();

     $emailActivity = $emailActivities->first();

     if (!empty($emailActivity)) {
       $updateResult = Activity::update(FALSE)
         ->addValue('status_id:name', 'No_show')
         ->addWhere('id', '=', $activityId)
         ->execute();

-      if ($updateResult) {
-        return true;
-      }
+      return !$updateResult->isError();
     }

-    return false;
+    return null;  // Indicates no email activity found
+  } catch (\Exception $e) {
+    \Civi::log()->error('Error in handleRescheduleEmailActivity: ' . $e->getMessage());
+    return false;
+  }
 }

600-703: Consider implementing rate limiting for email sending.

The email sending functionality in both new methods could benefit from rate limiting to prevent overwhelming the email server.

Consider implementing a rate limiter using a configuration parameter to control the maximum number of emails sent per minute. This would help prevent potential email server throttling or blacklisting.

Example configuration:

const EMAIL_RATE_LIMIT_PER_MINUTE = 60;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e5664df and 3ddd4b9.

📒 Files selected for processing (2)
  • wp-content/civi-extensions/goonjcustom/Civi/InductionService.php (4 hunks)
  • wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/InductionRescheduleCron.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • wp-content/civi-extensions/goonjcustom/api/v3/Goonjcustom/InductionRescheduleCron.php
🔇 Additional comments (1)
wp-content/civi-extensions/goonjcustom/Civi/InductionService.php (1)

Line range hint 134-147: LGTM!

The modifications to createInductionForVolunteer maintain proper error handling and logging.

Comment on lines +600 to +669


/**
*
*/
public static function sendInductionRescheduleEmail() {
$rescheduleEmailDelayDays = 1;
$rescheduleEmailTimestamp = strtotime("-{$rescheduleEmailDelayDays} days");

// Retrieve the email template for reschedule-email.
$template = MessageTemplate::get(FALSE)
->addSelect('id', 'msg_subject')
->addWhere('msg_title', 'LIKE', 'Induction_reschedule_slot_booking%')
->execute()->single();

$batchSize = 25;
$offset = 0;

do {
// Retrieve a batch of not visited induction activities older than 1 days
$notVisitedInductionActivities = Activity::get(FALSE)
->addSelect('id', 'source_contact_id', 'created_date')
->addWhere('activity_type_id:name', '=', 'Induction')
->addWhere('status_id:name', '=', 'Not Visited')
->addWhere('modified_date', '<', date('Y-m-d H:i:s', $rescheduleEmailTimestamp))
->setLimit($batchSize)
->setOffset($offset)
->execute();

foreach ($notVisitedInductionActivities as $activity) {
// Check if a follow-up email has already been sent
$emailActivities = Activity::get(FALSE)
->addWhere('activity_type_id:name', '=', 'Email')
->addWhere('subject', '=', $template['msg_subject'])
->addWhere('source_contact_id', '=', $activity['source_contact_id'])
->execute();

$emailActivity = $emailActivities->first();

if ($emailActivity) {
// If an email already exists, mark activity as 'No Show'
$updateResult = Activity::update(FALSE)
->addValue('status_id:name', 'No_show')
->addWhere('id', '=', $activity['id'])
->execute();
continue;
}

// If no email exists, mark activity for to be scheduled and send the email
$updateResult = Activity::update(FALSE)
->addValue('status_id:name', 'To be scheduled')
->addWhere('id', '=', $activity['id'])
->execute();

if ($updateResult->isError()) {
continue;
}

$emailParams = [
'contact_id' => $activity['source_contact_id'],
'template_id' => $template['id'],
];

$emailResult = civicrm_api3('Email', 'send', $emailParams);
}

$offset += $batchSize;

} while (count($notVisitedInductionActivities) === $batchSize);
}
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

Improve error handling in sendInductionRescheduleEmail method.

The method lacks proper error handling for the email sending operation and template retrieval.

 public static function sendInductionRescheduleEmail() {
+  try {
     $template = MessageTemplate::get(FALSE)
       ->addSelect('id', 'msg_subject')
       ->addWhere('msg_title', 'LIKE', 'Induction_reschedule_slot_booking%')
       ->execute()->single();
+
+    if (!$template) {
+      throw new \Exception('Reschedule email template not found');
+    }
     // ... rest of the method ...
     $emailResult = civicrm_api3('Email', 'send', $emailParams);
+    if ($emailResult['is_error']) {
+      \Civi::log()->error('Failed to send reschedule email', [
+        'contact_id' => $activity['source_contact_id'],
+        'error' => $emailResult['error_message']
+      ]);
+    }
+  } catch (\Exception $e) {
+    \Civi::log()->error('Error in sendInductionRescheduleEmail: ' . $e->getMessage());
+    throw $e;
+  }
 }

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

* Handles induction creation for a volunteer.
*/
public static function createInductionForVolunteer(string $op, string $objectName, int $objectId, &$objectRef) {

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.

remove it

->setOffset($offset)
->execute();


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.

remove extra line

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.

2 participants