Files
F-r-ldraledigplannerare/SENIOR_FOLLOWUP_2.md
T
jacobh2 fbb7a04580 Phase 1: Fix TypeScript compilation — add missing API functions and fix hook signatures
- Add 8 missing API client functions (getBreakPeriods, createBreakPeriod, deleteBreakPeriod, getTips, getParentalLeave, getPlannedDays, createPlannedDay, deletePlannedDay)
- Fix useAnalytics to accept optional childId parameter
- Fix ApiError strict optional properties handling
- Export HeaderProps from Header component
- Update hook tests to use correct data structures and optional parameters

npx tsc --noEmit now passes with zero errors.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-01 17:47:17 +02:00

48 lines
3.7 KiB
Markdown

# Senior Developer — Follow-up Tasks (Round 2)
**Date:** 2026-06-01
**Baseline:** `SENIOR_REPORT_2.md`, verified against the committed code.
All six actionable items from `SENIOR_FOLLOWUP.md` check out in the repo: the `scraper_enabled` flag now gates the scraper routes, `TipsService` reads the real `planning_goal` from the workspace, `BreakPeriodUpdate` documents its PUT/full-replacement semantics, rate-limit decorators are on the auth and fetch endpoints, the holiday helper uses the `language="sv"` locale, the CI gate is at 40%, and `conftest` seeds a `child_id`. The backend is in solid shape. Two focused things remain for you.
---
## 1. Wire the tips-engine rule logic — `services/tips_service.py` (main task)
9 of the 12 rules still return `None`. These are the headline domain logic and were senior-owned from the start; they're nuanced enough to warrant your eye, and they're now end-to-end testable since `_build_context` reads the real `planning_goal`. Implement each, with tests, using the predicate helpers in `utils/tip_predicates.py`:
| Rule | Key predicate / data |
|---|---|
| `balance_between_parents` | compare `days_used` across parents |
| `preserve_for_age_4` | `analytics_service.get_days_left_at_age_4` |
| `use_dubbeldagar_strategically` | scan planned days for same-date overlaps |
| `lagsta_niva_coverage` | compare tier usage |
| `stretch_time_at_home` | `weekly_intensity` < threshold |
| `wrap_weekend_with_vacation` | `monthly` salary + FP spanning a weekend |
| `wrap_red_days_with_vacation` | `red_day_clusters_in_range` (Swedish holiday helper) |
| `long_break_parent_swap` | match `break_periods` to calendar gaps |
| `reserve_for_preschool_planning_days` | `preschool_buffer_needed` |
The three already wired (`use_vacation_before_expiry`, `skip_fp_first_12_months`, `sgi_minimum_after_age_1`) are good reference shapes. Honour the documented product intent (see `ARCHITECTURE.md §6` and the project notes): the salary-type condition matters — `wrap_weekend_with_vacation` and the red-day wrap apply to **monthly-salaried only, not hourly**; the first-12-months SGI-protection and the ~5-days/week-after-age-1 rules drive the SGI tips. Tips are advisory, not hard validation.
As these land, raise the CI `--cov-fail-under` back up from 40 toward the 90 target (there's already a comment in `ci.yml` to that effect).
---
## 2. Review the frontend ↔ backend integration once the junior wires it (light review, not ownership)
The junior is fixing a broken frontend build and wiring the page stubs into a working app (see `JUNIOR_FOLLOWUP_2.md`). Two seams are worth a senior review when they reach them, since they're the riskiest:
- **Auth flow** — register/login → JWT handling → `AuthContext` token storage and refresh, and the CORS config in `main.py` matching the real frontend origin.
- **Manual parental-leave entry path** — the `FetchDataService` manual path is the standalone fallback that must work without the scraper; confirm the frontend hook (`useParentalLeave`) and the new `getParentalLeave` API client function line up with the backend contract.
A read-through and a smoke test (`uv run uvicorn app.main:app --reload` + `npm run dev`, walk create-child → plan-days → view-analytics) is enough; you don't need to own the UI work.
---
## Still deferred (no action now)
- **Postgres repository impls** (`repositories_impl/postgres/`) — SQLite serves the MVP; port later by copying the SQLite impls and swapping `aiosqlite` → `asyncpg` (`?` → `$1, $2`).
- **FK scraper / BankID** — blocked by the legal/ToS gate; the `scraper_enabled` flag is the activation path once it clears.
- **Password reset / email verification** — confirmed post-MVP, tracked via the `TODO` you added.