refactor(tracking): TrackingTodoWriter → TrackingCandidateWriter (Phase 2 von #360) #363

Closed
opened 2026-05-20 20:58:28 +02:00 by admin-mrrm · 0 comments
Owner

Ziel

Phase 2 von Epic #360 (Day-Planner). Den bestehenden tracking-todo-writer so refactoren, dass er Candidates erzeugt (Tabelle aus #361) statt direkt list_items in eine 'Pakete'-Liste zu schreiben. Damit ist Tracking die erste Source, die dem Candidate-Pattern aus ADR 0001 folgt.

Begründung

  • ADR 0001 (docs/adr/0001-candidate-model.md) verbietet Direct-Write — tracking-todo-writer ist die letzte Direct-Write-Source und blockt #178 (Mail→Todo), das das Candidate-Pattern erst dann erzwingen kann, wenn Tracking als Vorbild dient.
  • Showstopper-Bugs #328/#329/#330 sind bereits closed; dieser Refactor ist pure pattern alignment, keine User-Bugfix.

Scope

Code

  • TrackingTodoWriterServiceTrackingCandidateWriterService (umbenennen, in eigenes Modul candidates/ ziehen — bleibt in tracking/ Modul referenziert)
  • Service erzeugt einen Candidate mit:
    • source = 'tracking'
    • sourceRef = '<trackingId>:<statusKey>' — encodiert die Status-Transition; mehrere Status-Wechsel desselben Pakets erzeugen verschiedene Candidates (z.B. OutForDelivery und später Delivered)
    • title, priority aus TodoGeneratorService.toTodo()
    • trackingId als Ref (FK auf parcel_trackings)
    • lifecycleState = 'pending' (Default)
    • completionPolicy = 'manual' (User markiert als done)
  • Auf ON CONFLICT (owner_sub, source, source_ref) DO NOTHING → idempotent gegenüber Re-Sync
  • TrackingSyncService ruft den neuen Writer auf statt todoWriter

Was wegfällt

  • ensureTodoList() und die 'Pakete'-Liste-Logik — wir schreiben nicht mehr in lists/list_items
  • Damit: Pakete-Liste in der UI bekommt keine neuen Items mehr. Bestehende Items bleiben unangetastet (kein Backfill, keine Migration). Phase 5 (Planner v0) + nachfolgende Tagesplan-UI liefern die User-sichtbare Darstellung der Candidates.

Tests

  • Unit: Writer erzeugt Candidate mit korrektem source/sourceRef/Title/Priority/Refs
  • Unit: zweiter Aufruf mit identischem (trackingId, status) ist No-Op (idempotent)
  • Unit: zwei verschiedene Statuses für dasselbe Tracking erzeugen zwei verschiedene Candidates
  • Unit: TrackingSyncService ruft den Candidate-Writer statt Todo-Writer
  • Integration: Schema-Sanity bleibt grün; ggf. Integration-Test der die Pipeline end-to-end durchläuft (nice-to-have)

Out-of-scope

  • Migrieren/Backfill bestehender Tracking-Todos in Candidates (siehe oben — diese bleiben als historische Items in der Pakete-Liste)
  • Markieren alter Candidates als obsolete bei Status-Wechsel (kommt in Phase 5+ wenn der Planner Lifecycle steuert)
  • UI für Candidates (Phase 5+)
  • Mail→Candidate (#178, Phase 3)

Acceptance

  • TrackingCandidateWriterService erzeugt Candidates statt Todos
  • TrackingSyncService ruft neuen Writer
  • Alte TrackingTodoWriterService-Datei gelöscht, alle Verweise sauber
  • Unit-Tests gruen, Integration-Tests gruen
  • Hinweis in PR/Wiki: Pakete-Liste wird nicht mehr befuellt; neue User-sichtbare Darstellung kommt in Phase 5+

Bezug

  • Voraussetzung: #361 (Candidate-Schema, geclosed mit Phase 1)
  • Epic: #360
  • Folge-Phase: #178 (Mail→Candidate)
  • Macht obsolet: TrackingTodoWriterService
## Ziel Phase 2 von Epic #360 (Day-Planner). Den bestehenden `tracking-todo-writer` so refactoren, dass er **Candidates erzeugt** (Tabelle aus #361) statt direkt `list_items` in eine 'Pakete'-Liste zu schreiben. Damit ist Tracking die erste Source, die dem Candidate-Pattern aus ADR 0001 folgt. ## Begründung - ADR 0001 (`docs/adr/0001-candidate-model.md`) verbietet Direct-Write — `tracking-todo-writer` ist die letzte Direct-Write-Source und blockt #178 (Mail→Todo), das das Candidate-Pattern erst dann erzwingen kann, wenn Tracking als Vorbild dient. - Showstopper-Bugs #328/#329/#330 sind bereits closed; dieser Refactor ist *pure pattern alignment*, keine User-Bugfix. ## Scope ### Code - `TrackingTodoWriterService` → `TrackingCandidateWriterService` (umbenennen, in eigenes Modul `candidates/` ziehen — bleibt in `tracking/` Modul referenziert) - Service erzeugt einen Candidate mit: - `source = 'tracking'` - `sourceRef = '<trackingId>:<statusKey>'` — encodiert die Status-Transition; mehrere Status-Wechsel desselben Pakets erzeugen verschiedene Candidates (z.B. `OutForDelivery` und später `Delivered`) - `title`, `priority` aus `TodoGeneratorService.toTodo()` - `trackingId` als Ref (FK auf `parcel_trackings`) - `lifecycleState = 'pending'` (Default) - `completionPolicy = 'manual'` (User markiert als done) - Auf `ON CONFLICT (owner_sub, source, source_ref) DO NOTHING` → idempotent gegenüber Re-Sync - `TrackingSyncService` ruft den neuen Writer auf statt todoWriter ### Was wegfällt - `ensureTodoList()` und die 'Pakete'-Liste-Logik — wir schreiben nicht mehr in `lists`/`list_items` - Damit: **Pakete-Liste in der UI bekommt keine neuen Items mehr**. Bestehende Items bleiben unangetastet (kein Backfill, keine Migration). Phase 5 (Planner v0) + nachfolgende Tagesplan-UI liefern die User-sichtbare Darstellung der Candidates. ### Tests - Unit: Writer erzeugt Candidate mit korrektem source/sourceRef/Title/Priority/Refs - Unit: zweiter Aufruf mit identischem (trackingId, status) ist No-Op (idempotent) - Unit: zwei verschiedene Statuses für dasselbe Tracking erzeugen zwei verschiedene Candidates - Unit: TrackingSyncService ruft den Candidate-Writer statt Todo-Writer - Integration: Schema-Sanity bleibt grün; ggf. Integration-Test der die Pipeline end-to-end durchläuft (nice-to-have) ## Out-of-scope - Migrieren/Backfill bestehender Tracking-Todos in Candidates (siehe oben — diese bleiben als historische Items in der Pakete-Liste) - Markieren alter Candidates als `obsolete` bei Status-Wechsel (kommt in Phase 5+ wenn der Planner Lifecycle steuert) - UI für Candidates (Phase 5+) - Mail→Candidate (#178, Phase 3) ## Acceptance - [ ] `TrackingCandidateWriterService` erzeugt Candidates statt Todos - [ ] `TrackingSyncService` ruft neuen Writer - [ ] Alte `TrackingTodoWriterService`-Datei gelöscht, alle Verweise sauber - [ ] Unit-Tests gruen, Integration-Tests gruen - [ ] Hinweis in PR/Wiki: Pakete-Liste wird nicht mehr befuellt; neue User-sichtbare Darstellung kommt in Phase 5+ ## Bezug - Voraussetzung: #361 (Candidate-Schema, geclosed mit Phase 1) - Epic: #360 - Folge-Phase: #178 (Mail→Candidate) - Macht obsolet: TrackingTodoWriterService
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
admin-mrrm/mrrmlabapp#363
No description provided.