From 43ce0bcfe1efc60fa485da12528d081de01c7f6b Mon Sep 17 00:00:00 2001 From: Stefan Koelle Date: Thu, 17 Sep 2026 19:41:38 +0200 Subject: [PATCH] fix: build full_name from parts in chat messages endpoint - SELECT prefix, given_name, middle_name, family_name, suffix alongside full_name - Apply db._build_full_name() fallback when full_name is NULL - Document the pattern in AGENTS.md to prevent future regressions --- AGENTS.md | 13 +++++++++++++ src/api/main.py | 11 +++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d4fb308..65cc384 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -145,6 +145,19 @@ See `.env.example` for full list. Key variables: 4. Update endpoint table in `SPEC.md` and `README.md` 5. Test with: `curl -H "Remote-User: " http://127.0.0.1:8000/` +### Querying contact names from the DB +**IMPORTANT:** The `full_name` column in `contacts` can be NULL — it is +NOT guaranteed to be set. Always SELECT `prefix, given_name, middle_name, +family_name, suffix` alongside `full_name` and apply the fallback: +```python +if not row.get("full_name"): + row["full_name"] = db._build_full_name(row) +``` +This is what `_row_to_contact_out()` does for API responses. Any code +that needs a contact's display name (e.g. proxying to external APIs) +must follow the same pattern. See `get_contact_messages()` in +`src/api/main.py` for a reference implementation. + ### Adding a new contact field 1. Add column to `contacts` table in `sql/schema.sql` 2. Update `src/vcard_parser.py` to extract the field diff --git a/src/api/main.py b/src/api/main.py index a2ed712..16ade9d 100644 --- a/src/api/main.py +++ b/src/api/main.py @@ -229,14 +229,21 @@ def get_contact_messages( id_clause = "AND id = %s" if where_clause else "WHERE id = %s" with conn.cursor() as cur: cur.execute( - f"SELECT full_name FROM contacts {where_clause} {id_clause}", + f"""SELECT full_name, prefix, given_name, middle_name, family_name, suffix + FROM contacts {where_clause} {id_clause}""", params + [contact_id], ) row = cur.fetchone() - if not row or not row.get("full_name"): + if not row: return JSONResponse(status_code=404, content={"detail": "Kontakt nicht gefunden"}) + if not row.get("full_name"): + row["full_name"] = db._build_full_name(row) + + if not row.get("full_name"): + return JSONResponse(status_code=404, content={"detail": "Kontakt hat keinen Namen"}) + try: resp = requests.get( f"{Config.CHATAPI_URL.rstrip('/')}/conversation",