Monteur-Dropdown + VenDoc-Spaltennamen im CSV-Export angepasst
Monteur ist jetzt ein Dropdown (Michael/Daniel/Dietmar/Fidelis) mit freiem Textfeld für "Andere". CSV-Export nutzt jetzt VenDocs eigene Spaltennamen (Position/EH/Positionstext/Aufmaß), ermittelt aus einem echten VenDoc- Aufmaßblatt-Export des Nutzers; Art.-Nr. wird wie dort im Positionstext eingebettet, da VenDoc keine eigene Artikelnummer-Spalte führt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
8a4ce769a0
commit
18a3a636dd
@@ -4,6 +4,7 @@ import { api } from '../lib/api';
|
||||
import type { MaterialItem, Projekt } from '../lib/types';
|
||||
import { kabelInfoForBez } from '../data/kabelData';
|
||||
import KabelOptions from '../components/KabelOptions';
|
||||
import MonteurField from '../components/MonteurField';
|
||||
|
||||
const fmt1 = (v: number | string) => (Math.round((parseFloat(String(v)) || 0) * 10) / 10).toFixed(1);
|
||||
const num1 = (v: number | string) => Math.round((parseFloat(String(v)) || 0) * 10) / 10;
|
||||
@@ -216,25 +217,26 @@ export default function ProjektDetail() {
|
||||
setRetourBusy(false);
|
||||
}
|
||||
|
||||
// ── CSV-Export (für Import in VenDoc o.ä. als Auftragspositionen) ──
|
||||
// ── CSV-Export (für Import in VenDoc als Auftragspositionen) ──
|
||||
// Semikolon-getrennt, Komma als Dezimaltrenner, UTF-8 mit BOM – Standardkonvention
|
||||
// für deutschsprachiges Excel/ERP, damit die Datei ohne Umweg direkt geöffnet/
|
||||
// importiert werden kann. Reine Positionstabelle ohne Kopf-Metazeilen, damit ein
|
||||
// einfacher Positions-Import (z. B. VenDoc Universalimport) sie unverändert lesen kann.
|
||||
// für deutschsprachiges Excel/ERP. Spaltennamen (Position/EH/Positionstext/Aufmaß)
|
||||
// richten sich nach VenDocs eigenem Aufmaßblatt-Export (Auftrag A00079/2026), das
|
||||
// keine eigene Artikelnummer-Spalte führt – die Art.-Nr. wird daher wie dort in den
|
||||
// Positionstext eingebettet. Ob das exakte Spaltenformat vom Universalimport 1:1
|
||||
// übernommen wird, ist ungeprüft – ggf. anhand des ersten Testimports nachschärfen.
|
||||
const EH_MAP: Record<string, string> = { Stk: 'ST', m: 'M' }; // aus VenDoc-Beispiel bestätigt
|
||||
function csvEscape(v: string): string {
|
||||
if (/[;"\n\r]/.test(v)) return '"' + v.replace(/"/g, '""') + '"';
|
||||
return v;
|
||||
}
|
||||
function exportCSV() {
|
||||
if (!projekt) return;
|
||||
const header = ['Pos', 'Artikelnummer', 'Bezeichnung', 'Menge', 'Einheit', 'Notiz'];
|
||||
const header = ['Position', 'EH', 'Positionstext', 'Aufmaß'];
|
||||
const rows = matList.map((r, i) => [
|
||||
String(i + 1),
|
||||
r.artNr ?? '',
|
||||
r.bezeichnung,
|
||||
fmt1(r.menge).replace('.', ','),
|
||||
r.einheit,
|
||||
r.notiz ?? ''
|
||||
EH_MAP[r.einheit] ?? r.einheit,
|
||||
r.artNr ? `${r.bezeichnung} (${r.artNr})` : r.bezeichnung,
|
||||
fmt1(r.menge).replace('.', ',')
|
||||
]);
|
||||
const csv = [header, ...rows].map(row => row.map(csvEscape).join(';')).join('\r\n');
|
||||
const safeName = (titel || 'Materialschein').replace(/[^\p{L}\p{N}_-]+/gu, '_');
|
||||
@@ -305,9 +307,7 @@ export default function ProjektDetail() {
|
||||
<label className="field">Datum
|
||||
<input type="date" value={datum} onChange={e => setDatum(e.target.value)} onBlur={e => saveFeld('datum', e.target.value)} />
|
||||
</label>
|
||||
<label className="field">Monteur
|
||||
<input value={monteur} onChange={e => setMonteur(e.target.value)} onBlur={e => saveFeld('monteur', e.target.value)} />
|
||||
</label>
|
||||
<MonteurField key={id} value={monteur} onChange={setMonteur} onCommit={v => saveFeld('monteur', v)} />
|
||||
<label className="field" style={{ gridColumn: 'span 2' }}>Notiz / Bereich
|
||||
<textarea value={notiz} onChange={e => setNotiz(e.target.value)} onBlur={e => saveFeld('notiz', e.target.value)} />
|
||||
</label>
|
||||
|
||||
Reference in New Issue
Block a user