From a44fd1ae44cbf135f626bf0cf5a5f0e59ee2abd4 Mon Sep 17 00:00:00 2001 From: sysops Date: Sun, 10 May 2026 22:21:05 +0200 Subject: [PATCH] feat(PROJ-44): ocr_status/ocr_chars in MailDetail + v1 API GET /api/mails/{id} liefert jetzt ocr_status + ocr_chars fuer das GUI- Badge und den konditionalen Download-Button. Die externe v1-API (/api/v1/mails/{id}) bekommt zusaetzlich ocr_status, damit CRM- Integrationen entscheiden koennen, ob ein OCR-Text-Pull lohnt. --- internal/api/search_handlers.go | 11 +++++++++++ internal/api/v1_handlers.go | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/internal/api/search_handlers.go b/internal/api/search_handlers.go index ce238f6..d7ed687 100644 --- a/internal/api/search_handlers.go +++ b/internal/api/search_handlers.go @@ -311,6 +311,15 @@ func (s *Server) handleGetMail(w http.ResponseWriter, r *http.Request) { } } + // PROJ-44: OCR status + extracted character count for the GUI badge and + // the conditional "OCR-Text herunterladen" button. Errors are swallowed + // silently so a missing ocr_chars column on an old DB does not break the + // detail view; defaults are returned by GetOCRMeta in that case. + ocrStatus, ocrChars, _ := s.store.GetOCRMeta(r.Context(), id) + if ocrStatus == "" { + ocrStatus = "pending" + } + writeJSON(w, http.StatusOK, map[string]interface{}{ "id": id, "from": pm.From, @@ -326,6 +335,8 @@ func (s *Server) handleGetMail(w http.ResponseWriter, r *http.Request) { "verify_ok": verifyOK, "verified_at": verifiedAt, "thread_id": threadID, + "ocr_status": ocrStatus, + "ocr_chars": ocrChars, }) } diff --git a/internal/api/v1_handlers.go b/internal/api/v1_handlers.go index 389bbe5..be7a0fb 100644 --- a/internal/api/v1_handlers.go +++ b/internal/api/v1_handlers.go @@ -244,6 +244,13 @@ func (s *Server) handleV1GetMail(w http.ResponseWriter, r *http.Request) { dateStr = pm.Date.UTC().Format(time.RFC3339) } + // PROJ-44: expose ocr_status to external API consumers as well so CRM + // integrations can decide whether to ask for ocr-text downloads. + ocrStatus, _, _ := s.store.GetOCRMeta(r.Context(), id) + if ocrStatus == "" { + ocrStatus = "pending" + } + writeJSON(w, http.StatusOK, map[string]interface{}{ "id": id, "from": pm.From, @@ -254,6 +261,7 @@ func (s *Server) handleV1GetMail(w http.ResponseWriter, r *http.Request) { "size": len(raw), "body_plain": pm.TextBody, "attachments": attachments, + "ocr_status": ocrStatus, }) }