import { PureComponent } from 'react'; import Autocomplete from '@mui/material/Autocomplete'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import AppDialog from '../AppDialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogTitle from '@mui/material/DialogTitle'; import InputAdornment from '@mui/material/InputAdornment'; import MenuItem from '@mui/material/MenuItem'; import Stack from '@mui/material/Stack'; import TextInput from '../TextInput'; import Typography from '@mui/material/Typography'; import { companyTaxRateOptions } from '../../utils/articleDetail'; import { formatPriceAmount, parsePriceInput } from '../../utils/price'; function parseNumber(value, min = 0) { if (value === '' || value == null) return null; const num = Number(String(value).trim().replace(',', '.')); return Number.isFinite(num) && num >= min ? num : null; } export default class ArticleSupplierDialog extends PureComponent { constructor(props) { super(props); this.state = this.initState(props); } componentDidUpdate(prevProps) { if (this.props.open && !prevProps.open) { this.setState(this.initState(this.props)); } } initState(props) { const item = props.item; const defaultTaxRate = props.company?.taxrate != null ? Number(props.company.taxrate) : 19; return { entityId: item?.entityId ? Number(item.entityId) : null, sku: item?.sku ?? '', pu: item?.pu != null ? String(item.pu) : '1', stock: item?.stock != null ? String(item.stock) : '', netPrice: item?.price?.net != null ? formatPriceAmount(item.price.net) : '', taxRate: item?.price?.taxRate != null ? Number(item.price.taxRate) : defaultTaxRate, submitting: false, }; } handleSubmit = async (e) => { e.preventDefault(); const { entityId, sku, pu, stock, netPrice, taxRate } = this.state; const isEdit = Boolean(this.props.item?.id); if (!isEdit && !entityId) return; const parsedPu = parseNumber(pu, 0.0001); if (parsedPu == null || parsedPu <= 0) { return; } const parsedStock = parseNumber(stock, 0); const parsedNet = netPrice !== '' ? parsePriceInput(netPrice) : null; this.setState({ submitting: true }); try { await this.props.onSave({ id: this.props.item?.id, entityId: isEdit ? this.props.item.entityId : entityId, sku: sku.trim() || null, pu: parsedPu, stock: parsedStock, netPrice: parsedNet, taxRate: parsedNet != null ? taxRate : undefined, }); } finally { this.setState({ submitting: false }); } }; render() { const { open, onClose, suppliers = [], item, company, assignedEntityIds = [], } = this.props; const { entityId, sku, pu, stock, netPrice, taxRate, submitting } = this.state; const isEdit = Boolean(item?.id); const availableSuppliers = isEdit ? suppliers : suppliers.filter( (s) => !assignedEntityIds.includes(s.id) || s.id === entityId, ); const selectedSupplier = suppliers.find((s) => s.id === entityId) ?? null; const taxOptions = companyTaxRateOptions(company, taxRate); const parsedPu = parseNumber(pu, 0.0001); const puValid = parsedPu != null && parsedPu > 0; return (
{isEdit ? 'Lieferant bearbeiten' : 'Lieferant zuweisen'} {isEdit ? ( Lieferant {item.supplierName ?? `Lieferant #${item.entityId}`} ) : ( opt.name ?? `Lieferant #${opt.id}`} value={selectedSupplier} onChange={(_e, val) => this.setState({ entityId: val ? val.id : null })} renderInput={(params) => ( )} isOptionEqualToValue={(opt, val) => opt.id === val.id} /> )} this.setState({ sku: e.target.value })} placeholder="z. B. LF-09412" helperText="Wird beim Abgleich von Lieferscheinen / Wareneingängen genutzt" /> this.setState({ pu: e.target.value })} sx={{ flex: 1 }} /> this.setState({ stock: e.target.value })} sx={{ flex: 1 }} helperText="Optional (in Stk / Mengeneinheit)" /> this.setState({ netPrice: e.target.value })} placeholder="0,00" InputProps={{ endAdornment: ( € ), }} sx={{ flex: 1 }} helperText="Optionaler Einkaufspreis (EK)" /> this.setState({ taxRate: Number(e.target.value) }) } sx={{ width: { sm: 160 } }} disabled={!netPrice} > {taxOptions.map((rate) => ( {rate} % ))}
); } }