Jens Reinemann
eb9ab6aa54
feat: Multi-Inventar auf Client-Seite ( #79 )
...
Server:
- Inventories-Tabelle um name-Spalte erweitert
- Neue User-facing REST-Routes: GET/POST /api/inventories,
POST /api/inventories/{id}/switch
- LoginResponse enthält inventoryId + inventoryName
- InventoryRepository: createInventory(name), getUserInventories(),
getInventoryName()
- AuthRoutes: inventoryRepository injiziert für Login-Response
Shared:
- InventoryInfoDto (id, name, isActive)
- CreateInventoryRequest (name)
Client:
- SettingsKeys: ACTIVE_INVENTORY_ID, ACTIVE_INVENTORY_NAME
- SyncService: listInventories(), createInventory(), switchInventory()
- SyncServiceImpl: Implementierung der drei Endpunkte + Login
speichert inventoryId/Name
- InventoryPickerViewModel: Laden, Erstellen, Wechseln von Inventaren
mit automatischem Re-Sync
- InventoryPickerSheet: ModalBottomSheet mit Inventarliste, Auswahl
und Erstellen-Dialog
- MainScreen: TopAppBar zeigt aktiven Inventar-Namen mit Wechsel-Button
Tests:
- 8 neue Server-Tests (InventoryManagementTest)
- 8 neue Client-Tests (InventoryPickerViewModelTest)
- Bestehende FakeSyncService in 2 Test-Dateien aktualisiert
Closes #79
2026-05-17 03:55:08 +02:00
Jens Reinemann
0f25c180ed
feat(sync): Full-Inventory-Sync durch Delta-Sync ersetzen
...
Server + Client: Timestamp-basierter Delta-Sync als Alternative zum
Full-Sync. GET /api/inventory akzeptiert jetzt optionalen ?since=<ts>
Query-Parameter und liefert nur Items mit lastUpdated > since.
Shared: InventoryDto um deletedItemIds-Feld erweitert (Default: leer,
backward-compatible mit bestehenden Clients).
Server:
- DeletedItems-Tabelle trackt geloeschte Item-IDs pro Inventory
- InventoryRepository.loadInventorySince(): Delta-Query mit Items +
deletedItemIds seit Timestamp
- saveInventory()/deleteItem(): Loeschungen werden in DeletedItems
protokolliert
- DatabaseFactory: DeletedItems-Tabelle registriert
Client (App):
- SyncService.downloadInventory(since: Long?): optionaler since-Param
- SyncServiceImpl: haengt ?since= an GET-Request
- ItemDao.deleteByIds(): Batch-Loeschung fuer Delta-Sync
- ImportExportRepositoryImpl: verarbeitet deletedItemIds aus DTO
- SettingsViewModel.pullSync(fullSync): Delta-Sync mit letztem
Sync-Timestamp; fullSyncRequired-Event loest weiterhin Full-Sync aus
Entscheidungen:
- Timestamp-basiert (nutzt bestehendes lastUpdated-Feld)
- Full-Sync bleibt Fallback (fullSyncRequired, erster Sync)
- Categories/Locations/Settings immer vollstaendig (klein)
6 neue DeltaSyncTests + 3 Repository-Tests + 2 SyncService-Tests
Closes #74
2026-05-17 03:15:49 +02:00
Jens Reinemann
56ac9b1425
feat: Messaging-System mit Offline-First und WebSocket-Push ( #58 )
...
## Server
- Messages-Tabelle (id, sender_id, receiver_id, body, sent_at, delivered_at)
- MessageRepository: save/getUndelivered/getConversation/markDelivered (JOIN statt N+1)
- POST /api/messages, GET /api/messages/{userId}: Nachrichten senden/abrufen
- GET /api/users: User-Liste fuer authentifizierte User (ohne eigenen Account)
- WebSocketManager: notifyNewMessage() + isOnline()
- WebSocketRoutes: unzugestellte Nachrichten bei Reconnect pushen
- LoginResponse: userId + username ergaenzt
- Server-Dependency: kotlinx.serialization fuer shared
## App
- MessageEntity + MessageDao (Room, Migration 3->4)
- KrisenvorratDatabase v4, Migrations.MIGRATION_3_4
- MessageRepositoryImpl: Offline-First (isPending), drain bei WebSocket-Connect
- WebSocketEvent.NewMessage -> MessageDto aus shared
- WebSocketClientImpl: new_message-Event parsen
- AUTH_USER_ID in SettingsKeys, SyncServiceImpl speichert userId bei Login
- UserListScreen + UserListViewModel: User-Liste anzeigen
- ChatScreen + ChatViewModel: WhatsApp-Style Chat (links/rechts, Zeitstempel)
- Navigation: Screen.UserList, Screen.Chat, MESSAGES in Bottom-Nav
- RepositoryModule: MessageRepository gebunden
## Tests
- 234 Tests, 0 Fehler
2026-05-16 23:35:25 +02:00
Jens Reinemann
8280a9daf9
refactor: kcal/100g -> kcal/kg umbenennen und Mindestbestand entfernen
...
- ItemEntity, ItemDto: kcalPer100g -> kcalPerKg (kcal_per_kg),
minStock-Spalte komplett entfernt
- CalculateSupplyRangeUseCase: Formel angepasst (/ 1000.0 * kcalPerKg)
- GetMinStockWarningsUseCase + MinStockWarning: gelöscht
- UI (ItemFormScreen, WarningsScreen, DashboardScreen): Mindestbestand-
Felder und Warnungsabschnitte entfernt
- ViewModels, UiState, Repository: alle Referenzen bereinigt
- Server (Tables, InventoryRepository): Schema angepasst
- Room: fallbackToDestructiveMigration() hinzugefügt (keine Produktivdaten)
- Alle 434 Tests gruen
2026-05-16 14:19:10 +02:00
Jens Reinemann
c0c4978ccf
feat(shared): add shared module with common DTO models
...
New Gradle module :shared (pure Kotlin/JVM) containing @Serializable
DTO classes for use by both the Android app and future Ktor server.
shared/src/main/kotlin/de/krisenvorrat/shared/model/:
- InventoryDto: root DTO replacing ExportData (version, categories,
locations, items, settings)
- CategoryDto, LocationDto, ItemDto, SettingDto: extracted from
the former *Export data classes in :app
Migration in :app:
- ExportData.kt deleted (classes moved to :shared)
- ImportExportRepositoryImpl now imports from de.krisenvorrat.shared.model
- app/build.gradle.kts adds implementation(project(:shared))
Build config:
- libs.versions.toml: added kotlin-jvm plugin entry
- build.gradle.kts (root): registered kotlin-jvm plugin
- settings.gradle.kts: include(:shared)
JSON wire format is unchanged; all 165 existing tests pass.
Closes #39
2026-05-14 19:50:23 +02:00