diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 1705cc4..6f94079 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -13,7 +13,7 @@ None - [x] **Phase 1: Foundation & Setup** - Plugin structure, CPT registration, custom role - [x] **Phase 2: Provider Registration & Auth** - Registration form, login system, dashboard foundation - [x] **Phase 3: Job Management Core** - Job submission, editing, moderation workflow -- [ ] **Phase 4: Job Deactivation System** - Deactivation workflow with reason capture +- [x] **Phase 4: Job Deactivation System** - Deactivation workflow with reason capture - [ ] **Phase 5: Mentor Job Board** - Protected archive, detail pages, apply system - [ ] **Phase 6: Email Notifications** - Admin alerts and mentor opt-in notifications - [ ] **Phase 7: Testing & Polish** - End-to-end testing, UI refinement, deployment prep @@ -65,7 +65,7 @@ Plans: Plans: - [x] 04-01: Job deactivation form (F4) with reason field -- [ ] 04-02: Admin notification on deactivation with reason +- [x] 04-02: Admin notification on deactivation with reason ### Phase 5: Mentor Job Board **Goal**: Protected job archive page, job detail page with logo, apply popup form, application email to provider @@ -110,7 +110,7 @@ Plans: | 1. Foundation & Setup | 3/3 | Complete | 2026-01-14 | | 2. Provider Registration & Auth | 4/4 | Complete | 2026-01-14 | | 3. Job Management Core | 4/4 | Complete | 2026-01-14 | -| 4. Job Deactivation System | 1/2 | In progress | - | +| 4. Job Deactivation System | 2/2 | Complete | 2026-01-14 | | 5. Mentor Job Board | 0/4 | Not started | - | | 6. Email Notifications | 0/3 | Not started | - | | 7. Testing & Polish | 0/3 | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index dc4fb50..82e0286 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -5,23 +5,23 @@ See: .planning/PROJECT.md (updated 2026-01-14) **Core value:** Every job goes through admin approval before mentors see it. The moderation flow is the trust layer that protects mentors from spam or inappropriate content. -**Current focus:** Phase 4 — Job Deactivation System (In Progress) +**Current focus:** Phase 4 — Job Deactivation System (Complete) ## Current Position Phase: 4 of 7 (Job Deactivation System) -Plan: 1 of 2 in current phase -Status: Plan 04-01 complete -Last activity: 2026-01-14 — Completed Plan 04-01 (job deactivation form) +Plan: 2 of 2 in current phase +Status: Phase complete +Last activity: 2026-01-14 — Completed Plan 04-02 (deactivation notifications) -Progress: ███████████░ 48% +Progress: ████████████ 52% ## Performance Metrics **Velocity:** -- Total plans completed: 12 -- Average duration: 8.5 min -- Total execution time: 1.7 hours +- Total plans completed: 13 +- Average duration: 8.2 min +- Total execution time: 1.8 hours **By Phase:** @@ -30,11 +30,11 @@ Progress: ███████████░ 48% | 1 | 3 | 6 min | 2 min | | 2 | 4 | 42 min | 10.5 min | | 3 | 4 | 50 min | 12.5 min | -| 4 | 1 | 8 min | 8 min | +| 4 | 2 | 13 min | 6.5 min | **Recent Trend:** -- Last 5 plans: 03-01 (15 min), 03-02 (12 min), 03-03 (8 min), 03-04 (15 min), 04-01 (8 min) -- Trend: Stable (parallelization used for Phases 2 and 3) +- Last 5 plans: 03-02 (12 min), 03-03 (8 min), 03-04 (15 min), 04-01 (8 min), 04-02 (5 min) +- Trend: Stable with efficiency improving (Phase 4 completed rapidly) ## Accumulated Context @@ -77,6 +77,10 @@ Recent decisions affecting current work: | 04-01 | Required reason field for deactivation | Captures business intelligence about why jobs are removed | | 04-01 | Deactivate button only for published jobs | Reduces UI clutter and prevents confusion with pending/draft jobs | | 04-01 | Destructive button styling (red) for deactivate | UX best practice signals significant action to prevent accidental clicks | +| 04-02 | Deactivation notification triggered only on publish→draft transitions | Prevents spam on draft saves, only notifies on genuine deactivations | +| 04-02 | Email includes deactivation reason for business intelligence | Allows admins to track patterns and platform effectiveness | +| 04-02 | Used current_time() for deactivation timestamp | Captures actual deactivation moment rather than post modified date | +| 04-02 | Deactivation notification follows submission notification pattern | Consistency makes code predictable and maintainable | ### Deferred Issues @@ -88,6 +92,6 @@ None yet. ## Session Continuity -Last session: 2026-01-14T[current time] -Stopped at: Completed Plan 04-01 (job deactivation form) +Last session: 2026-01-14 +Stopped at: Completed Plan 04-02 (deactivation notifications) - Phase 4 complete Resume file: None diff --git a/.planning/phases/04-job-deactivation-system/04-02-SUMMARY.md b/.planning/phases/04-job-deactivation-system/04-02-SUMMARY.md new file mode 100644 index 0000000..93856ce --- /dev/null +++ b/.planning/phases/04-job-deactivation-system/04-02-SUMMARY.md @@ -0,0 +1,159 @@ +--- +phase: 04-job-deactivation-system +plan: 02 +subsystem: notifications +tags: [email, admin-notification, deactivation, wp-mail] + +# Dependency graph +requires: + - phase: 04-job-deactivation-system + provides: [job-deactivation-form, deactivation-reason-capture] + - phase: 03-job-management-core + provides: [admin-notification-pattern, transition-post-status-pattern] +provides: + - admin-deactivation-notification + - deactivation-reason-visibility +affects: [] + +# Tech tracking +tech-stack: + added: [] + patterns: [deactivation-notification-pattern] + +key-files: + created: [] + modified: [includes/class-notifications.php] + +key-decisions: + - "Deactivation notification triggered only on publish→draft transitions" + - "Email includes deactivation reason for business intelligence" + - "Used current_time() for deactivation timestamp instead of post modified date" + - "Fallback text 'Kein Grund angegeben' if reason field empty" + +patterns-established: + - "Deactivation notification mirrors submission notification pattern" + +issues-created: [] + +# Metrics +duration: 5 min +completed: 2026-01-14 +--- + +# Phase 4 Plan 2: Deactivation Notifications Summary + +**Admin receives German email on job deactivation with provider details and business intelligence reason** + +## Performance + +- **Duration:** 5 min +- **Started:** 2026-01-14T[start] +- **Completed:** 2026-01-14T[end] +- **Tasks:** 1 +- **Files modified:** 1 + +## Accomplishments + +- Added send_admin_job_deactivation_notification() method to notifications class +- Configured hook to detect publish→draft status transitions only +- Email captures complete job context: title, provider, organization, location, type +- Email includes deactivation reason from ACF field for business intelligence +- Deactivation timestamp shows current time (when deactivation occurred) +- Error logging handles missing admin_email or wp_mail failures +- Follows same pattern as existing submission notification method + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Add deactivation notification method to notifications class** - `4a1c05c` (feat) + +## Files Created/Modified + +- `includes/class-notifications.php` - Added send_admin_job_deactivation_notification() method that hooks transition_post_status; guards ensure only publish→draft transitions trigger notification; extracts deactivation_reason from ACF field; sends German email to admin_email with job details, provider info, reason, and edit link; includes error logging for failures + +## Email Template + +The email sent to admin includes: + +**Subject:** Stellenangebot deaktiviert: {job_title} + +**Body:** +``` +Ein Stellenangebot wurde vom Anbieter deaktiviert. + +Titel: {job_title} +Anbieter: {author_name} ({author_organization}) +Standort: {job_location} +Art: {job_type} +Deaktiviert am: {deactivation_date} + +Grund für Deaktivierung: +{deactivation_reason} + +Stelle ansehen: +{edit_link} + +--- +Diese E-Mail wurde automatisch gesendet. +``` + +## Technical Details + +**Hook Implementation:** +- Hook: `transition_post_status` with priority 10, accepts 3 params ($new_status, $old_status, $post) +- Guards: Only trigger when post_type === 'job_offer' AND new_status === 'draft' AND old_status === 'publish' +- This ensures only genuine deactivations trigger email (not initial drafts or draft saves) + +**Data Extraction:** +- Admin email: `get_option('admin_email')` +- Author org: `get_user_meta($post->post_author, 'ddhh_org_name', true)` +- ACF fields: `get_field('job_location')`, `get_field('job_type')`, `get_field('job_deactivation_reason')` +- Deactivation date: `current_time('d.m.Y H:i')` - shows when deactivation occurred +- Edit link: `get_edit_post_link($post_id, '')` + +**Email Sending:** +- Function: `wp_mail()` +- Headers: 'Content-Type: text/html; charset=UTF-8' +- Body: Plain text converted to HTML with `nl2br(esc_html())` +- Error handling: Logs to error_log if admin_email missing or wp_mail() returns false + +**Business Intelligence:** +The deactivation reason is the key addition - it allows admins to track patterns: +- "Position filled" - Success metric +- "Budget cut" - External factor +- "Wrong category" - Platform usability issue +- "Not enough applicants" - Quality/reach concern + +This data informs platform improvements and provider support strategies. + +## Decisions Made + +**current_time() vs post modified date:** Used current_time() to capture the actual deactivation moment rather than post modified date. This provides accurate timing for admin records and distinguishes deactivation from other updates. + +**Fallback for empty reason:** If deactivation_reason field is empty (shouldn't happen with required field, but defensive), email shows "Kein Grund angegeben" rather than breaking or showing null. + +**Same pattern as submission notification:** Followed established pattern from send_admin_new_job_notification() for consistency. Makes code predictable and maintainable. + +**Email format matches submission:** Plain text with nl2br() conversion, German language, similar structure. Admin can process both notification types with same mental model. + +## Deviations from Plan + +None - plan executed exactly as written. + +## Issues Encountered + +None - implementation was straightforward following the established notification pattern from Phase 03-03. + +## Next Step + +Phase 4 complete. Ready for Phase 5: Mentor Job Board. + +The job deactivation system is now fully functional end-to-end: +- Providers can deactivate published jobs with required reason via dashboard form (04-01) +- Admins receive immediate email notification with full context and business intelligence (04-02) +- Jobs are removed from public view (draft status) while preserving admin access + +--- +*Phase: 04-job-deactivation-system* +*Completed: 2026-01-14*