u
This commit is contained in:
@@ -18,9 +18,15 @@ import Typography from '@mui/material/Typography';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import InputLabel from '@mui/material/InputLabel';
|
||||
import Select from '@mui/material/Select';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import FormHelperText from '@mui/material/FormHelperText';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import Inventory2OutlinedIcon from '@mui/icons-material/Inventory2Outlined';
|
||||
import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
|
||||
import WarehouseIcon from '@mui/icons-material/Warehouse';
|
||||
import { StorageManagerContext } from '../../api/storageManagerContext';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { notifyError } from '../../utils/notify';
|
||||
@@ -29,6 +35,7 @@ import {
|
||||
fetchDeliveryLedgerSummary,
|
||||
bookDeliveryLines,
|
||||
} from '../../utils/deliveryLedger';
|
||||
import warehouseAutomat from '../../automats/warehouseAutomat';
|
||||
|
||||
export default class BookDeliveryDialog extends PureComponent {
|
||||
static contextType = StorageManagerContext;
|
||||
@@ -52,6 +59,8 @@ export default class BookDeliveryDialog extends PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
const initialWarehouses = warehouseAutomat.state.warehouses || [];
|
||||
|
||||
this.state = {
|
||||
summary: props.summary ?? null,
|
||||
loading: !props.summary,
|
||||
@@ -61,9 +70,13 @@ export default class BookDeliveryDialog extends PureComponent {
|
||||
? `Lieferung ${props.delivery.number}`
|
||||
: 'Lieferung Wareneingang',
|
||||
isBooking: false,
|
||||
warehouses: initialWarehouses,
|
||||
selectedWarehouseId: initialWarehouses.length === 1 ? initialWarehouses[0].id : '',
|
||||
warehouseError: null,
|
||||
};
|
||||
|
||||
this.handleAmountChange = this.handleAmountChange.bind(this);
|
||||
this.handleWarehouseChange = this.handleWarehouseChange.bind(this);
|
||||
this.handleTransactionTextChange = this.handleTransactionTextChange.bind(this);
|
||||
this.handleBookAll = this.handleBookAll.bind(this);
|
||||
this.handleResetAmounts = this.handleResetAmounts.bind(this);
|
||||
@@ -71,24 +84,48 @@ export default class BookDeliveryDialog extends PureComponent {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.unsubWarehouse = warehouseAutomat.subscribe((state) => {
|
||||
const warehouses = state.warehouses || [];
|
||||
this.setState((prev) => {
|
||||
const selectedId =
|
||||
prev.selectedWarehouseId ||
|
||||
(warehouses.length === 1 ? warehouses[0].id : '');
|
||||
return {
|
||||
warehouses,
|
||||
selectedWarehouseId: selectedId,
|
||||
};
|
||||
});
|
||||
});
|
||||
void warehouseAutomat.actions.load().catch(() => {});
|
||||
|
||||
if (this.props.open) {
|
||||
void this.loadSummary();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.unsubWarehouse?.();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.open && !prevProps.open) {
|
||||
const currentWarehouses = this.state.warehouses || warehouseAutomat.state.warehouses || [];
|
||||
this.setState(
|
||||
{
|
||||
summary: this.props.summary ?? null,
|
||||
loading: !this.props.summary,
|
||||
error: null,
|
||||
warehouseError: null,
|
||||
selectedWarehouseId:
|
||||
this.state.selectedWarehouseId ||
|
||||
(currentWarehouses.length === 1 ? currentWarehouses[0].id : ''),
|
||||
transactionText: this.props.delivery?.number
|
||||
? `Lieferung ${this.props.delivery.number}`
|
||||
: 'Lieferung Wareneingang',
|
||||
isBooking: false,
|
||||
},
|
||||
() => {
|
||||
void warehouseAutomat.actions.load().catch(() => {});
|
||||
if (this.props.summary) {
|
||||
this.initAmountsFromSummary(this.props.summary, this.props.prefillLineId);
|
||||
} else {
|
||||
@@ -109,6 +146,14 @@ export default class BookDeliveryDialog extends PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
handleWarehouseChange(event) {
|
||||
const value = event.target.value;
|
||||
this.setState({
|
||||
selectedWarehouseId: value ? Number(value) : '',
|
||||
warehouseError: null,
|
||||
});
|
||||
}
|
||||
|
||||
async loadSummary() {
|
||||
const { delivery, prefillLineId } = this.props;
|
||||
if (!delivery?.id) return;
|
||||
@@ -201,7 +246,14 @@ export default class BookDeliveryDialog extends PureComponent {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ isBooking: true, error: null });
|
||||
const { selectedWarehouseId } = this.state;
|
||||
if (!selectedWarehouseId) {
|
||||
this.setState({ warehouseError: 'Bitte wählen Sie ein Ziellager aus.' });
|
||||
enqueueSnackbar('Bitte wählen Sie ein Ziellager aus.', { variant: 'warning' });
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ isBooking: true, error: null, warehouseError: null });
|
||||
try {
|
||||
const ledgerApi = this.context?.ledger;
|
||||
const deliveryApi = this.context?.delivery;
|
||||
@@ -209,6 +261,7 @@ export default class BookDeliveryDialog extends PureComponent {
|
||||
await bookDeliveryLines({
|
||||
delivery: summary.delivery || delivery,
|
||||
linesToBook,
|
||||
warehouseId: selectedWarehouseId,
|
||||
ledgerApi,
|
||||
transactionText,
|
||||
});
|
||||
@@ -443,6 +496,9 @@ export default class BookDeliveryDialog extends PureComponent {
|
||||
amountsToBook,
|
||||
transactionText,
|
||||
isBooking,
|
||||
warehouses,
|
||||
selectedWarehouseId,
|
||||
warehouseError,
|
||||
} = this.state;
|
||||
|
||||
const lines = summary?.lines || [];
|
||||
@@ -458,6 +514,8 @@ export default class BookDeliveryDialog extends PureComponent {
|
||||
(l) => Number(amountsToBook[l.id]) > 0
|
||||
).length;
|
||||
const isFullyBooked = summary?.status === 'booked';
|
||||
const selectedWarehouse = warehouses.find((w) => w.id === selectedWarehouseId);
|
||||
const isWarehouseMissing = !selectedWarehouseId;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
@@ -529,7 +587,59 @@ export default class BookDeliveryDialog extends PureComponent {
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Box sx={{ mb: 2 }}>
|
||||
{warehouses.length === 0 && !isFullyBooked && (
|
||||
<Alert severity="error" sx={{ mb: 2 }}>
|
||||
Es ist noch kein Lager eingerichtet. Bitte legen Sie unter „Artikel → Lager“ zuerst ein Lager an.
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
gap: 2,
|
||||
mb: 2,
|
||||
flexDirection: { xs: 'column', sm: 'row' },
|
||||
}}
|
||||
>
|
||||
<FormControl
|
||||
size="small"
|
||||
required
|
||||
error={Boolean(warehouseError)}
|
||||
disabled={isBooking || isFullyBooked}
|
||||
sx={{ minWidth: { sm: 240 }, flex: { sm: '0 0 auto' } }}
|
||||
>
|
||||
<InputLabel id="warehouse-select-label">Ziellager *</InputLabel>
|
||||
<Select
|
||||
labelId="warehouse-select-label"
|
||||
id="warehouse-select"
|
||||
value={selectedWarehouseId ?? ''}
|
||||
label="Ziellager *"
|
||||
onChange={this.handleWarehouseChange}
|
||||
startAdornment={
|
||||
<WarehouseIcon
|
||||
sx={{ mr: 1, color: 'text.secondary', fontSize: 20 }}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{warehouses.length === 0 ? (
|
||||
<MenuItem value="" disabled>
|
||||
Keine Lager vorhanden
|
||||
</MenuItem>
|
||||
) : (
|
||||
warehouses.map((wh) => (
|
||||
<MenuItem key={wh.id} value={wh.id}>
|
||||
{wh.name}
|
||||
</MenuItem>
|
||||
))
|
||||
)}
|
||||
</Select>
|
||||
{warehouseError ? (
|
||||
<FormHelperText>{warehouseError}</FormHelperText>
|
||||
) : (
|
||||
<FormHelperText>Pflichtfeld: Ziellager für die Buchung</FormHelperText>
|
||||
)}
|
||||
</FormControl>
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
size="small"
|
||||
@@ -546,9 +656,19 @@ export default class BookDeliveryDialog extends PureComponent {
|
||||
Alle Artikel dieser Lieferung sind bereits vollständig im Lager verbucht.
|
||||
</Alert>
|
||||
) : totalToBook > 0 ? (
|
||||
<Alert severity="info">
|
||||
Es werden <strong>{totalToBook} Stück</strong> für{' '}
|
||||
<strong>{countLinesToBook} Position{countLinesToBook === 1 ? '' : 'en'}</strong> als Lagerzugang (DELIVERY) im Ledger gebucht.
|
||||
<Alert severity={selectedWarehouseId ? 'info' : 'warning'}>
|
||||
{selectedWarehouseId ? (
|
||||
<>
|
||||
Es werden <strong>{totalToBook} Stück</strong> für{' '}
|
||||
<strong>{countLinesToBook} Position{countLinesToBook === 1 ? '' : 'en'}</strong> als Lagerzugang (DELIVERY) in das Lager{' '}
|
||||
<strong>„{selectedWarehouse?.name || '–'}“</strong> gebucht.
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
Bitte wählen Sie ein <strong>Ziellager</strong> aus, um die Buchung von{' '}
|
||||
<strong>{totalToBook} Stück</strong> durchzuführen.
|
||||
</>
|
||||
)}
|
||||
</Alert>
|
||||
) : (
|
||||
<Alert severity="warning">
|
||||
@@ -569,7 +689,7 @@ export default class BookDeliveryDialog extends PureComponent {
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={this.handleConfirmBook}
|
||||
disabled={isBooking || totalToBook <= 0 || loading}
|
||||
disabled={isBooking || totalToBook <= 0 || loading || isWarehouseMissing}
|
||||
startIcon={
|
||||
isBooking ? (
|
||||
<CircularProgress size={16} color="inherit" />
|
||||
|
||||
Reference in New Issue
Block a user