mirror of
https://github.com/s-frick/effigenix.git
synced 2026-03-28 13:59:36 +01:00
feat(inventory): StorageLocation bearbeiten und (de-)aktivieren (#2)
Use Cases: UpdateStorageLocation, DeactivateStorageLocation, ActivateStorageLocation
Endpoints: PUT /{id}, PATCH /{id}/deactivate, PATCH /{id}/activate
Repository: existsByNameAndIdNot für Uniqueness-Check bei Update
Tests: 14 neue Integrationstests (25 gesamt)
This commit is contained in:
parent
05878b1ce9
commit
24a6869faf
11 changed files with 493 additions and 2 deletions
|
|
@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||
import de.effigenix.domain.usermanagement.RoleName;
|
||||
import de.effigenix.domain.usermanagement.UserStatus;
|
||||
import de.effigenix.infrastructure.inventory.web.dto.CreateStorageLocationRequest;
|
||||
import de.effigenix.infrastructure.inventory.web.dto.UpdateStorageLocationRequest;
|
||||
import de.effigenix.infrastructure.usermanagement.persistence.entity.RoleEntity;
|
||||
import de.effigenix.infrastructure.usermanagement.persistence.entity.UserEntity;
|
||||
import de.effigenix.infrastructure.usermanagement.persistence.repository.RoleJpaRepository;
|
||||
|
|
@ -35,7 +36,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||
/**
|
||||
* Integrationstests für StorageLocationController.
|
||||
*
|
||||
* Abgedeckte Testfälle: Story 1.1 – Lagerort anlegen
|
||||
* Abgedeckte Testfälle:
|
||||
* - Story 1.1 – Lagerort anlegen
|
||||
* - Story 1.2 – Lagerort bearbeiten und (de-)aktivieren
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@AutoConfigureMockMvc
|
||||
|
|
@ -273,8 +276,212 @@ class StorageLocationControllerIntegrationTest {
|
|||
}
|
||||
}
|
||||
|
||||
// ==================== Lagerort bearbeiten (Story 1.2) ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("Lagerort Name ändern → 200")
|
||||
void updateStorageLocation_changeName_returns200() throws Exception {
|
||||
String id = createAndReturnId("Update Test", "DRY_STORAGE", null, null);
|
||||
|
||||
var request = new UpdateStorageLocationRequest("Neuer Name", null, null);
|
||||
|
||||
mockMvc.perform(put("/api/inventory/storage-locations/" + id)
|
||||
.header("Authorization", "Bearer " + adminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").value(id))
|
||||
.andExpect(jsonPath("$.name").value("Neuer Name"))
|
||||
.andExpect(jsonPath("$.storageType").value("DRY_STORAGE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Lagerort Temperaturbereich ändern → 200")
|
||||
void updateStorageLocation_changeTemperatureRange_returns200() throws Exception {
|
||||
String id = createAndReturnId("Temp Update", "COLD_ROOM", "-2", "8");
|
||||
|
||||
var request = new UpdateStorageLocationRequest(null, "-5", "12");
|
||||
|
||||
mockMvc.perform(put("/api/inventory/storage-locations/" + id)
|
||||
.header("Authorization", "Bearer " + adminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.name").value("Temp Update"))
|
||||
.andExpect(jsonPath("$.temperatureRange.minTemperature").value(-5))
|
||||
.andExpect(jsonPath("$.temperatureRange.maxTemperature").value(12));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Lagerort mit ungültigem Namen aktualisieren → 400")
|
||||
void updateStorageLocation_withBlankName_returns400() throws Exception {
|
||||
String id = createAndReturnId("Blank Update", "DRY_STORAGE", null, null);
|
||||
|
||||
var request = new UpdateStorageLocationRequest("", null, null);
|
||||
|
||||
mockMvc.perform(put("/api/inventory/storage-locations/" + id)
|
||||
.header("Authorization", "Bearer " + adminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.code").value("INVALID_STORAGE_LOCATION_NAME"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Lagerort mit doppeltem Namen aktualisieren → 409")
|
||||
void updateStorageLocation_withDuplicateName_returns409() throws Exception {
|
||||
createAndReturnId("Existing Name", "DRY_STORAGE", null, null);
|
||||
String id = createAndReturnId("To Rename", "COLD_ROOM", null, null);
|
||||
|
||||
var request = new UpdateStorageLocationRequest("Existing Name", null, null);
|
||||
|
||||
mockMvc.perform(put("/api/inventory/storage-locations/" + id)
|
||||
.header("Authorization", "Bearer " + adminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isConflict())
|
||||
.andExpect(jsonPath("$.code").value("STORAGE_LOCATION_NAME_EXISTS"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Lagerort mit eigenem Namen aktualisieren → 200 (kein Duplikat)")
|
||||
void updateStorageLocation_withOwnName_returns200() throws Exception {
|
||||
String id = createAndReturnId("Same Name", "DRY_STORAGE", null, null);
|
||||
|
||||
var request = new UpdateStorageLocationRequest("Same Name", null, null);
|
||||
|
||||
mockMvc.perform(put("/api/inventory/storage-locations/" + id)
|
||||
.header("Authorization", "Bearer " + adminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.name").value("Same Name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Nicht existierenden Lagerort aktualisieren → 404")
|
||||
void updateStorageLocation_notFound_returns404() throws Exception {
|
||||
var request = new UpdateStorageLocationRequest("New Name", null, null);
|
||||
|
||||
mockMvc.perform(put("/api/inventory/storage-locations/" + UUID.randomUUID())
|
||||
.header("Authorization", "Bearer " + adminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isNotFound())
|
||||
.andExpect(jsonPath("$.code").value("STORAGE_LOCATION_NOT_FOUND"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Lagerort aktualisieren ohne STOCK_WRITE → 403")
|
||||
void updateStorageLocation_withViewerToken_returns403() throws Exception {
|
||||
var request = new UpdateStorageLocationRequest("Name", null, null);
|
||||
|
||||
mockMvc.perform(put("/api/inventory/storage-locations/" + UUID.randomUUID())
|
||||
.header("Authorization", "Bearer " + viewerToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
// ==================== Lagerort deaktivieren (Story 1.2) ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("Aktiven Lagerort deaktivieren → 200")
|
||||
void deactivateStorageLocation_active_returns200() throws Exception {
|
||||
String id = createAndReturnId("Deactivate Test", "DRY_STORAGE", null, null);
|
||||
|
||||
mockMvc.perform(patch("/api/inventory/storage-locations/" + id + "/deactivate")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").value(id))
|
||||
.andExpect(jsonPath("$.active").value(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Bereits inaktiven Lagerort deaktivieren → 409")
|
||||
void deactivateStorageLocation_alreadyInactive_returns409() throws Exception {
|
||||
String id = createAndReturnId("Double Deactivate", "DRY_STORAGE", null, null);
|
||||
|
||||
mockMvc.perform(patch("/api/inventory/storage-locations/" + id + "/deactivate")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
mockMvc.perform(patch("/api/inventory/storage-locations/" + id + "/deactivate")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isConflict())
|
||||
.andExpect(jsonPath("$.code").value("ALREADY_INACTIVE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Nicht existierenden Lagerort deaktivieren → 404")
|
||||
void deactivateStorageLocation_notFound_returns404() throws Exception {
|
||||
mockMvc.perform(patch("/api/inventory/storage-locations/" + UUID.randomUUID() + "/deactivate")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isNotFound())
|
||||
.andExpect(jsonPath("$.code").value("STORAGE_LOCATION_NOT_FOUND"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Lagerort deaktivieren ohne STOCK_WRITE → 403")
|
||||
void deactivateStorageLocation_withViewerToken_returns403() throws Exception {
|
||||
mockMvc.perform(patch("/api/inventory/storage-locations/" + UUID.randomUUID() + "/deactivate")
|
||||
.header("Authorization", "Bearer " + viewerToken))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
// ==================== Lagerort aktivieren (Story 1.2) ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("Inaktiven Lagerort aktivieren → 200")
|
||||
void activateStorageLocation_inactive_returns200() throws Exception {
|
||||
String id = createAndReturnId("Activate Test", "DRY_STORAGE", null, null);
|
||||
|
||||
mockMvc.perform(patch("/api/inventory/storage-locations/" + id + "/deactivate")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
mockMvc.perform(patch("/api/inventory/storage-locations/" + id + "/activate")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").value(id))
|
||||
.andExpect(jsonPath("$.active").value(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Bereits aktiven Lagerort aktivieren → 409")
|
||||
void activateStorageLocation_alreadyActive_returns409() throws Exception {
|
||||
String id = createAndReturnId("Double Activate", "DRY_STORAGE", null, null);
|
||||
|
||||
mockMvc.perform(patch("/api/inventory/storage-locations/" + id + "/activate")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isConflict())
|
||||
.andExpect(jsonPath("$.code").value("ALREADY_ACTIVE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Nicht existierenden Lagerort aktivieren → 404")
|
||||
void activateStorageLocation_notFound_returns404() throws Exception {
|
||||
mockMvc.perform(patch("/api/inventory/storage-locations/" + UUID.randomUUID() + "/activate")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isNotFound())
|
||||
.andExpect(jsonPath("$.code").value("STORAGE_LOCATION_NOT_FOUND"));
|
||||
}
|
||||
|
||||
// ==================== Hilfsmethoden ====================
|
||||
|
||||
private String createAndReturnId(String name, String storageType, String minTemp, String maxTemp) throws Exception {
|
||||
var request = new CreateStorageLocationRequest(name, storageType, minTemp, maxTemp);
|
||||
|
||||
var result = mockMvc.perform(post("/api/inventory/storage-locations")
|
||||
.header("Authorization", "Bearer " + adminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isCreated())
|
||||
.andReturn();
|
||||
|
||||
return objectMapper.readTree(result.getResponse().getContentAsString()).get("id").asText();
|
||||
}
|
||||
|
||||
private String generateToken(String userId, String username, String permissions) {
|
||||
long now = System.currentTimeMillis();
|
||||
javax.crypto.SecretKey key = io.jsonwebtoken.security.Keys.hmacShaKeyFor(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue