diff --git a/package-lock.json b/package-lock.json
index c822103..f3bc8ef 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,8 +18,7 @@
"@shopify/draggable": "^1.2.1",
"dashgui": "file:../dashgui",
"notistack": "^3.0.2",
- "pdfjs-dist": "^6.3.289",
- "pdftotext-wasm": "file:../pdftotext-wasm",
+ "pdfconvert-wasm": "^0.3.0",
"react": "^19.3.0",
"react-automat": "^0.1.0",
"react-dom": "^19.3.0",
@@ -57,13 +56,6 @@
"react-dom": "^19.0.0"
}
},
- "../pdftotext-wasm": {
- "version": "0.1.0",
- "license": "GPLv3",
- "bin": {
- "pdftotext-wasm": "bin.js"
- }
- },
"node_modules/@apideck/better-ajv-errors": {
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.7.tgz",
@@ -2080,271 +2072,6 @@
}
}
},
- "node_modules/@napi-rs/canvas": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-1.0.9.tgz",
- "integrity": "sha512-QviPdJImDi/jMAvBfqaw+19BndMd/sizXVW3NnpMd3VJGz++QXkOHcP9kWR/smHG0hNjHeyuHFyrx/5lD0oNcQ==",
- "license": "MIT",
- "optional": true,
- "workspaces": [
- "e2e/*"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- },
- "optionalDependencies": {
- "@napi-rs/canvas-android-arm64": "1.0.9",
- "@napi-rs/canvas-darwin-arm64": "1.0.9",
- "@napi-rs/canvas-darwin-x64": "1.0.9",
- "@napi-rs/canvas-linux-arm-gnueabihf": "1.0.9",
- "@napi-rs/canvas-linux-arm64-gnu": "1.0.9",
- "@napi-rs/canvas-linux-arm64-musl": "1.0.9",
- "@napi-rs/canvas-linux-riscv64-gnu": "1.0.9",
- "@napi-rs/canvas-linux-x64-gnu": "1.0.9",
- "@napi-rs/canvas-linux-x64-musl": "1.0.9",
- "@napi-rs/canvas-win32-arm64-msvc": "1.0.9",
- "@napi-rs/canvas-win32-x64-msvc": "1.0.9"
- }
- },
- "node_modules/@napi-rs/canvas-android-arm64": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-1.0.9.tgz",
- "integrity": "sha512-4LGXk2/0HVzE29K8SzML5WubgCp++B1FH3qgl35XmSZE+lLdr6P9VRQEnZ0MCLZMTSuJP41yyhtoiVNEuvrTIA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-darwin-arm64": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-1.0.9.tgz",
- "integrity": "sha512-YNdfLBzY0W/Pep9fo2L6RmoNlNksnn05LRnX66W63R3ij58S25QOTcjdtEt2v8+PnCESzqZsYzUo+QPeIR44NA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-darwin-x64": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-1.0.9.tgz",
- "integrity": "sha512-ceZQSknTEcy3dOXoekv59LTCkXjvnLsq+VW5PeNNDHEPQbRS5Ervkm1EaDa7WLAjiYWMLuSQTRTHao1dEX4prg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-1.0.9.tgz",
- "integrity": "sha512-XhfI0Wwv4llhd6nnWDtY3kQKjq0r+y1i91PlJlJI24ag2U9WrnwbG1qS3+fDLEyouwEVFchiKkTEHozK+5iUNA==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-arm64-gnu": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-1.0.9.tgz",
- "integrity": "sha512-012oiYtKaE7i9oxc8q7nraT7kDOpLcaCmFLzVe9Ty34RHDdoDzbWLrVh827CNxYh/EADX1eSikA3ymLjo/nNuw==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-arm64-musl": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-1.0.9.tgz",
- "integrity": "sha512-Ls5UWYFFn63casTZEczbeyEg3vRDRkv9lscuGwfchtY5yLLQhgOB8SN4YGxmfJ5vTaBwZ2YUxBS3NtmjJmFXdA==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-riscv64-gnu": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-1.0.9.tgz",
- "integrity": "sha512-hLKEGxV7ZiRHqndePTokgDMdBlo/rDfzg7P4p4QIv9pUhuYobnu3R2NIFLCRghG0nwfo+s2sw+c1xZFeCmEAsw==",
- "cpu": [
- "riscv64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-x64-gnu": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-1.0.9.tgz",
- "integrity": "sha512-6kaz3w0QMy77PDWk6rJ1ksIihdad3qzEyX2o2oGT8GwCaypfT5mhjr8buOO5hstyLxcWXDScuz56RsINLtBPIQ==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-linux-x64-musl": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-1.0.9.tgz",
- "integrity": "sha512-xrGvmS3v55hmZ86ls/kBLVNMUTYio3f6Ik0DireemG994VfPAwiA3ZXA0Uf1bByctkB3NQ1Sfb+H5bkdUnnzfQ==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-win32-arm64-msvc": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-1.0.9.tgz",
- "integrity": "sha512-yjmVS3ArZeRVCP7jqbPq4rpZa/BhTeI7ELE2XqJg3snICQBDevLZyArxswHkiTnT34KRic33/4fLirrHI+SY8A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
- "node_modules/@napi-rs/canvas-win32-x64-msvc": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-1.0.9.tgz",
- "integrity": "sha512-QlSYQdMQslB81nlABo9wNfQ6npFhE7/O+saCZdqVGueGanyRk4jCogD5EwQenfP3kIq9e+mm6GreQBjX5MrA8g==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
"node_modules/@napi-rs/lzma-linux-x64-gnu": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz",
@@ -5980,21 +5707,11 @@
"node": ">=8"
}
},
- "node_modules/pdfjs-dist": {
- "version": "6.3.289",
- "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-6.3.289.tgz",
- "integrity": "sha512-ZHjSVpDa3D6izMq8/04lvkhkATUmL9px6ChPaXc1k6nU2Mrhlg1/7F0bdUqCwUjw3NsPTfPZsMDUU6ZIcRaeQw==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=22.13.0 || >=24"
- },
- "optionalDependencies": {
- "@napi-rs/canvas": "^1.0.0"
- }
- },
- "node_modules/pdftotext-wasm": {
- "resolved": "../pdftotext-wasm",
- "link": true
+ "node_modules/pdfconvert-wasm": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/pdfconvert-wasm/-/pdfconvert-wasm-0.3.0.tgz",
+ "integrity": "sha512-FbEk+Grg0UST4kOPuN7OFfVsut1FvDOJNPS3pt4rzCS8VlFsFzD7ptg7YtFZjEOKgJ4MgqlfCgjK4RYaRBpT0Q==",
+ "license": "GPLv3"
},
"node_modules/picocolors": {
"version": "1.1.1",
diff --git a/package.json b/package.json
index 7560ed4..e0cda11 100644
--- a/package.json
+++ b/package.json
@@ -24,8 +24,7 @@
"@shopify/draggable": "^1.2.1",
"dashgui": "file:../dashgui",
"notistack": "^3.0.2",
- "pdfjs-dist": "^6.3.289",
- "pdftotext-wasm": "file:../pdftotext-wasm",
+ "pdfconvert-wasm": "^0.3.0",
"react": "^19.3.0",
"react-automat": "^0.1.0",
"react-dom": "^19.3.0",
diff --git a/src/automats/deliveryEditorAutomat.js b/src/automats/deliveryEditorAutomat.js
index 8fe4bb0..514ccb2 100644
--- a/src/automats/deliveryEditorAutomat.js
+++ b/src/automats/deliveryEditorAutomat.js
@@ -70,8 +70,10 @@ export const initialDelivery = {
supplierArticlesLoading: false,
loadingLineKeys: {},
supplierArticlesError: null,
+ unmatchedSupplierName: null,
};
+
export const initialState = {
deliveryEntities: [],
...initialDelivery,
@@ -137,6 +139,7 @@ export function createDeliveryEditorAutomat(options = {}) {
automat.setState({
deliveryEntity: entityId,
partyId: entityId,
+ unmatchedSupplierName: entityId != null ? null : automat.state.unmatchedSupplierName,
...(idChanged
? {
supplierArticles: [],
@@ -152,6 +155,11 @@ export function createDeliveryEditorAutomat(options = {}) {
}
},
+ setUnmatchedSupplierName(name) {
+ automat.setState({ unmatchedSupplierName: name ?? null });
+ },
+
+
setPartyId(partyId) {
automat.actions.setDeliveryEntity(partyId);
},
@@ -464,6 +472,7 @@ export const {
setAttachments,
updateAttachment,
removeAttachment,
+ setUnmatchedSupplierName,
resetDelivery,
resetDeliveryEditor,
} = deliveryEditorAutomat.actions;
@@ -473,7 +482,9 @@ export const selectDeliveryId = (state = deliveryEditorAutomat.state) => state.d
export const selectDeliveryEntities = (state = deliveryEditorAutomat.state) => state.deliveryEntities;
export const selectDeliveryDate = (state = deliveryEditorAutomat.state) => state.date;
export const selectDeliveryEntity = (state = deliveryEditorAutomat.state) => state.deliveryEntity ?? state.partyId;
+export const selectUnmatchedSupplierName = (state = deliveryEditorAutomat.state) => state.unmatchedSupplierName;
export const selectDeliveryExternalNumber = (state = deliveryEditorAutomat.state) => state.externalNumber ?? state.external_number;
+
export const selectDeliveryNumber = (state = deliveryEditorAutomat.state) => state.number;
export const selectDeliveryType = (state = deliveryEditorAutomat.state) => state.type;
export const selectDeliveryLineitems = (state = deliveryEditorAutomat.state) => state.lines ?? state.lineitems;
diff --git a/src/components/manifest/ManifestPdfDialog.jsx b/src/components/manifest/ManifestPdfDialog.jsx
index 6100e22..7a7630e 100644
--- a/src/components/manifest/ManifestPdfDialog.jsx
+++ b/src/components/manifest/ManifestPdfDialog.jsx
@@ -92,9 +92,18 @@ function EventLog({ messages, streaming }) {
);
}
-export default function ManifestPdfDialog({ open, filename, data, onClose, onAbort }) {
+export default function ManifestPdfDialog({
+ open,
+ filename,
+ data,
+ unmatchedSupplierName,
+ onCreateSupplier,
+ onClose,
+ onAbort,
+}) {
if (!open) return null;
+
const { streaming = false, messages = [], result = null, error = null, aborted = false } = data ?? {};
const hasResult = Boolean(result);
@@ -177,6 +186,28 @@ export default function ManifestPdfDialog({ open, filename, data, onClose, onAbo
Daten erfolgreich in das Formular übernommen.
)}
+
+ {/* Unmatched supplier alert */}
+ {hasResult && !streaming && !error && !aborted && unmatchedSupplierName && (
+ onCreateSupplier(unmatchedSupplierName)}
+ >
+ Lieferant anlegen
+
+ ) : null
+ }
+ >
+ Lieferant „{unmatchedSupplierName}“ wurde im Dokument erkannt, existiert aber noch nicht in den Stammdaten.
+
+ )}
@@ -191,11 +222,28 @@ export default function ManifestPdfDialog({ open, filename, data, onClose, onAbo
Abbrechen
) : (
-
+ <>
+ {unmatchedSupplierName && onCreateSupplier ? (
+
+ ) : null}
+
+ >
)}
+
);
}
diff --git a/src/components/withNavigate.jsx b/src/components/withNavigate.jsx
index 4b0354b..595d87f 100644
--- a/src/components/withNavigate.jsx
+++ b/src/components/withNavigate.jsx
@@ -1,9 +1,11 @@
-import { useNavigate } from 'react-router-dom';
+import { useLocation, useNavigate } from 'react-router-dom';
export default function withNavigate(Wrapped) {
function NavigateWrapper(props) {
const navigate = useNavigate();
- return ;
+ const location = useLocation();
+ return ;
}
return NavigateWrapper;
}
+
diff --git a/src/pages/lieferung/lieferanten.jsx b/src/pages/lieferung/lieferanten.jsx
index 362b0a2..8fa4b8f 100644
--- a/src/pages/lieferung/lieferanten.jsx
+++ b/src/pages/lieferung/lieferanten.jsx
@@ -1,5 +1,7 @@
import { PureComponent } from 'react';
+import Alert from '@mui/material/Alert';
import Box from '@mui/material/Box';
+
import Button from '@mui/material/Button';
import CircularProgress from '@mui/material/CircularProgress';
import IconButton from '@mui/material/IconButton';
@@ -13,11 +15,14 @@ import { enqueueSnackbar } from 'notistack';
import BackendError from '../../components/BackendError';
import SingleLineTextEdit from 'dashgui/SingleLineTextEdit';
import { PanelTile, PanelTileGrid } from 'dashgui/panels';
+import withNavigate from '../../components/withNavigate';
import { StorageManagerContext } from '../../api/storageManagerContext';
import { requireDefined, requireObject } from '../../utils/apiShape';
import { backendErrorFrom } from '../../utils/backendError';
import { notifyError } from '../../utils/notify';
import { setLastDeliveryPath } from '../../automats';
+import { deliveryDraftAutomat } from '../../automats/deliveryEditorAutomat';
+
function sortSuppliers(suppliers) {
return [...suppliers].sort((a, b) =>
@@ -29,17 +34,34 @@ function draftsFrom(suppliers) {
return Object.fromEntries(suppliers.map((row) => [row.id, row.name]));
}
+function getInitialParams(props) {
+ const searchParams = typeof window !== 'undefined' ? new URLSearchParams(window.location.search) : null;
+ const prefill =
+ props.location?.state?.name ??
+ props.location?.state?.newName ??
+ searchParams?.get('name') ??
+ searchParams?.get('newName') ??
+ deliveryDraftAutomat.state.unmatchedSupplierName ??
+ '';
+ const returnTo =
+ props.location?.state?.returnTo ??
+ searchParams?.get('returnTo') ??
+ null;
+ return { prefill: prefill.trim(), returnTo };
+}
+
class LieferungLieferantenPage extends PureComponent {
static contextType = StorageManagerContext;
constructor(props) {
super(props);
+ const { prefill } = getInitialParams(props);
this.state = {
status: 'loading',
error: null,
suppliers: [],
drafts: {},
- newName: '',
+ newName: prefill,
busyKey: null,
};
this._cancelled = false;
@@ -49,11 +71,27 @@ class LieferungLieferantenPage extends PureComponent {
}
componentDidMount() {
- setLastDeliveryPath(null);
+ const { returnTo, prefill } = getInitialParams(this.props);
+ if (!returnTo) {
+ setLastDeliveryPath(null);
+ }
+ if (prefill && !this.state.newName) {
+ this.setState({ newName: prefill });
+ }
this._cancelled = false;
void this.loadSuppliers();
}
+ componentDidUpdate(prevProps) {
+ if (prevProps.location !== this.props.location) {
+ const { prefill } = getInitialParams(this.props);
+ if (prefill && prefill !== this.state.newName) {
+ this.setState({ newName: prefill });
+ }
+ }
+ }
+
+
componentWillUnmount() {
this._cancelled = true;
}
@@ -94,16 +132,28 @@ class LieferungLieferantenPage extends PureComponent {
const name = this.state.newName.trim();
if (!name || this.state.busyKey != null) return;
+ const { returnTo } = getInitialParams(this.props);
+
this.setState({ busyKey: 'new' });
try {
const data = await this.context.supplier.create({ name });
requireObject(data, 'POST /api/supplier');
requireObject(data.supplier, 'supplier');
requireDefined(data.supplier.id, 'supplier.id');
+ const newSupplier = data.supplier;
+
+ // Assign the new supplier to the active delivery draft & clear unmatched name
+ deliveryDraftAutomat.actions.setDeliveryEntity(newSupplier.id);
+ deliveryDraftAutomat.actions.setUnmatchedSupplierName(null);
+
await this.refreshFromServer();
if (this._cancelled) return;
this.setState({ newName: '', busyKey: null });
- enqueueSnackbar('Lieferant angelegt.', { variant: 'success' });
+ enqueueSnackbar(`Lieferant „${newSupplier.name || name}“ angelegt.`, { variant: 'success' });
+
+ if (returnTo && this.props.navigate) {
+ this.props.navigate(returnTo);
+ }
} catch (err) {
if (this._cancelled) return;
notifyError(err);
@@ -111,6 +161,7 @@ class LieferungLieferantenPage extends PureComponent {
}
}
+
async handleRename(supplier) {
const draft = String(this.state.drafts[supplier.id] ?? '').trim();
if (!draft) {
@@ -165,6 +216,8 @@ class LieferungLieferantenPage extends PureComponent {
const { status, error, suppliers, drafts, newName, busyKey } = this.state;
const busy = busyKey != null;
+ const { returnTo } = getInitialParams(this.props);
+
if (status === 'loading') {
return (
@@ -183,6 +236,26 @@ class LieferungLieferantenPage extends PureComponent {
+ {returnTo ? (
+ this.props.navigate?.(returnTo)}
+ >
+ Zurück zur Lieferung
+
+ }
+ >
+ {newName
+ ? `Lieferantenname „${newName}“ aus Dokument übernommen.`
+ : 'Neuen Lieferanten für die Lieferung anlegen.'}
+
+ ) : null}
+
Lieferanten der ausgewählten Firma.
@@ -271,4 +344,5 @@ class LieferungLieferantenPage extends PureComponent {
}
}
-export default LieferungLieferantenPage;
+export default withNavigate(LieferungLieferantenPage);
+
diff --git a/src/pages/lieferung/neu.jsx b/src/pages/lieferung/neu.jsx
index aac80f2..977fe7c 100644
--- a/src/pages/lieferung/neu.jsx
+++ b/src/pages/lieferung/neu.jsx
@@ -1,7 +1,9 @@
import { PureComponent } from 'react';
import Alert from '@mui/material/Alert';
import Box from '@mui/material/Box';
+import Button from '@mui/material/Button';
import CircularProgress from '@mui/material/CircularProgress';
+
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { enqueueSnackbar } from 'notistack';
@@ -54,11 +56,14 @@ class LieferungNeuPage extends PureComponent {
textEditorAttachment: null,
articleSearchDialogOpen: false,
articleSearchLine: null,
+ unmatchedSupplierName: null,
};
this._cancelled = false;
this.handleRetry = this.handleRetry.bind(this);
this.handlePartyChange = this.handlePartyChange.bind(this);
+ this.handleCreateSupplierFromPdf = this.handleCreateSupplierFromPdf.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);
@@ -209,8 +214,20 @@ class LieferungNeuPage extends PureComponent {
handlePartyChange(partyId) {
this.automat.actions.setDeliveryEntity(partyId);
+ if (partyId != null) {
+ this.setState({ unmatchedSupplierName: null });
+ this.automat.actions.setUnmatchedSupplierName(null);
+ }
}
+ handleCreateSupplierFromPdf(supplierName) {
+ const name = (supplierName ?? this.state.unmatchedSupplierName ?? '').trim();
+ this.handleClosePdfDialog();
+ const target = `/lieferung/lieferanten?name=${encodeURIComponent(name)}&returnTo=/lieferung/neu`;
+ this.props.navigate(target, { state: { name, returnTo: '/lieferung/neu' } });
+ }
+
+
handleDateChange(date) {
this.automat.actions.setDate(date);
}
@@ -424,7 +441,7 @@ class LieferungNeuPage extends PureComponent {
};
this.automat.actions.addAttachment(pdfAttachment);
- // 2. Extract text using pdftotext-wasm to create 2nd file (textfile)
+ // 2. Extract text using pdfconvert-wasm to create 2nd file (textfile)
try {
const text = await extractPdfText(file, { layout: true });
const txtName = file.name.replace(/\.pdf$/i, '') + '.txt';
@@ -441,7 +458,7 @@ class LieferungNeuPage extends PureComponent {
};
this.automat.actions.addAttachment(txtAttachment);
} catch (txtErr) {
- console.error('Fehler beim Extrahieren von Text mit pdftotext-wasm:', txtErr);
+ console.error('Fehler beim Extrahieren von Text mit pdfconvert-wasm:', txtErr);
}
} else {
// Direct text / CSV attachment
@@ -612,9 +629,17 @@ class LieferungNeuPage extends PureComponent {
const docType = result?.type ?? result?.basedata?.manifestType;
const notes = Array.isArray(result?.notes) ? result.notes : [];
+ const parsedSupplierName = (
+ result?.supplierName ??
+ result?.basedata?.lieferantName ??
+ result?.lieferantName ??
+ result?.basedata?.supplierName ??
+ ''
+ ).trim();
+
// If supplierId is null, try matching supplier by name from loaded delivery entities
- if (supplierId == null && result?.basedata?.lieferantName && Array.isArray(this.state.deliveryEntities)) {
- const nameToMatch = result.basedata.lieferantName.trim().toLowerCase();
+ if (supplierId == null && parsedSupplierName && Array.isArray(this.state.deliveryEntities)) {
+ const nameToMatch = parsedSupplierName.toLowerCase();
const matched = this.state.deliveryEntities.find(
(e) =>
e.name &&
@@ -625,6 +650,11 @@ class LieferungNeuPage extends PureComponent {
if (matched) supplierId = matched.id;
}
+ const unmatchedSupplierName = supplierId == null && parsedSupplierName ? parsedSupplierName : null;
+ this.setState({ unmatchedSupplierName });
+ this.automat.actions.setUnmatchedSupplierName(unmatchedSupplierName);
+
+
if (docDate) this.automat.actions.setDate(docDate);
if (supplierId != null) this.automat.actions.setDeliveryEntity(supplierId);
if (extNum != null) {
@@ -1018,16 +1048,50 @@ class LieferungNeuPage extends PureComponent {
/>
{partyId == null && (!lines || lines.length === 0) ? (
-
- {cfg.partyGateMessage}
-
+ {this.state.unmatchedSupplierName ? (
+
+
+ Lieferant „{this.state.unmatchedSupplierName}“ wurde im Dokument erkannt, existiert aber noch nicht in den Stammdaten.
+
+
+
+
+
+ ) : (
+
+ {cfg.partyGateMessage}
+
+ )}
) : (
<>
- {partyId == null && lines && lines.length > 0 && (
+ {partyId == null && (
-
- Bitte wählen Sie oben einen Lieferanten aus, um die erfassten Positionen speichern zu können.
+ this.handleCreateSupplierFromPdf(this.state.unmatchedSupplierName)}
+ >
+ Lieferant anlegen
+
+ ) : null
+ }
+ sx={{ py: 0.5, alignItems: 'center' }}
+ >
+ {this.state.unmatchedSupplierName
+ ? `Lieferant „${this.state.unmatchedSupplierName}“ wurde im Dokument erkannt, existiert aber noch nicht in den Stammdaten.`
+ : 'Bitte wählen Sie oben einen Lieferanten aus, um die erfassten Positionen speichern zu können.'}
)}
@@ -1069,9 +1133,12 @@ class LieferungNeuPage extends PureComponent {
open={pdfDialogOpen}
filename={pdfFileName}
data={pdfDialogData}
+ unmatchedSupplierName={this.state.unmatchedSupplierName}
+ onCreateSupplier={this.handleCreateSupplierFromPdf}
onClose={this.handleClosePdfDialog}
onAbort={this.handleAbortParse}
/>
+
{
+ const reader = new FileReader();
+ reader.onloadend = () => resolve(reader.result);
+ reader.onerror = reject;
+ reader.readAsDataURL(blob);
+ });
}
+