mirror of
https://github.com/s-frick/effigenix.git
synced 2026-03-28 08:29:36 +01:00
feat(tui,seed): Seed-Testdaten und Bestandsbewegung-Detail verbessern
Seed-Daten SQL-File (099-seed-testdata.sql) mit realistischem Szenario "Fleischerei & Feinkost" erstellt: 6 User, 6 Kategorien, 5 Lieferanten, 18 Artikel, 5 Kunden, 5 Lagerorte, Bestände, Rezepte, Chargen, Produktionsaufträge und Bestandsbewegungen. StockMovement-Detailseite: IDs durch lesbare Namen ersetzt (Lagerort, Artikel, Benutzer) mit ausgegrautem ID dahinter, stockBatchId entfernt.
This commit is contained in:
parent
6504d3a54e
commit
d63ac899e7
3 changed files with 617 additions and 8 deletions
|
|
@ -1,11 +1,12 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Box, Text, useInput } from 'ink';
|
||||
import { useNavigation } from '../../state/navigation-context.js';
|
||||
import { useStockMovements } from '../../hooks/useStockMovements.js';
|
||||
import { LoadingSpinner } from '../shared/LoadingSpinner.js';
|
||||
import { ErrorDisplay } from '../shared/ErrorDisplay.js';
|
||||
import { MOVEMENT_TYPE_LABELS, MOVEMENT_DIRECTION_LABELS } from '@effigenix/api-client';
|
||||
import type { MovementType, MovementDirection } from '@effigenix/api-client';
|
||||
import { MOVEMENT_TYPE_LABELS, MOVEMENT_DIRECTION_LABELS, STORAGE_TYPE_LABELS } from '@effigenix/api-client';
|
||||
import type { MovementType, MovementDirection, StorageType } from '@effigenix/api-client';
|
||||
import { client } from '../../utils/api-client.js';
|
||||
|
||||
const DIRECTION_COLORS: Record<string, string> = {
|
||||
IN: 'green',
|
||||
|
|
@ -16,12 +17,51 @@ export function StockMovementDetailScreen() {
|
|||
const { params, back } = useNavigation();
|
||||
const { movement, loading, error, fetchMovement, clearError } = useStockMovements();
|
||||
|
||||
const [storageLabel, setStorageLabel] = useState<string | null>(null);
|
||||
const [articleLabel, setArticleLabel] = useState<string | null>(null);
|
||||
const [userLabel, setUserLabel] = useState<string | null>(null);
|
||||
|
||||
const movementId = params.movementId ?? '';
|
||||
|
||||
useEffect(() => {
|
||||
if (movementId) void fetchMovement(movementId);
|
||||
}, [fetchMovement, movementId]);
|
||||
|
||||
// Resolve Storage Location via Stock → StorageLocation
|
||||
useEffect(() => {
|
||||
if (!movement?.stockId) return;
|
||||
void (async () => {
|
||||
try {
|
||||
const stock = await client.stocks.getById(movement.stockId);
|
||||
const loc = await client.storageLocations.getById(stock.storageLocationId);
|
||||
const typeLabel = STORAGE_TYPE_LABELS[loc.storageType as StorageType] ?? loc.storageType;
|
||||
setStorageLabel(`${loc.name} (${typeLabel})`);
|
||||
} catch { setStorageLabel(null); }
|
||||
})();
|
||||
}, [movement?.stockId]);
|
||||
|
||||
// Resolve Article name + number
|
||||
useEffect(() => {
|
||||
if (!movement?.articleId) return;
|
||||
void (async () => {
|
||||
try {
|
||||
const article = await client.articles.getById(movement.articleId);
|
||||
setArticleLabel(`${article.name} (${article.articleNumber})`);
|
||||
} catch { setArticleLabel(null); }
|
||||
})();
|
||||
}, [movement?.articleId]);
|
||||
|
||||
// Resolve User
|
||||
useEffect(() => {
|
||||
if (!movement?.performedBy) return;
|
||||
void (async () => {
|
||||
try {
|
||||
const user = await client.users.getById(movement.performedBy);
|
||||
setUserLabel(user.username);
|
||||
} catch { setUserLabel(null); }
|
||||
})();
|
||||
}, [movement?.performedBy]);
|
||||
|
||||
useInput((_input, key) => {
|
||||
if (key.backspace || key.escape) back();
|
||||
});
|
||||
|
|
@ -58,9 +98,8 @@ export function StockMovementDetailScreen() {
|
|||
<Box><Text color="gray">Typ: </Text><Text>{typeLabel}</Text></Box>
|
||||
<Box><Text color="gray">Richtung: </Text><Text color={dirColor}>{dirLabel}</Text></Box>
|
||||
<Box><Text color="gray">Menge: </Text><Text>{movement.quantityAmount} {movement.quantityUnit}</Text></Box>
|
||||
<Box><Text color="gray">Stock-ID: </Text><Text>{movement.stockId}</Text></Box>
|
||||
<Box><Text color="gray">Artikel-ID: </Text><Text>{movement.articleId}</Text></Box>
|
||||
<Box><Text color="gray">Chargen-Batch: </Text><Text>{movement.stockBatchId}</Text></Box>
|
||||
<Box><Text color="gray">Lagerort: </Text><Text>{storageLabel ?? '...'}</Text><Text dimColor> {movement.stockId}</Text></Box>
|
||||
<Box><Text color="gray">Artikel: </Text><Text>{articleLabel ?? '...'}</Text><Text dimColor> {movement.articleId}</Text></Box>
|
||||
<Box><Text color="gray">Chargen-Nr.: </Text><Text>{movement.batchId}</Text></Box>
|
||||
<Box><Text color="gray">Chargen-Typ: </Text><Text>{movement.batchType}</Text></Box>
|
||||
{movement.reason && (
|
||||
|
|
@ -69,7 +108,7 @@ export function StockMovementDetailScreen() {
|
|||
{movement.referenceDocumentId && (
|
||||
<Box><Text color="gray">Referenz-Dok.: </Text><Text>{movement.referenceDocumentId}</Text></Box>
|
||||
)}
|
||||
<Box><Text color="gray">Durchgeführt von:</Text><Text> {movement.performedBy}</Text></Box>
|
||||
<Box><Text color="gray">Durchgeführt von:</Text><Text> {userLabel ?? '...'}</Text><Text dimColor> {movement.performedBy}</Text></Box>
|
||||
<Box><Text color="gray">Zeitpunkt: </Text><Text>{dateStr}</Text></Box>
|
||||
</Box>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue