photo viewing, and record drill-down
- Overview is now the single front page (list + "+" FAB to scan)
instead of a separate near-empty Scan tab; export moved from
Overview into the drawer
- Drop petrol_station/transaction_number from storage, the edit
form, and CSV/ODS export - not useful for a personal fuel-cost log
(destructive Room migration, version 1->2 already shipped earlier)
- Add a live plausibility check (total_price vs. price_per_litre *
litres - discount) shown as a green/red badge on the review screen
- Add a shared Details/Photo review screen (ReceiptReviewScreen),
with pinch-to-zoom on the photo (new Coil dependency), reused both
right after a scan and when drilling into an already-saved receipt
from the list (ReceiptDetailScreen, with Update/Delete)
- Fix receipt photos not surviving an app restart: camera/gallery
captures now write to internal storage (filesDir) instead of the
cache dir, which the OS can clear independent of the database; the
gallery picker was also saving the Photo Picker's own short-lived
content:// Uri instead of a Uri onto our persisted copy
- App log: add a Copy button and selectable text
- Fix the connection status bar overlapping the system gesture nav
bar under edge-to-edge
- Settings: prefill an editable example server URL, add a "Test
connection" button; both it and the connection status bar now
surface the actual failure reason, not just pass/fail
manual CI publishes
- Settings: prefill an editable example server URL, add a "Test
connection" button
- Front page now shows the receipts list (Overview) with a column
header and an empty-state message
- Add a connection status bar (polls /health) shown on every screen
- Capture: add "Choose from gallery" alongside the camera
- Add an in-app "App log" screen; ApiClient/CaptureViewModel/
OverviewViewModel/ConnectionStatusViewModel now log key events,
including the actual connection-failure reason (not just pass/fail)
- .gitea/workflows/build.yml: publish to dl.ladkau.de on a manual
"Run workflow" dispatch too, not just push
- README.md: document the CI secrets (REGISTRY_USER/PASSWORD,
DL_SFTP_KEY) that must be configured in Gitea, separate from the
local registry.env
- build-image/: Dockerfile bundling JDK 17, the Android SDK, and
Node.js (needed by Gitea's JS-based actions) - the app has no
native code, so no NDK
- build-image.sh/upload-image.sh: extended to also build/push this
image alongside the existing OCR pipeline tools image
- run-image.sh: runs `make android` inside the image against a live
checkout, for a CI-equivalent local build
- Makefile: `make android` builds and versions a release APK into
dist/, from the current git tag
- .gitea/workflows/build.yml: now pulls the custom image and just
runs `make android`, replacing the ad-hoc Node/SDK install steps
- README.md: describes the pipeline, server, app, and build tooling
- registry.env.example: fix REGISTRY_IMAGE to be fully-qualified
(an unqualified name was silently resolving pushes to Docker Hub
instead of the configured registry)
- docker-compose.yml + tooling-container/src/server.py: serve
preprocess/OCR/extract over an async job API (POST /jobs, GET
/jobs/{id}) instead of manual host-script runs per receipt
- android/: Kotlin/Compose app - capture a receipt photo, poll job
progress, review/edit extracted fields, save locally (Room), export
to CSV/ODS
- .gitea/workflows/build.yml: build the debug APK and publish it to
dl.ladkau.de on push
- build-image.sh: also pull ollama/ollama so all pipeline images are
ready after one script
- add project logo (also used for the app's launcher icon/splash)
Self-hosted, verifiable pipeline for extracting structured data (station,
date/time, price per litre, litres, discount, total) from German fuel
receipt photos: grayscale + mild bilateral filter + contrast stretch,
Tesseract OCR, then LLM structuring via a small local model (Qwen 2.5,
served by Ollama). Each step is independently runnable and inspectable
through numbered scripts against a shared tooling container.
Ollama runs as its own long-lived container (0_run_ollama.sh), separate
from the stateless per-receipt pipeline steps, so the model stays loaded
in memory between runs. Includes a containerized ground-truth batch test
(test_batch.sh) that reproduces the full pipeline over the test receipts
and reports per-field accuracy.
Targets eventual deployment on a Raspberry Pi 4 k3s cluster.