Disable menu/popover animations; update manifest handling
This commit is contained in:
@@ -557,7 +557,9 @@ export const supplier = {
|
||||
|
||||
/**
|
||||
* Company-scoped goods receipts (manifest type = delivery).
|
||||
* DeliverySummary = { id, number, type: 'delivery', supplierId, date }
|
||||
* DeliverySummary = { id, number, externalNumber, type: 'delivery', supplierId, date }
|
||||
* - number: server-allocated, read-only manifest number (from nextNumber('delivery')).
|
||||
* - externalNumber: user-entered reference (nullable).
|
||||
* DeliveryLine = { id, articleId, sku, amount, net, transactedAmount, rebate, tax, comment }
|
||||
* Delivery = DeliverySummary & { lines: DeliveryLine[] }
|
||||
* DeliveryLineInput = { sku, amount, net, tax, rebate?, transactedAmount?, comment? }
|
||||
@@ -575,7 +577,9 @@ export const delivery = {
|
||||
|
||||
/**
|
||||
* POST /api/delivery
|
||||
* Body: { number, date, supplierId?, lines: DeliveryLineInput[] }
|
||||
* Body: { externalNumber?, date, supplierId?, lines: DeliveryLineInput[] }
|
||||
* number is NOT sent — the server allocates it automatically. The
|
||||
* caller-supplied reference goes in externalNumber (nullable).
|
||||
* Line requires sku, amount, net, tax. rebate→0, transactedAmount→amount.
|
||||
* → 201 { delivery: Delivery }
|
||||
*/
|
||||
@@ -585,7 +589,9 @@ export const delivery = {
|
||||
|
||||
/**
|
||||
* PATCH /api/delivery/:id
|
||||
* Body: partial { number?, date?, supplierId?, lines? }.
|
||||
* Body: partial { externalNumber?, date?, supplierId?, lines? }.
|
||||
* number is read-only and cannot be edited. externalNumber is editable and
|
||||
* can be cleared by sending null or an empty string.
|
||||
* If lines present, replaces all lines; if omitted, lines unchanged.
|
||||
* → 200 { delivery: Delivery }
|
||||
*/
|
||||
|
||||
@@ -35,6 +35,7 @@ class ManifestForm extends PureComponent {
|
||||
date: '',
|
||||
partyId: null,
|
||||
number: '',
|
||||
externalNumber: '',
|
||||
lines: [emptyLine()],
|
||||
saving: false,
|
||||
};
|
||||
@@ -43,6 +44,8 @@ class ManifestForm extends PureComponent {
|
||||
this.handlePartyChange = this.handlePartyChange.bind(this);
|
||||
this.handleDateChange = this.handleDateChange.bind(this);
|
||||
this.handleNumberChange = this.handleNumberChange.bind(this);
|
||||
this.handleExternalNumberChange =
|
||||
this.handleExternalNumberChange.bind(this);
|
||||
this.handleLineChange = this.handleLineChange.bind(this);
|
||||
this.handleAddLine = this.handleAddLine.bind(this);
|
||||
this.handleRemoveLine = this.handleRemoveLine.bind(this);
|
||||
@@ -122,6 +125,8 @@ class ManifestForm extends PureComponent {
|
||||
date: dateInputValue(doc.date),
|
||||
partyId: doc[cfg.partyField],
|
||||
number: doc.number ?? '',
|
||||
externalNumber:
|
||||
doc.externalNumber != null ? String(doc.externalNumber) : '',
|
||||
lines,
|
||||
});
|
||||
} catch (err) {
|
||||
@@ -157,6 +162,10 @@ class ManifestForm extends PureComponent {
|
||||
this.setState({ number });
|
||||
}
|
||||
|
||||
handleExternalNumberChange(externalNumber) {
|
||||
this.setState({ externalNumber });
|
||||
}
|
||||
|
||||
handleLineChange(key, field, value) {
|
||||
this.setState((prev) => ({
|
||||
lines: prev.lines.map((line) =>
|
||||
@@ -188,11 +197,16 @@ class ManifestForm extends PureComponent {
|
||||
body = buildManifestBody(
|
||||
{
|
||||
number: this.state.number,
|
||||
externalNumber: this.state.externalNumber,
|
||||
date: this.state.date,
|
||||
partyId: this.state.partyId,
|
||||
lines: this.state.lines,
|
||||
},
|
||||
{ partyField: cfg.partyField, requireAtLeastOne },
|
||||
{
|
||||
partyField: cfg.partyField,
|
||||
requireAtLeastOne,
|
||||
externalNumber: cfg.externalNumber,
|
||||
},
|
||||
);
|
||||
} catch (err) {
|
||||
notifyError(err);
|
||||
@@ -225,6 +239,8 @@ class ManifestForm extends PureComponent {
|
||||
date: dateInputValue(doc.date),
|
||||
partyId: doc[cfg.partyField],
|
||||
number: doc.number ?? '',
|
||||
externalNumber:
|
||||
doc.externalNumber != null ? String(doc.externalNumber) : '',
|
||||
lines:
|
||||
apiLines.length > 0 ? apiLines.map(lineFromApi) : [emptyLine()],
|
||||
saving: false,
|
||||
@@ -280,6 +296,7 @@ class ManifestForm extends PureComponent {
|
||||
date,
|
||||
partyId,
|
||||
number,
|
||||
externalNumber,
|
||||
saving,
|
||||
} = this.state;
|
||||
|
||||
@@ -307,10 +324,12 @@ class ManifestForm extends PureComponent {
|
||||
partyId={partyId}
|
||||
date={date}
|
||||
number={number}
|
||||
externalNumber={externalNumber}
|
||||
saving={saving}
|
||||
onPartyChange={this.handlePartyChange}
|
||||
onDateChange={this.handleDateChange}
|
||||
onNumberChange={this.handleNumberChange}
|
||||
onExternalNumberChange={this.handleExternalNumberChange}
|
||||
/>
|
||||
{status === 'ready' ? this.renderArticles() : null}
|
||||
</PanelTileGrid>
|
||||
|
||||
@@ -4,7 +4,7 @@ import Stack from '@mui/material/Stack';
|
||||
import TextField from '@mui/material/TextField';
|
||||
import SingleLineTextEdit from '../SingleLineTextEdit';
|
||||
import { PanelTile } from '../panels';
|
||||
import { partyDisplayName } from './manifestConfig';
|
||||
import { manifestConfig, partyDisplayName } from './manifestConfig';
|
||||
|
||||
class ManifestHeader extends PureComponent {
|
||||
constructor(props) {
|
||||
@@ -27,12 +27,20 @@ class ManifestHeader extends PureComponent {
|
||||
partyId,
|
||||
date,
|
||||
number,
|
||||
externalNumber,
|
||||
saving,
|
||||
onDateChange,
|
||||
onNumberChange,
|
||||
onExternalNumberChange,
|
||||
} = this.props;
|
||||
|
||||
const selected = parties.find((row) => row.id === partyId) ?? null;
|
||||
// Delivery: number is server-allocated/read-only; the caller reference
|
||||
// lives in the editable externalNumber field.
|
||||
const cfg = manifestConfig(kind);
|
||||
const useExternalNumber = Boolean(cfg.externalNumber);
|
||||
|
||||
const selected =
|
||||
parties.find((row) => row.id === partyId) ?? null;
|
||||
|
||||
return (
|
||||
<PanelTile wide={3} minHeight={160} color={headerColor} title="Kopfdaten">
|
||||
@@ -80,10 +88,20 @@ class ManifestHeader extends PureComponent {
|
||||
size="small"
|
||||
label="Nummer"
|
||||
value={number}
|
||||
disabled={saving}
|
||||
disabled={saving || useExternalNumber}
|
||||
onChange={onNumberChange}
|
||||
sx={{ minWidth: 180, flex: 1 }}
|
||||
/>
|
||||
{useExternalNumber ? (
|
||||
<SingleLineTextEdit
|
||||
size="small"
|
||||
label="Referenz"
|
||||
value={externalNumber ?? ''}
|
||||
disabled={saving}
|
||||
onChange={onExternalNumberChange}
|
||||
sx={{ minWidth: 180, flex: 1 }}
|
||||
/>
|
||||
) : null}
|
||||
</Stack>
|
||||
</PanelTile>
|
||||
);
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
formatDate,
|
||||
loadParties,
|
||||
manifestConfig,
|
||||
numberDisplay,
|
||||
partyDisplayName,
|
||||
sortDocs,
|
||||
} from './manifestConfig';
|
||||
@@ -169,6 +170,9 @@ class ManifestList extends PureComponent {
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Nummer</TableCell>
|
||||
{cfg.externalNumber ? (
|
||||
<TableCell>Referenz</TableCell>
|
||||
) : null}
|
||||
<TableCell>{cfg.dateLabel}</TableCell>
|
||||
<TableCell>{cfg.partyLabel}</TableCell>
|
||||
<TableCell padding="checkbox" />
|
||||
@@ -183,6 +187,11 @@ class ManifestList extends PureComponent {
|
||||
onClick={() => this.handleEdit(row)}
|
||||
>
|
||||
<TableCell>{row.number}</TableCell>
|
||||
{cfg.externalNumber ? (
|
||||
<TableCell>
|
||||
{numberDisplay(row.externalNumber)}
|
||||
</TableCell>
|
||||
) : null}
|
||||
<TableCell>{formatDate(row.date)}</TableCell>
|
||||
<TableCell>{this.partyName(row[partyField])}</TableCell>
|
||||
<TableCell
|
||||
|
||||
@@ -44,6 +44,16 @@ export function formatDate(iso) {
|
||||
return d.toLocaleDateString('de-DE');
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivery documents have a server-allocated, read-only `number` plus an
|
||||
* optional user-entered `externalNumber`. Returns the display value for a
|
||||
* field, defaulting to a dash when empty.
|
||||
*/
|
||||
export function numberDisplay(value) {
|
||||
if (value == null || String(value).trim() === '') return '–';
|
||||
return String(value);
|
||||
}
|
||||
|
||||
export function dateInputValue(iso) {
|
||||
if (!iso) return '';
|
||||
const d = new Date(iso);
|
||||
@@ -105,20 +115,35 @@ export function buildLines(lines, { requireAtLeastOne }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ number: string, date: string, partyId: number|null, lines: object[] }} form
|
||||
* @param {{ partyField: 'supplierId'|'entityId', requireAtLeastOne: boolean }} opts
|
||||
* @param {{ number: string, externalNumber?: string, date: string, partyId: number|null, lines: object[] }} form
|
||||
* @param {{ partyField: 'supplierId'|'entityId', requireAtLeastOne: boolean, externalNumber?: boolean }} opts
|
||||
*/
|
||||
export function buildManifestBody(form, { partyField, requireAtLeastOne }) {
|
||||
const number = String(form.number ?? '').trim();
|
||||
export function buildManifestBody(
|
||||
form,
|
||||
{ partyField, requireAtLeastOne, externalNumber: useExternalNumber },
|
||||
) {
|
||||
const date = form.date;
|
||||
if (!number) throw new Error('Nummer fehlt.');
|
||||
if (!date) throw new Error('Datum fehlt.');
|
||||
|
||||
const body = {
|
||||
number,
|
||||
date,
|
||||
lines: buildLines(form.lines, { requireAtLeastOne }),
|
||||
};
|
||||
let body;
|
||||
if (useExternalNumber) {
|
||||
// Delivery: number is server-allocated/read-only. The caller-supplied
|
||||
// reference goes in externalNumber (nullable; empty string → null).
|
||||
const externalNumber = String(form.externalNumber ?? '').trim();
|
||||
body = {
|
||||
externalNumber: externalNumber || null,
|
||||
date,
|
||||
lines: buildLines(form.lines, { requireAtLeastOne }),
|
||||
};
|
||||
} else {
|
||||
const number = String(form.number ?? '').trim();
|
||||
if (!number) throw new Error('Nummer fehlt.');
|
||||
body = {
|
||||
number,
|
||||
date,
|
||||
lines: buildLines(form.lines, { requireAtLeastOne }),
|
||||
};
|
||||
}
|
||||
if (form.partyId != null) body[partyField] = form.partyId;
|
||||
else if (!requireAtLeastOne) body[partyField] = null;
|
||||
return body;
|
||||
@@ -192,6 +217,9 @@ export function manifestConfig(kind) {
|
||||
listPromise: (ctx) => ctx.deliveries ?? ctx.deliveryPromise,
|
||||
partiesByIdFromList: (parties) =>
|
||||
Object.fromEntries(parties.map((row) => [row.id, row])),
|
||||
// Delivery uses a server-allocated read-only number plus an optional
|
||||
// caller-supplied external reference.
|
||||
externalNumber: true,
|
||||
};
|
||||
}
|
||||
if (kind === 'quote') {
|
||||
|
||||
@@ -25,5 +25,17 @@ export function createDefaultTheme() {
|
||||
},
|
||||
},
|
||||
nav,
|
||||
components: {
|
||||
MuiMenu: {
|
||||
defaultProps: {
|
||||
transitionDuration: 0,
|
||||
},
|
||||
},
|
||||
MuiPopover: {
|
||||
defaultProps: {
|
||||
transitionDuration: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user