mirror of
https://github.com/s-frick/effigenix.git
synced 2026-03-28 13:59:36 +01:00
feat(scanner): Mobile Scanner App mit echten Produktionsaufträgen
Scanner-App Tauri v2 Android App mit Login, Barcode-Scanner, Consume/Move/Book-Flows und Aufgabenliste. TasksPage lädt echte RELEASED/IN_PROGRESS Produktionsaufträge via API, Consume-Flow nutzt den konkreten Auftrag für korrekte Rezept-Skalierung statt blind den ersten IN_PROGRESS-Auftrag zu nehmen. Backend: FindStockByBatchId Use Case + REST-Endpoint für Stock-Lookup per Chargennummer.
This commit is contained in:
parent
72979c9537
commit
bf09e3b747
93 changed files with 8977 additions and 60 deletions
|
|
@ -0,0 +1,28 @@
|
|||
package de.effigenix.application.inventory;
|
||||
|
||||
import de.effigenix.domain.inventory.Stock;
|
||||
import de.effigenix.domain.inventory.StockError;
|
||||
import de.effigenix.domain.inventory.StockRepository;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FindStockByBatchId {
|
||||
|
||||
private final StockRepository stockRepository;
|
||||
|
||||
public FindStockByBatchId(StockRepository stockRepository) {
|
||||
this.stockRepository = stockRepository;
|
||||
}
|
||||
|
||||
public Result<StockError, List<Stock>> execute(String batchId) {
|
||||
if (batchId == null || batchId.isBlank()) {
|
||||
return Result.failure(new StockError.InvalidBatchReference("Batch ID must not be blank"));
|
||||
}
|
||||
return switch (stockRepository.findAllByBatchId(batchId)) {
|
||||
case Result.Failure(var err) -> Result.failure(new StockError.RepositoryFailure(err.message()));
|
||||
case Result.Success(var stocks) -> Result.success(stocks);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ import de.effigenix.application.inventory.BookProductionOutput;
|
|||
import de.effigenix.application.inventory.ConfirmReservation;
|
||||
import de.effigenix.application.inventory.RecordStockMovement;
|
||||
import de.effigenix.application.inventory.ActivateStorageLocation;
|
||||
import de.effigenix.application.inventory.FindStockByBatchId;
|
||||
import de.effigenix.application.inventory.AddStockBatch;
|
||||
import de.effigenix.application.inventory.BlockStockBatch;
|
||||
import de.effigenix.application.inventory.CheckStockExpiry;
|
||||
|
|
@ -99,6 +100,11 @@ public class InventoryUseCaseConfiguration {
|
|||
return new ListStocks(stockRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FindStockByBatchId findStockByBatchId(StockRepository stockRepository) {
|
||||
return new FindStockByBatchId(stockRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AddStockBatch addStockBatch(StockRepository stockRepository, UnitOfWork unitOfWork) {
|
||||
return new AddStockBatch(stockRepository, unitOfWork);
|
||||
|
|
|
|||
|
|
@ -264,6 +264,24 @@ public class JdbcStockRepository implements StockRepository {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<Stock>> findAllByBatchId(String batchId) {
|
||||
try {
|
||||
var stocks = jdbc.sql("""
|
||||
SELECT DISTINCT s.* FROM stocks s
|
||||
JOIN stock_batches b ON b.stock_id = s.id
|
||||
WHERE b.batch_id = :batchId
|
||||
""")
|
||||
.param("batchId", batchId)
|
||||
.query(this::mapStockRow)
|
||||
.list();
|
||||
return Result.success(loadChildrenForAll(stocks));
|
||||
} catch (Exception e) {
|
||||
logger.trace("Database error in findAllByBatchId", e);
|
||||
return Result.failure(new RepositoryError.DatabaseError(e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, Void> save(Stock stock) {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package de.effigenix.infrastructure.inventory.web.controller;
|
||||
|
||||
import de.effigenix.application.inventory.FindStockByBatchId;
|
||||
import de.effigenix.application.inventory.AddStockBatch;
|
||||
import de.effigenix.application.inventory.BlockStockBatch;
|
||||
import de.effigenix.application.inventory.ConfirmReservation;
|
||||
|
|
@ -63,6 +64,7 @@ public class StockController {
|
|||
private final GetStock getStock;
|
||||
private final ListStocks listStocks;
|
||||
private final ListStocksBelowMinimum listStocksBelowMinimum;
|
||||
private final FindStockByBatchId findStockByBatchId;
|
||||
private final AddStockBatch addStockBatch;
|
||||
private final RemoveStockBatch removeStockBatch;
|
||||
private final BlockStockBatch blockStockBatch;
|
||||
|
|
@ -72,7 +74,7 @@ public class StockController {
|
|||
private final ConfirmReservation confirmReservation;
|
||||
|
||||
public StockController(CreateStock createStock, UpdateStock updateStock, GetStock getStock, ListStocks listStocks,
|
||||
ListStocksBelowMinimum listStocksBelowMinimum,
|
||||
ListStocksBelowMinimum listStocksBelowMinimum, FindStockByBatchId findStockByBatchId,
|
||||
AddStockBatch addStockBatch, RemoveStockBatch removeStockBatch,
|
||||
BlockStockBatch blockStockBatch, UnblockStockBatch unblockStockBatch,
|
||||
ReserveStock reserveStock, ReleaseReservation releaseReservation,
|
||||
|
|
@ -82,6 +84,7 @@ public class StockController {
|
|||
this.getStock = getStock;
|
||||
this.listStocks = listStocks;
|
||||
this.listStocksBelowMinimum = listStocksBelowMinimum;
|
||||
this.findStockByBatchId = findStockByBatchId;
|
||||
this.addStockBatch = addStockBatch;
|
||||
this.removeStockBatch = removeStockBatch;
|
||||
this.blockStockBatch = blockStockBatch;
|
||||
|
|
@ -109,6 +112,20 @@ public class StockController {
|
|||
};
|
||||
}
|
||||
|
||||
@GetMapping("/by-batch/{batchId}")
|
||||
@PreAuthorize("hasAuthority('STOCK_READ')")
|
||||
public ResponseEntity<List<StockResponse>> findByBatchId(@PathVariable String batchId) {
|
||||
return switch (findStockByBatchId.execute(batchId)) {
|
||||
case Result.Failure(var err) -> throw new StockDomainErrorException(err);
|
||||
case Result.Success(var stocks) -> {
|
||||
var responses = stocks.stream()
|
||||
.map(StockResponse::from)
|
||||
.toList();
|
||||
yield ResponseEntity.ok(responses);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: Must be declared before /{id} to avoid Spring matching "below-minimum" as path variable
|
||||
@GetMapping("/below-minimum")
|
||||
@PreAuthorize("hasAuthority('STOCK_READ')")
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public class SecurityConfig {
|
|||
@Bean
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.setAllowedOrigins(allowedOrigins);
|
||||
configuration.setAllowedOriginPatterns(List.of("*"));
|
||||
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
|
||||
configuration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
|
||||
configuration.setAllowCredentials(true);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ logging:
|
|||
# CORS Configuration
|
||||
effigenix:
|
||||
cors:
|
||||
allowed-origins: ${CORS_ALLOWED_ORIGINS:http://localhost:3000}
|
||||
allowed-origins: ${CORS_ALLOWED_ORIGINS:http://localhost:3000,http://localhost:1420,tauri://localhost}
|
||||
inventory:
|
||||
expiry-check-cron: "0 0 6 * * *"
|
||||
|
||||
|
|
|
|||
|
|
@ -153,5 +153,6 @@ class ListStocksBelowMinimumTest {
|
|||
@Override public Result<RepositoryError, List<Stock>> findAllWithExpiryRelevantBatches(LocalDate referenceDate) { return Result.success(List.of()); }
|
||||
@Override public Result<RepositoryError, List<Stock>> findAllByBatchId(String batchId) { return Result.success(List.of()); }
|
||||
@Override public Result<RepositoryError, Void> save(Stock stock) { return Result.success(null); }
|
||||
@Override public Result<RepositoryError, List<Stock>> findAllByBatchId(String batchId) { return Result.success(List.of()); }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue