# UpdateStatus Workflow Update job application status in both SeriousLetter and job-room.ch (ORP). **Trigger:** "update job", "job status", "rejected by X", "got interview at X", ": " --- ## CRITICAL RULES 1. **NEVER ask for confirmation** - when user reports a status change, update both SL and ORP immediately 2. **ALWAYS update both systems** - SeriousLetter AND job-room.ch, every time 3. **Use ORP API, NOT UI clicks** - POST /_action/update-work-effort via page.evaluate(fetch()) 4. **Full reference**: See `memory/orp-internal-api.md` for complete API docs --- ## Step 1: Update SeriousLetter ``` sl_search_jobs(q: "company name") # Find the job sl_update_job(job_uuid, status: "rejected", rejected_date: "YYYY-MM-DD") ``` **Valid statuses:** opportunity, editing, applied, rejected, not_applying, outdated --- ## Step 2: Sync to ORP (Create Entry if Missing) ``` sl_jobroom_sync_job(job_uuid) # Creates ORP entry if it doesn't exist ``` This handles new entry creation. If the entry already exists, it skips (dedup). --- ## Step 3: Update ORP Status via API Navigate to job-room.ch in Playwright (any page), then use internal API: ### 3a. Find the work effort ```javascript await page.evaluate(async () => { const token = sessionStorage.getItem('authenticationToken'); const userId = 'USER_ID'; // See known IDs below const resp = await fetch( `/onlineform-service/api/npa/_search/by-owner-user-id?userId=${userId}&_ng=ZGU=`, { headers: { 'Authorization': token, 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' } } ); const data = await resp.json(); const proof = data.content[0]; return proof.workEfforts.find(we => we.applyChannel.address.name.includes('COMPANY') ); }); ``` **Response structure:** `{ content: [{ id: proofId, workEfforts: [...] }] }` - Access via `data.content[0].workEfforts` (NOT `data[0]` - it's NOT a plain array) ### 3b. Update status ```javascript await page.evaluate(async (we) => { const token = sessionStorage.getItem('authenticationToken'); const userId = 'USER_ID'; // Modify the existing payload - it's a FULL REPLACE we.applyStatus = ['REJECTED']; // or ['EMPLOYED'], ['PENDING'] we.rejectionReason = 'Absage erhalten am DD.MM.YYYY'; const resp = await fetch( `/onlineform-service/api/npa/_action/update-work-effort?userId=${userId}&_ng=ZGU=`, { method: 'POST', headers: { 'Authorization': token, 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify(we) } ); return { status: resp.status }; // 201 = success }, workEffort); ``` --- ## Known User IDs | User | userId | |------|--------| | Matthias | `591489d5-0039-11f1-a99a-462689f09ec3` | | Gina | `703d651c-0412-11f1-a99a-462689f09ec3` | --- ## ORP Status Values | SL Status | ORP applyStatus | ORP rejectionReason | |-----------|----------------|---------------------| | rejected | `["REJECTED"]` | "Absage erhalten am DD.MM.YYYY" | | applied | `["PENDING"]` | null | | rejected + interview | `["REJECTED", "INTERVIEW"]` | reason text | --- ## Authentication Notes - Token: `sessionStorage.getItem('authenticationToken')` - already includes auth prefix - `_ng=ZGU=` is just `base64("de")` (language key), NOT a CSRF token - Must run inside Playwright browser context - curl returns 401 - Token expires ~10h after login --- ## Status-Specific Actions ### Rejection 1. `sl_update_job(status: "rejected", rejected_date: today)` 2. `sl_jobroom_sync_job(job_uuid)` (ensure entry exists) 3. ORP API: set `applyStatus: ["REJECTED"]`, `rejectionReason: "Absage erhalten am DD.MM.YYYY"` ### Interview 1. `sl_update_job(interview_date: "YYYY-MM-DD")` 2. ORP API: add `"INTERVIEW"` to applyStatus array ### Applied (new application) 1. `sl_update_job(status: "applied", applied_date: today)` 2. `sl_jobroom_sync_job(job_uuid)` handles creation with PENDING status --- **Last Updated:** 2026-03-17