refactor: remove all asset/account functionality (models, schemas, routers, store, views, components, tests, docs)
This commit is contained in:
16
AGENTS.md
16
AGENTS.md
@@ -22,9 +22,6 @@ cd api; uvicorn app.main:app --host 0.0.0.0 --port 23994
|
||||
|
||||
# Type-check frontend (noEmit; uses project references tsconfig)
|
||||
cd WebUI; npm run typecheck
|
||||
|
||||
# Run the one hand-written test (backend must be running on :23994)
|
||||
python tests/test_accounts.py
|
||||
```
|
||||
|
||||
**Build order matters:** `python main.py` automatically compiles WebUI (`npm install` + `npm run build`), copies `WebUI/dist/` → `api/webui/`, then starts uvicorn. It checks timestamps to skip rebuilds when frontend is unchanged.
|
||||
@@ -40,9 +37,8 @@ python tests/test_accounts.py
|
||||
- **SQLite path** is computed relative to `api/` via `__file__` — safe regardless of cwd. `connect_args={"check_same_thread": False}` for FastAPI async compatibility.
|
||||
- **`database.py:init_db()`** auto-creates tables on startup (`create_all`) and auto-adds missing columns via `ALTER TABLE ADD COLUMN` (no Alembic). Columns that are non-nullable with no default are skipped.
|
||||
- **UserSettings is a singleton**: always id=1, auto-created on first `GET`. `set_default_password()` auto-initializes password to `"elysia"` on first access if `password_hash` is empty.
|
||||
- **Account balance changes** auto-create `AccountHistory` records in `update_balance()`. You cannot directly modify balance via `PUT /api/accounts/{id}` — balance is replaced via `POST /api/accounts/{id}/balance`.
|
||||
- **Habit checkins for the same day** accumulate count (not new rows), enforced by a `(habit_id, checkin_date)` unique constraint. Cancelling reduces count; deleting when count ≤ 0 removes the row.
|
||||
- **Anniversaries / DebtInstallments** have computed fields (`next_date`, `days_until`, `year_count` / `remaining_periods`) calculated at request time, not stored in DB. The calculation functions live in the router layer (not models), because they depend on `date.today()`.
|
||||
- **Anniversaries** have computed fields (`next_date`, `days_until`, `year_count`) calculated at request time, not stored in DB. The calculation functions live in the router layer (not models), because they depend on `date.today()`.
|
||||
- **`task_tags` M2M table** is defined in `models/tag.py` (not `models/task.py`). Tags only support create/delete (no update).
|
||||
- **Update schemas** use `clearable_fields` + `exclude_unset=True` to distinguish "field not sent" from "field sent as null". For non-clearable fields, `None` means "don't change"; for clearable fields, `None` means "clear it". See `schemas/task.py:TaskUpdate`, `schemas/habit.py:HabitUpdate`, `schemas/anniversary.py:AnniversaryUpdate`.
|
||||
- **JWT authentication** — `utils/auth.py` handles JWT (HS256, key: `"elysia-todo-secret-key-change-in-production"`, 24h expiry). Middleware in `main.py` validates tokens for all `/api/*` routes except `/api/auth/*` and `/health`. Default password: `elysia`. Login via `POST /api/auth/login`. Token key in localStorage: `elysia_auth_token`. **Middleware only validates the token; it does NOT inject user info into `request.state`.** Routes needing user data must call `get_current_user(request)` manually.
|
||||
@@ -50,18 +46,17 @@ python tests/test_accounts.py
|
||||
- `Category`: refuses deletion if tasks are linked (400)
|
||||
- `HabitGroup`: sets linked habits' `group_id` to NULL
|
||||
- `AnniversaryCategory`: sets linked anniversaries' `category_id` to NULL
|
||||
- `FinancialAccount`: full cascade delete (removes linked history + installments)
|
||||
|
||||
### Router registration quirks
|
||||
- **`/health` MUST be registered before `/{full_path:path}`** in `main.py:114` — otherwise SPA fallback intercepts health checks and returns `index.html`.
|
||||
- **habits router** (`routers/habits.py`) is an empty-shell router that combines 3 sub-routers via `include_router`: habit-groups (`/api/habit-groups`), habits (`/api/habits`), and checkins (`/api/habits/{habit_id}/checkins`).
|
||||
- **anniversaries and accounts routers** BOTH use `prefix="/api"` (not `/api/anniversaries` or `/api/accounts`). Their internal paths are `/anniversaries`, `/anniversary-categories`, `/accounts`, `/debt-installments`, etc. They coexist because internal paths don't overlap — but be careful adding new routes; the first `include_router` match wins.
|
||||
- **anniversaries router** uses `prefix="/api"` (not `/api/anniversaries`). Its internal paths are `/anniversaries`, `/anniversary-categories`, etc.
|
||||
|
||||
### Frontend (`WebUI/`)
|
||||
- Vue Router uses `createWebHistory()` (HTML5 history mode) — **requires the backend SPA fallback** (`/{full_path:path}` → `index.html`).
|
||||
- Vite dev proxy forwards `/api` → `http://localhost:23994`.
|
||||
- `@` alias maps to `src/`.
|
||||
- 9 Pinia stores: `auth`, `task`, `category`, `tag`, `habit`, `anniversary`, `account`, `userSettings`, `ui`. The `ui` store manages dialog visibility, editing state, sidebar collapse, and global loading (no API calls).
|
||||
- 8 Pinia stores: `auth`, `task`, `category`, `tag`, `habit`, `anniversary`, `userSettings`, `ui`. The `ui` store manages dialog visibility, editing state, sidebar collapse, and global loading (no API calls).
|
||||
- Element Plus icons registered globally in `main.ts` — use `<Edit />`, `<Delete />` etc. in templates without imports.
|
||||
- Element Plus uses Chinese locale (`zh-cn`).
|
||||
- **Vite 7.x + TypeScript 5.9** with `erasableSyntaxOnly: true` and project references.
|
||||
@@ -77,10 +72,7 @@ python tests/test_accounts.py
|
||||
- `docker-compose.yml` mounts `api/data/` and `api/logs/` for persistence; `api/webui/` is read-only.
|
||||
|
||||
## Testing quirks
|
||||
- Only one test file: `tests/test_accounts.py` — **hand-written, no framework** (not pytest). It counts pass/fail manually and uses `requests` directly against `localhost:23994`.
|
||||
- Backend must be running before executing tests.
|
||||
- **The test permanently mutates the database** — Section 15 deliberately leaves test data in place for UI display. Run it on a disposable database copy or reset manually if you need a clean state.
|
||||
- **The test sends no auth headers** and will fail with 401 if JWT auth is enforced. You must first `POST /api/auth/login` with `{"password": "elysia"}` to get a token, then include `Authorization: Bearer <token>` in requests, or temporarily comment out the auth middleware for testing.
|
||||
- No test framework or test files currently in the repo.
|
||||
- No test coverage for tasks, habits, anniversaries, or tags.
|
||||
|
||||
## What's missing (agents should not assume)
|
||||
|
||||
Reference in New Issue
Block a user