1
0
Fork 0
mirror of https://github.com/s-frick/effigenix.git synced 2026-03-28 08:29:36 +01:00

feat(production): Produktionsauftrag umterminieren und abfragen (US-P17)

Reschedule (PLANNED/RELEASED) mit Datumsvalidierung und List-Endpoint
mit optionaler Filterung nach Datum/Status als Full Vertical Slice.
Lasttests um neue Szenarien erweitert.
This commit is contained in:
Sebastian Frick 2026-02-25 22:37:20 +01:00
parent d63ac899e7
commit ad33eed2f4
17 changed files with 1061 additions and 8 deletions

View file

@ -147,6 +147,35 @@ public final class ProductionScenario {
);
}
public static ChainBuilder rescheduleProductionOrder() {
return exec(
http("Produktionsauftrag umterminieren")
.post("/api/production/production-orders/#{productionOrderId}/reschedule")
.header("Authorization", "Bearer #{accessToken}")
.header("Content-Type", "application/json")
.body(StringBody(JsonBodyBuilder.rescheduleProductionOrderBody()))
.check(status().in(200, 400, 409, 500))
);
}
public static ChainBuilder listProductionOrders() {
return exec(
http("Produktionsaufträge auflisten")
.get("/api/production/production-orders")
.header("Authorization", "Bearer #{accessToken}")
.check(status().is(200))
);
}
public static ChainBuilder listProductionOrdersByStatus() {
return exec(
http("Produktionsaufträge nach Status")
.get("/api/production/production-orders?status=PLANNED")
.header("Authorization", "Bearer #{accessToken}")
.check(status().is(200))
);
}
// ---- Zusammengesetztes Szenario ----
/**
@ -216,13 +245,20 @@ public final class ProductionScenario {
exec(completeProductionOrder())
)
.pause(1, 2)
// Neuen Auftrag anlegen und direkt stornieren
// Neuen Auftrag anlegen, umterminieren und dann stornieren
.exec(createProductionOrder())
.pause(1, 2)
.doIf(session -> session.contains("productionOrderId")).then(
exec(cancelProductionOrder())
exec(rescheduleProductionOrder())
.pause(1, 2)
.exec(cancelProductionOrder())
)
.pause(1, 2)
// Produktionsaufträge auflisten (ungefiltert + nach Status)
.exec(listProductionOrders())
.pause(1, 2)
.exec(listProductionOrdersByStatus())
.pause(1, 2)
// Nochmal Chargen-Liste prüfen
.exec(listBatches());
}
@ -235,9 +271,11 @@ public final class ProductionScenario {
.exec(AuthenticationScenario.login("admin", "admin123"))
.repeat(15).on(
randomSwitch().on(
percent(40.0).then(listRecipes()),
percent(30.0).then(getRandomRecipe()),
percent(30.0).then(listBatches())
percent(30.0).then(listRecipes()),
percent(20.0).then(getRandomRecipe()),
percent(20.0).then(listBatches()),
percent(15.0).then(listProductionOrders()),
percent(15.0).then(listProductionOrdersByStatus())
).pause(1, 3)
);
}

View file

@ -119,7 +119,12 @@ public class FullWorkloadSimulation extends Simulation {
details("Produktionsauftrag freigeben").responseTime().mean().lt(50),
details("Produktionsauftrag abschließen").responseTime().mean().lt(50),
details("Produktionsauftrag stornieren").responseTime().mean().lt(50),
details("Bestandsbewegung erfassen").responseTime().mean().lt(50)
details("Produktionsauftrag umterminieren").responseTime().mean().lt(50),
details("Bestandsbewegung erfassen").responseTime().mean().lt(50),
// Produktionsaufträge-Listen: mean < 35ms
details("Produktionsaufträge auflisten").responseTime().mean().lt(35),
details("Produktionsaufträge nach Status").responseTime().mean().lt(35)
);
}
}

View file

@ -99,4 +99,9 @@ public final class JsonBodyBuilder {
{"recipeId":"%s","plannedQuantity":"20","plannedQuantityUnit":"KG","plannedDate":"%s","priority":"NORMAL"}"""
.formatted(recipeId, LocalDate.now().plusDays(1));
}
public static String rescheduleProductionOrderBody() {
return """
{"newPlannedDate":"%s"}""".formatted(LocalDate.now().plusDays(7));
}
}