--- phase: 06-email-notifications plan: 03 type: execute depends_on: ["06-01", "06-02"] files_modified: [includes/class-notifications.php, includes/class-scheduler.php] --- Send async batch email notifications to opted-in mentors when jobs are published, preventing timeouts with background processing. Purpose: Notify mentors about new job opportunities in real-time without blocking the admin's publish action, respecting user opt-in preferences and email provider limits. Output: Automated email notifications to opted-in mentors on job publish, processed asynchronously in batches. ~/.claude/get-shit-done/workflows/execute-plan.md ./summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md # Prior work this plan builds on: @.planning/phases/03-job-management-core/03-03-SUMMARY.md @.planning/phases/04-job-deactivation-system/04-02-SUMMARY.md @.planning/phases/05-mentor-job-board/05-02-SUMMARY.md @.planning/phases/06-email-notifications/06-01-SUMMARY.md @.planning/phases/06-email-notifications/06-02-SUMMARY.md # Source files: @includes/class-notifications.php @includes/class-scheduler.php @includes/class-user-preferences.php **Tech stack available:** Action Scheduler (from 06-02), wp_mail, get_user_meta, WP_User_Query, get_field (ACF), transition_post_status hook **Established patterns:** - German email templates with error logging (Phase 03-03, 04-02, 05-02) - transition_post_status hook for detecting status changes (Phase 03-03, 04-02) - Notification class with static methods (Phase 03-03) - Action Scheduler batch processing (Phase 06-02) **Constraining decisions:** - Phase 06-01: User meta 'ddhh_jm_notify_new_jobs' indicates opt-in status - Phase 06-01: get_opted_in_mentors() returns array of opted-in user IDs - Phase 06-02: schedule_mentor_notification_batch() handles batch scheduling - Phase 06-02: Callback hook 'ddhh_jm_send_mentor_notification_batch' needs implementation - Phase 03-03: Email templates in German, use error_log for failures - Phase 03-03: Only trigger on specific transitions (avoid spam on every save) - PROJECT.md line 27: "Mentor opt-in notification system for new published jobs" Task 1: Add job publish hook to schedule mentor notifications includes/class-notifications.php Add method notify_mentors_on_job_publish() to DDHH_JM_Notifications class. Hook to transition_post_status at priority 10 following established pattern. Method parameters: $new_status, $old_status, $post. Check: (1) post_type is 'job_offer', (2) new_status is 'publish', (3) old_status is NOT 'publish' (only notify on initial publish, not updates). If checks pass, get opted-in mentors via DDHH_JM_User_Preferences::get_opted_in_mentors(). If empty array, log "No opted-in mentors to notify" and return (no error - valid scenario). If mentors found, call DDHH_JM_Scheduler::schedule_mentor_notification_batch() with mentor IDs and $post->ID. Log success with count: "Scheduled X notification batches for job ID Y". Register hook in setup_hooks() method: add_action('transition_post_status', array(__CLASS__, 'notify_mentors_on_job_publish'), 10, 3). This triggers async batch processing without blocking the publish action. Check includes/class-notifications.php contains notify_mentors_on_job_publish() method. Verify transition_post_status hook registered in setup_hooks(). Confirm method only triggers on pending/draft→publish transitions. Verify calls to user preferences and scheduler classes. Job publish hook implemented, triggers only on initial publish, queries opted-in mentors, schedules async batches via scheduler, hook registered in notifications class Task 2: Implement async batch email processor callback includes/class-scheduler.php Add method process_mentor_notification_batch() to DDHH_JM_Scheduler class. Method parameters: $user_ids (array), $job_id (int). For each user ID in batch: (1) Get user data with get_userdata($user_id), skip if null (user deleted). (2) Get user email. (3) Get job details: post_title, get_field('job_location'), get_field('job_type'), permalink (for "View Job" link). (4) Prepare German email subject: "Neues Stellenangebot: {job_title}". (5) Prepare German email body: "Hallo,\n\nein neues Stellenangebot wurde veröffentlicht:\n\nStelle: {job_title}\nStandort: {job_location}\nArt: {job_type}\n\nSie können das Angebot hier ansehen:\n{permalink}\n\nUm keine weiteren Benachrichtigungen zu erhalten, können Sie diese in Ihrem Profil deaktivieren.\n\nDiese E-Mail wurde automatisch gesendet." (6) Send email with wp_mail($email, $subject, $body). (7) If wp_mail fails, log error: "Failed to send mentor notification to user {$user_id} for job {$job_id}". (8) Add small delay (usleep(100000) = 0.1 seconds) between emails to avoid rate limits. After loop, log success: "Processed notification batch: {count} emails sent for job {$job_id}". Register callback in setup_hooks(): add_action('ddhh_jm_send_mentor_notification_batch', array(__CLASS__, 'process_mentor_notification_batch'), 10, 2). This executes asynchronously when Action Scheduler processes the queue. Check includes/class-scheduler.php contains process_mentor_notification_batch() method. Verify callback registered in setup_hooks() for hook 'ddhh_jm_send_mentor_notification_batch'. Confirm German email template with job details and permalink. Verify error logging for failed sends. Confirm rate limit delay between emails. Batch processor callback implemented, sends German emails with job details, includes unsubscribe hint, logs errors, has rate limit delay, callback registered for Action Scheduler hook Before declaring plan complete: - [ ] Job publish hook triggers only on initial publish (not updates) - [ ] Opted-in mentors queried via user preferences class - [ ] Batch scheduling called via scheduler class - [ ] Async callback registered for Action Scheduler hook - [ ] Email template in German with job details - [ ] Error logging for failures - [ ] Rate limit delay between emails - [ ] Unsubscribe hint included in emails - Job publish triggers async mentor notifications - Only opted-in mentors receive emails - Emails processed in background (no blocking) - Batches of 50 users prevent timeouts - German email template with job details and link - Error logging for debugging - Rate limit compliance (0.1s delay between sends) - Users informed how to opt-out in email - Phase 6 complete - async notification system fully functional After completion, create `.planning/phases/06-email-notifications/06-03-SUMMARY.md`: # Phase 6 Plan 3: Async Mentor Notifications Summary **[Substantive one-liner - what shipped, not "phase complete"]** ## Accomplishments - [Key outcome 1] - [Key outcome 2] ## Files Created/Modified - `includes/class-notifications.php` - Description - `includes/class-scheduler.php` - Description ## Decisions Made [Key decisions and rationale, or "None"] ## Issues Encountered [Problems and resolutions, or "None"] ## Next Step Phase 6 complete. Ready for Phase 7: Testing & Polish (end-to-end testing, UI refinement, deployment preparation).