1
0
Fork 0
mirror of https://github.com/s-frick/effigenix.git synced 2026-03-28 17:04:49 +01:00

feat(inventory): Lagerorte abfragen mit Filter nach Typ und Status (#3)

Query UseCase: ListStorageLocations mit optionalen Filtern storageType und active
GET /api/inventory/storage-locations mit STOCK_READ oder STOCK_WRITE
Tests: 10 neue Integrationstests (35 gesamt)
This commit is contained in:
Sebastian Frick 2026-02-19 12:42:25 +01:00
parent 9b9b7311d1
commit 6010820944
4 changed files with 224 additions and 2 deletions

View file

@ -69,6 +69,7 @@ class StorageLocationControllerIntegrationTest {
private long jwtExpiration;
private String adminToken;
private String readerToken;
private String viewerToken;
@BeforeEach
@ -87,13 +88,20 @@ class StorageLocationControllerIntegrationTest {
passwordEncoder.encode("Pass123"), Set.of(adminRole),
"BRANCH-01", UserStatus.ACTIVE, LocalDateTime.now(), null));
String readerId = UUID.randomUUID().toString();
userRepository.save(new UserEntity(
readerId, "inv.reader", "inv.reader@test.com",
passwordEncoder.encode("Pass123"), Set.of(viewerRole),
"BRANCH-01", UserStatus.ACTIVE, LocalDateTime.now(), null));
String viewerId = UUID.randomUUID().toString();
userRepository.save(new UserEntity(
viewerId, "inv.viewer", "inv.viewer@test.com",
passwordEncoder.encode("Pass123"), Set.of(viewerRole),
"BRANCH-01", UserStatus.ACTIVE, LocalDateTime.now(), null));
adminToken = generateToken(adminId, "inv.admin", "STOCK_WRITE");
adminToken = generateToken(adminId, "inv.admin", "STOCK_WRITE,STOCK_READ");
readerToken = generateToken(readerId, "inv.reader", "STOCK_READ");
viewerToken = generateToken(viewerId, "inv.viewer", "USER_READ");
}
@ -467,6 +475,139 @@ class StorageLocationControllerIntegrationTest {
.andExpect(jsonPath("$.code").value("STORAGE_LOCATION_NOT_FOUND"));
}
// ==================== Lagerorte abfragen (Story 1.3) ====================
@Test
@DisplayName("Alle Lagerorte abfragen → 200 mit Liste")
void listStorageLocations_returnsAll() throws Exception {
createAndReturnId("Lager A", "DRY_STORAGE", null, null);
createAndReturnId("Lager B", "COLD_ROOM", "-2", "8");
mockMvc.perform(get("/api/inventory/storage-locations")
.header("Authorization", "Bearer " + adminToken))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[*].name", containsInAnyOrder("Lager A", "Lager B")))
.andExpect(jsonPath("$[0].id").isNotEmpty())
.andExpect(jsonPath("$[0].storageType").isNotEmpty())
.andExpect(jsonPath("$[0].active").isBoolean());
}
@Test
@DisplayName("Lagerorte nach StorageType filtern → 200")
void listStorageLocations_filterByStorageType() throws Exception {
createAndReturnId("Kühlraum", "COLD_ROOM", "-2", "8");
createAndReturnId("Trockenlager", "DRY_STORAGE", null, null);
createAndReturnId("Gefrierschrank", "FREEZER", "-25", "-18");
mockMvc.perform(get("/api/inventory/storage-locations")
.param("storageType", "COLD_ROOM")
.header("Authorization", "Bearer " + adminToken))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(1)))
.andExpect(jsonPath("$[0].storageType").value("COLD_ROOM"));
}
@Test
@DisplayName("Lagerorte nach active filtern → 200")
void listStorageLocations_filterByActive() throws Exception {
String activeId = createAndReturnId("Aktiv", "DRY_STORAGE", null, null);
String inactiveId = createAndReturnId("Inaktiv", "COLD_ROOM", null, null);
// Deaktivieren
mockMvc.perform(patch("/api/inventory/storage-locations/" + inactiveId + "/deactivate")
.header("Authorization", "Bearer " + adminToken))
.andExpect(status().isOk());
mockMvc.perform(get("/api/inventory/storage-locations")
.param("active", "true")
.header("Authorization", "Bearer " + adminToken))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(1)))
.andExpect(jsonPath("$[0].name").value("Aktiv"));
}
@Test
@DisplayName("Lagerorte mit storageType und active filtern → 200")
void listStorageLocations_filterByStorageTypeAndActive() throws Exception {
createAndReturnId("Kühl Aktiv", "COLD_ROOM", null, null);
String inactiveId = createAndReturnId("Kühl Inaktiv", "COLD_ROOM", null, null);
createAndReturnId("Trocken Aktiv", "DRY_STORAGE", null, null);
mockMvc.perform(patch("/api/inventory/storage-locations/" + inactiveId + "/deactivate")
.header("Authorization", "Bearer " + adminToken))
.andExpect(status().isOk());
mockMvc.perform(get("/api/inventory/storage-locations")
.param("storageType", "COLD_ROOM")
.param("active", "true")
.header("Authorization", "Bearer " + adminToken))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(1)))
.andExpect(jsonPath("$[0].name").value("Kühl Aktiv"));
}
@Test
@DisplayName("Lagerorte mit ungültigem StorageType filtern → 400")
void listStorageLocations_invalidStorageType_returns400() throws Exception {
mockMvc.perform(get("/api/inventory/storage-locations")
.param("storageType", "INVALID")
.header("Authorization", "Bearer " + adminToken))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value("INVALID_STORAGE_TYPE"));
}
@Test
@DisplayName("Lagerorte abfragen mit STOCK_READ → 200")
void listStorageLocations_withReaderToken_returns200() throws Exception {
createAndReturnId("Reader Test", "DRY_STORAGE", null, null);
mockMvc.perform(get("/api/inventory/storage-locations")
.header("Authorization", "Bearer " + readerToken))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(1)));
}
@Test
@DisplayName("Lagerorte abfragen ohne passende Berechtigung → 403")
void listStorageLocations_withViewerToken_returns403() throws Exception {
mockMvc.perform(get("/api/inventory/storage-locations")
.header("Authorization", "Bearer " + viewerToken))
.andExpect(status().isForbidden());
}
@Test
@DisplayName("Lagerorte abfragen ohne Token → 401")
void listStorageLocations_withoutToken_returns401() throws Exception {
mockMvc.perform(get("/api/inventory/storage-locations"))
.andExpect(status().isUnauthorized());
}
@Test
@DisplayName("Leere Liste wenn keine Lagerorte existieren → 200")
void listStorageLocations_empty_returns200() throws Exception {
mockMvc.perform(get("/api/inventory/storage-locations")
.header("Authorization", "Bearer " + adminToken))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(0)));
}
@Test
@DisplayName("Lagerorte enthalten vollständige Daten (id, name, storageType, temperatureRange, active)")
void listStorageLocations_returnsCompleteData() throws Exception {
createAndReturnId("Vollständig", "COLD_ROOM", "-2", "8");
mockMvc.perform(get("/api/inventory/storage-locations")
.header("Authorization", "Bearer " + adminToken))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].id").isNotEmpty())
.andExpect(jsonPath("$[0].name").value("Vollständig"))
.andExpect(jsonPath("$[0].storageType").value("COLD_ROOM"))
.andExpect(jsonPath("$[0].temperatureRange.minTemperature").value(-2))
.andExpect(jsonPath("$[0].temperatureRange.maxTemperature").value(8))
.andExpect(jsonPath("$[0].active").value(true));
}
// ==================== Hilfsmethoden ====================
private String createAndReturnId(String name, String storageType, String minTemp, String maxTemp) throws Exception {