Implementiert:
- GET /api/inventory/overview Liefert pro SKU: - Produktname - Kategorie - Größe / Farbe - Preis - Aktueller Bestand (SUM der InventoryMovements) Bedeutung: - Ein einzelner Request ist ausreichend für das gesamte Inventory-Dashboard - Backend liefert UI-fertige Daten (keine Aggregation im Frontend nötig) Grundlage für: - Inventory Tabelle - Low-Stock Checks - Drop-Planung - Workspace UI
This commit is contained in:
@@ -0,0 +1,109 @@
|
|||||||
|
VOYAGE – SKUs & InventoryMovements
|
||||||
|
=================================
|
||||||
|
|
||||||
|
1. Product vs. SKU
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Ein Product beschreibt das Modell / die Idee.
|
||||||
|
Beispiel:
|
||||||
|
- "Voyage Tee"
|
||||||
|
|
||||||
|
Eine SKU (Stock Keeping Unit) ist die kleinste verkaufbare Einheit.
|
||||||
|
Sie beschreibt eine konkrete Variante eines Produkts.
|
||||||
|
|
||||||
|
Beispiel-SKUs für "Voyage Tee":
|
||||||
|
- VOY-TEE-BLK-M (Schwarz, Größe M)
|
||||||
|
- VOY-TEE-BLK-L (Schwarz, Größe L)
|
||||||
|
- VOY-TEE-WHT-M (Weiß, Größe M)
|
||||||
|
|
||||||
|
Wichtige Regel:
|
||||||
|
- Produkte werden NICHT gelagert oder verkauft
|
||||||
|
- NUR SKUs werden gelagert, verkauft und gezählt
|
||||||
|
|
||||||
|
|
||||||
|
2. Warum SKUs notwendig sind
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
- Bestand unterscheidet sich pro Größe/Farbe
|
||||||
|
- Preis kann pro Variante unterschiedlich sein
|
||||||
|
- Orders referenzieren SKUs
|
||||||
|
- Inventory bezieht sich IMMER auf SKUs
|
||||||
|
|
||||||
|
Kurz:
|
||||||
|
Alles Operative hängt an der SKU, nicht am Product.
|
||||||
|
|
||||||
|
|
||||||
|
3. InventoryMovement – Grundidee
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
InventoryMovement speichert JEDE Veränderung am Bestand.
|
||||||
|
|
||||||
|
Es gibt KEIN Feld wie:
|
||||||
|
- stock = 49
|
||||||
|
|
||||||
|
Stattdessen gibt es Buchungen (Movements):
|
||||||
|
- +50 PRODUCTION
|
||||||
|
- -1 SALE
|
||||||
|
- +1 RETURN
|
||||||
|
- -3 ADJUSTMENT
|
||||||
|
|
||||||
|
|
||||||
|
4. Inventory als Buchhaltung
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Inventory funktioniert wie ein Konto:
|
||||||
|
|
||||||
|
- Jede Bewegung ist eine Buchung
|
||||||
|
- Der aktuelle Bestand ist die Summe aller Buchungen
|
||||||
|
|
||||||
|
Beispiel für eine SKU:
|
||||||
|
|
||||||
|
+50 (PRODUCTION)
|
||||||
|
-1 (SALE)
|
||||||
|
+1 (RETURN)
|
||||||
|
|
||||||
|
Current Stock = 50
|
||||||
|
|
||||||
|
|
||||||
|
5. Vorteile dieses Modells
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
- Vollständige Historie
|
||||||
|
- Jeder Bestand ist erklärbar
|
||||||
|
- Fehler lassen sich nachvollziehen
|
||||||
|
- Perfekt für:
|
||||||
|
- Drops
|
||||||
|
- Reporting
|
||||||
|
- Automationen
|
||||||
|
- Forecasting
|
||||||
|
|
||||||
|
|
||||||
|
6. Beziehung zwischen Product, SKU und Inventory
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
Product
|
||||||
|
└─ SKU
|
||||||
|
└─ InventoryMovements
|
||||||
|
├─ +50 (PRODUCTION)
|
||||||
|
├─ -1 (SALE)
|
||||||
|
└─ -3 (ADJUSTMENT)
|
||||||
|
|
||||||
|
|
||||||
|
7. Goldene Regeln
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
1. Bestand niemals direkt speichern
|
||||||
|
2. Inventory immer über Movements ändern
|
||||||
|
3. Orders erzeugen InventoryMovements
|
||||||
|
4. Drops erzeugen initiale Production-Movements
|
||||||
|
|
||||||
|
|
||||||
|
8. Was darauf aufbaut
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- Inventory Overview (Stock pro SKU)
|
||||||
|
- Order-Fulfillment (automatische Abbuchung)
|
||||||
|
- Drop-Planung (geplant vs. real)
|
||||||
|
- Low-Stock Alerts
|
||||||
|
|
||||||
|
Dieses Modell ist bewusst einfach, aber skalierbar.
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
VOYAGE – Nächste Projektschritte (Workspace + Login + Webblog) – UPDATE 2026-01-20
|
||||||
|
===============================================================================
|
||||||
|
|
||||||
|
Ziel
|
||||||
|
----
|
||||||
|
Ein internes Workspace-System mit Login + Webinterface
|
||||||
|
und ein separates öffentliches Webblog für Content & Brand.
|
||||||
|
|
||||||
|
|
||||||
|
Aktueller Stand
|
||||||
|
---------------
|
||||||
|
Bereits implementiert:
|
||||||
|
- Products
|
||||||
|
- SKUs (Varianten)
|
||||||
|
- InventoryMovements (Bestandsbuchungen)
|
||||||
|
- Current Stock pro SKU
|
||||||
|
- Inventory Overview Endpoint (aggregierte Bestandsübersicht)
|
||||||
|
- Login-System (Spring Security, Form Login, Session)
|
||||||
|
- /api/** ist geschützt (nur eingeloggt)
|
||||||
|
- Login per Browser (/login) und per curl (Cookie/JSESSIONID) funktioniert
|
||||||
|
|
||||||
|
Damit ist das Domain-Fundament + Zugriffsschutz + UI-taugliche API abgeschlossen.
|
||||||
|
|
||||||
|
|
||||||
|
Wichtiger Hinweis zur Datenbank (AKTUELLER ZUSTAND)
|
||||||
|
---------------------------------------------------
|
||||||
|
Die Anwendung verwendet derzeit eine H2 In-Memory Datenbank:
|
||||||
|
|
||||||
|
- JDBC URL: jdbc:h2:mem:...
|
||||||
|
- Die Datenbank liegt ausschließlich im RAM
|
||||||
|
- BEI JEDEM APP-RESTART WERDEN ALLE DATEN GELÖSCHT
|
||||||
|
|
||||||
|
Dieser Zustand ist bewusst gewählt und sinnvoll für:
|
||||||
|
- frühe Entwicklung
|
||||||
|
- schnelles Testen
|
||||||
|
- Debugging
|
||||||
|
- Fokus auf Domain-Logik statt Persistenz
|
||||||
|
|
||||||
|
Wichtig:
|
||||||
|
- Products, SKUs und InventoryMovements müssen nach jedem Neustart neu angelegt werden
|
||||||
|
- IDs (productId, skuId) ändern sich nach jedem Restart
|
||||||
|
|
||||||
|
Geplanter späterer Schritt:
|
||||||
|
- Umstellung auf persistente DB (z. B. H2 file, Postgres)
|
||||||
|
- Einführung von Migrations (Flyway)
|
||||||
|
|
||||||
|
|
||||||
|
Grundprinzip
|
||||||
|
------------
|
||||||
|
Workspace (intern) und Public Website (Blog) sind zwei verschiedene Welten
|
||||||
|
und sollten technisch getrennt sein.
|
||||||
|
|
||||||
|
- Workspace = interne Realität (Inventory, Orders, Drops)
|
||||||
|
- Public Web = Content, Blog, Brand (keine sensiblen Daten)
|
||||||
|
|
||||||
|
|
||||||
|
Empfohlene Architektur
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
1) workspace-api (Spring Boot)
|
||||||
|
- Products / SKUs / Inventory (besteht)
|
||||||
|
- Aggregierte Inventory-Übersicht (besteht)
|
||||||
|
- Auth (besteht)
|
||||||
|
- später Orders / Drops
|
||||||
|
|
||||||
|
2) workspace-ui (Webinterface)
|
||||||
|
- internes Dashboard
|
||||||
|
- spricht mit workspace-api
|
||||||
|
- nutzt Session-Cookies (Browser)
|
||||||
|
|
||||||
|
3) public-web (Blog / Brand)
|
||||||
|
- öffentlich zugänglich
|
||||||
|
- kein Login nötig
|
||||||
|
- getrennt vom Workspace
|
||||||
|
|
||||||
|
|
||||||
|
Repo-Struktur
|
||||||
|
-------------
|
||||||
|
voyage/
|
||||||
|
├─ apps/
|
||||||
|
│ ├─ workspace-api/ (Backend)
|
||||||
|
│ ├─ workspace-ui/ (internes UI)
|
||||||
|
│ └─ public-web/ (Blog / Brand)
|
||||||
|
└─ packages/
|
||||||
|
└─ shared/ (optional: DTOs / Types)
|
||||||
|
|
||||||
|
|
||||||
|
Empfohlene Reihenfolge (sehr wichtig)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
SCHRITT 1: Login-System für Workspace
|
||||||
|
------------------------------------
|
||||||
|
Status: ERLEDIGT ✅
|
||||||
|
|
||||||
|
Ziel:
|
||||||
|
- Zugriff auf /api/** nur für eingeloggte Nutzer
|
||||||
|
- Workspace nicht öffentlich zugänglich
|
||||||
|
|
||||||
|
Implementiert:
|
||||||
|
- Spring Security
|
||||||
|
- Form Login
|
||||||
|
- Session-basiert (kein JWT)
|
||||||
|
|
||||||
|
Offene Endpoints:
|
||||||
|
- /health (öffentlich)
|
||||||
|
- /h2-console (nur Development)
|
||||||
|
|
||||||
|
|
||||||
|
SCHRITT 2: Workspace-taugliche Endpoints
|
||||||
|
----------------------------------------
|
||||||
|
Status: ERLEDIGT ✅
|
||||||
|
|
||||||
|
Implementiert:
|
||||||
|
- GET /api/inventory/overview
|
||||||
|
|
||||||
|
Liefert pro SKU:
|
||||||
|
- Produktname
|
||||||
|
- Kategorie
|
||||||
|
- Größe / Farbe
|
||||||
|
- Preis
|
||||||
|
- Aktueller Bestand (SUM der InventoryMovements)
|
||||||
|
|
||||||
|
Bedeutung:
|
||||||
|
- Ein einzelner Request ist ausreichend für das gesamte Inventory-Dashboard
|
||||||
|
- Backend liefert UI-fertige Daten (keine Aggregation im Frontend nötig)
|
||||||
|
|
||||||
|
Grundlage für:
|
||||||
|
- Inventory Tabelle
|
||||||
|
- Low-Stock Checks
|
||||||
|
- Drop-Planung
|
||||||
|
- Workspace UI
|
||||||
|
|
||||||
|
|
||||||
|
SCHRITT 3: Workspace UI (minimal starten)
|
||||||
|
-----------------------------------------
|
||||||
|
Status: ALS NÄCHSTES ✅
|
||||||
|
|
||||||
|
Nicht zu groß denken. Start mit EINER Seite:
|
||||||
|
|
||||||
|
- Inventory Übersicht
|
||||||
|
- Tabelle mit allen SKUs + currentStock
|
||||||
|
- Suche & Filter (Name, SKU, Kategorie)
|
||||||
|
- Button für Inventory Movements (+ / -)
|
||||||
|
|
||||||
|
Ergebnis:
|
||||||
|
Ein echtes internes Tool, das täglich nutzbar ist.
|
||||||
|
|
||||||
|
|
||||||
|
SCHRITT 4: Public Webblog (parallel, aber getrennt)
|
||||||
|
---------------------------------------------------
|
||||||
|
Status: PARALLEL MÖGLICH ✅
|
||||||
|
|
||||||
|
Empfohlener Start:
|
||||||
|
- Eigenes Frontend (public-web)
|
||||||
|
- Content als Markdown-Dateien im Repo
|
||||||
|
- Git als CMS
|
||||||
|
|
||||||
|
Vorteile:
|
||||||
|
- Kein Admin-UI nötig
|
||||||
|
- Keine Auth
|
||||||
|
- Sehr schneller Content-Workflow
|
||||||
|
|
||||||
|
|
||||||
|
Warum diese Reihenfolge sinnvoll ist
|
||||||
|
------------------------------------
|
||||||
|
- Workspace erzeugt operativen Wert
|
||||||
|
- Login schützt eure Arbeit
|
||||||
|
- Inventory Overview macht das System direkt benutzbar
|
||||||
|
- UI kann ohne weitere Backend-Arbeit gebaut werden
|
||||||
|
- Blog kann unabhängig wachsen
|
||||||
|
- Keine unnötige Komplexität zu früh
|
||||||
|
|
||||||
|
|
||||||
|
Langfristige Erweiterungen
|
||||||
|
--------------------------
|
||||||
|
- Orders → automatische InventoryMovements
|
||||||
|
- Drops → Production → initialer Bestand
|
||||||
|
- Automations (Low-Stock Alerts)
|
||||||
|
- Rollen (Admin / Viewer)
|
||||||
|
- Persistente Datenbank + Migrations
|
||||||
|
- Public Shop (optional)
|
||||||
|
|
||||||
|
|
||||||
|
Merksätze
|
||||||
|
---------
|
||||||
|
- Workspace zuerst, Public später
|
||||||
|
- Login früh einbauen (erledigt)
|
||||||
|
- Inventory niemals direkt ändern
|
||||||
|
- SKUs sind die operative Wahrheit
|
||||||
|
- In-Memory DB = flüchtig, aber perfekt für den Start
|
||||||
|
|
||||||
|
|
||||||
|
Nächster konkreter Schritt
|
||||||
|
--------------------------
|
||||||
|
Start von:
|
||||||
|
- workspace-ui (Inventory Tabelle auf Basis von /api/inventory/overview)
|
||||||
|
|
||||||
|
Danach:
|
||||||
|
- Orders + automatische Inventory-Abbuchung
|
||||||
|
- Umstellung auf persistente DB, sobald Stabilität erreicht ist
|
||||||
@@ -37,8 +37,14 @@ dependencies {
|
|||||||
testImplementation 'org.springframework.boot:spring-boot-starter-validation-test'
|
testImplementation 'org.springframework.boot:spring-boot-starter-validation-test'
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
|
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||||
|
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||||
|
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||||
|
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||||
|
|
||||||
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
generateJava {
|
generateJava {
|
||||||
schemaPaths = ["${projectDir}/src/main/resources/graphql-client"]
|
schemaPaths = ["${projectDir}/src/main/resources/graphql-client"]
|
||||||
packageName = 'com.voyage.workspace_api.codegen'
|
packageName = 'com.voyage.workspace_api.codegen'
|
||||||
@@ -47,4 +53,4 @@ generateJava {
|
|||||||
|
|
||||||
tasks.named('test') {
|
tasks.named('test') {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
@@ -1 +1,6 @@
|
|||||||
spring.application.name=workspace-api
|
spring.application.name=workspace-api
|
||||||
|
|
||||||
|
spring.h2.console.enabled=true
|
||||||
|
spring.datasource.url=jdbc:h2:mem:voyage;DB_CLOSE_DELAY=-1
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
spring.profiles.active=dev
|
||||||
Reference in New Issue
Block a user