Erster Commit
This commit is contained in:
246
js/vda-parser.js
Normal file
246
js/vda-parser.js
Normal file
@@ -0,0 +1,246 @@
|
||||
/**
|
||||
* VDA 4913 Parser - Field positions verified against real data
|
||||
*/
|
||||
window.EDIBridge = window.EDIBridge || {};
|
||||
|
||||
class VDAParser {
|
||||
static parse(content) {
|
||||
const lines = content.split(/\r?\n/).filter(l => l.length >= 3);
|
||||
const result = { interchanges: [] };
|
||||
let curI = null, curT = null, curDN = null;
|
||||
|
||||
for (const line of lines) {
|
||||
const rt = line.substring(0, 3);
|
||||
switch (rt) {
|
||||
// VDA 4905 (DELFOR)
|
||||
case '511':
|
||||
curI = { header: this.parse511(line), articles: [], transports: [] };
|
||||
result.interchanges.push(curI);
|
||||
break;
|
||||
case '512':
|
||||
if (!curI) break;
|
||||
// In 4905, articles are children of the interchange
|
||||
curT = { article: this.parse512(line), schedules: [], deliveries: [] };
|
||||
curI.articles.push(curT);
|
||||
break;
|
||||
case '513':
|
||||
if (!curT || !curT.article) break; // Ensure we are in an article context
|
||||
const s513 = this.parse513(line);
|
||||
curT.schedules.push(...s513.schedules);
|
||||
if (s513.lastDn && s513.lastDn !== '00000000' && s513.lastDn.trim() !== '') {
|
||||
curT.deliveries.push({
|
||||
docNo: s513.lastDn,
|
||||
date: s513.lastDate,
|
||||
qty: s513.lastQty,
|
||||
unit: curT.article.unit || 'ST'
|
||||
});
|
||||
}
|
||||
curT.efz = s513.efz;
|
||||
curT.nullStellung = s513.nullStellung || '';
|
||||
break;
|
||||
case '514':
|
||||
if (!curT || !curT.article) break;
|
||||
curT.schedules.push(...this.parse514(line));
|
||||
break;
|
||||
case '519':
|
||||
if (curI) curI.trailer = this.parse519(line);
|
||||
break;
|
||||
|
||||
// VDA 4913 (DESADV)
|
||||
case '711':
|
||||
curI = { header: this.parse711(line), transports: [], articles: [] };
|
||||
result.interchanges.push(curI);
|
||||
break;
|
||||
case '712':
|
||||
if (!curI) break;
|
||||
curT = { data: this.parse712(line), deliveryNotes: [] };
|
||||
curI.transports.push(curT);
|
||||
break;
|
||||
case '713':
|
||||
if (!curT) break;
|
||||
curDN = { header: this.parse713(line), positions: [], texts: [] };
|
||||
curT.deliveryNotes.push(curDN);
|
||||
break;
|
||||
case '714':
|
||||
if (!curDN) break;
|
||||
curDN.positions.push({ data: this.parse714(line), packaging: [] });
|
||||
break;
|
||||
case '715':
|
||||
if (!curDN) break;
|
||||
const lastP = curDN.positions[curDN.positions.length - 1];
|
||||
if (lastP) lastP.packaging.push(this.parse715(line));
|
||||
break;
|
||||
case '716':
|
||||
if (curDN) {
|
||||
curDN.texts.push(line.substring(5).trim());
|
||||
const revLvl = line.substring(5, 7).trim();
|
||||
if (revLvl && curDN.positions.length > 0) {
|
||||
const lastPos = curDN.positions[curDN.positions.length - 1];
|
||||
if (!lastPos.data.revisionLevel) lastPos.data.revisionLevel = revLvl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '719':
|
||||
if (curI) curI.trailer = this.parse719(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static getCustomerId(content) {
|
||||
if (!content) return null;
|
||||
const lines = content.split(/\r?\n/).filter(l => l.length >= 3);
|
||||
for (const line of lines) {
|
||||
const rt = line.substring(0, 3);
|
||||
if (rt === '711' || rt === '511') {
|
||||
return line.substring(5, 14).trim();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// --- VDA 4905 Parsers ---
|
||||
static parse511(l) {
|
||||
return {
|
||||
version: l.substring(3, 5).trim(),
|
||||
customerId: l.substring(5, 14).trim(),
|
||||
supplierId: l.substring(14, 23).trim(),
|
||||
oldTransNo: l.substring(23, 28).trim(),
|
||||
newTransNo: l.substring(28, 33).trim(),
|
||||
date: l.substring(33, 39).trim()
|
||||
};
|
||||
}
|
||||
|
||||
static parse512(l) {
|
||||
return {
|
||||
plant: l.substring(5, 8).trim(),
|
||||
docNum: l.substring(8, 17).trim(),
|
||||
docDate: l.substring(17, 23).trim(),
|
||||
custMat: l.substring(38, 60).trim(),
|
||||
suppMat: l.substring(60, 82).trim(),
|
||||
orderNo: l.substring(82, 94).trim(),
|
||||
unloadingPoint: l.substring(94, 99).trim(),
|
||||
unit: l.substring(103, 105).trim() || 'ST'
|
||||
};
|
||||
}
|
||||
|
||||
static parse513(l) {
|
||||
const weDate = l.substring(5, 11).trim();
|
||||
const lastDn = l.substring(11, 19).trim();
|
||||
const lastDate = l.substring(19, 25).trim();
|
||||
// VDA 4905: Letzte Liefermenge hat 3 implizite Dezimalstellen → /1000
|
||||
const lastQty = (parseInt(l.substring(25, 37), 10) || 0) / 1000;
|
||||
// VDA 4905: EFZ hat ebenfalls 3 implizite Dezimalstellen → /1000
|
||||
const efz = (parseInt(l.substring(37, 47), 10) || 0) / 1000;
|
||||
|
||||
const schedules = [];
|
||||
let offset = 47;
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const dateRaw = l.substring(offset, offset + 6);
|
||||
const qtyStr = l.substring(offset + 6, offset + 15).trim();
|
||||
if (dateRaw.trim() && dateRaw.trim() !== '000000') {
|
||||
// VDA 4905: Abrufmengen haben 3 implizite Dezimalstellen → /1000
|
||||
schedules.push({ date: dateRaw, qty: (parseInt(qtyStr, 10) || 0) / 1000 });
|
||||
}
|
||||
offset += 15;
|
||||
}
|
||||
// Null-Stellung (6 Zeichen JJMMTT) steht nach den 5 Abrufzeilen
|
||||
const nullStellungRaw = l.substring(offset, offset + 6).trim();
|
||||
const nullStellung = (nullStellungRaw && nullStellungRaw !== '000000') ? nullStellungRaw : '';
|
||||
return { weDate, lastDn, lastDate, lastQty, efz, nullStellung, schedules };
|
||||
}
|
||||
|
||||
static parse514(l) {
|
||||
const schedules = [];
|
||||
let offset = 5;
|
||||
for (let i = 0; i < 8; i++) {
|
||||
const dateRaw = l.substring(offset, offset + 6);
|
||||
const qtyStr = l.substring(offset + 6, offset + 15).trim();
|
||||
if (dateRaw.trim() && dateRaw.trim() !== '000000') {
|
||||
// VDA 4905: Abrufmengen haben 3 implizite Dezimalstellen → /1000
|
||||
schedules.push({ date: dateRaw, qty: (parseInt(qtyStr, 10) || 0) / 1000 });
|
||||
}
|
||||
offset += 15;
|
||||
}
|
||||
return schedules;
|
||||
}
|
||||
|
||||
static parse519(l) {
|
||||
return {
|
||||
count511: parseInt(l.substring(5, 12), 10) || 0,
|
||||
count512: parseInt(l.substring(12, 19), 10) || 0,
|
||||
count513: parseInt(l.substring(19, 26), 10) || 0,
|
||||
count514: parseInt(l.substring(26, 33), 10) || 0
|
||||
};
|
||||
}
|
||||
|
||||
// --- VDA 4913 Parsers ---
|
||||
|
||||
static parse711(l) {
|
||||
return {
|
||||
version: l.substring(3, 5).trim(),
|
||||
targetId: l.substring(5, 14).trim(),
|
||||
sourceId: l.substring(14, 23).trim(),
|
||||
transNo1: l.substring(23, 28).trim(),
|
||||
transNo2: l.substring(28, 33).trim(),
|
||||
date: l.substring(33, 39).trim(),
|
||||
altId: l.substring(39, 48).trim()
|
||||
};
|
||||
}
|
||||
|
||||
static parse712(l) {
|
||||
return {
|
||||
refNo: l.substring(5, 13).trim(),
|
||||
carrierName: l.substring(16, 30).trim(),
|
||||
date: l.substring(30, 36).trim(),
|
||||
time: l.substring(36, 40).trim(),
|
||||
grossWeight: parseInt(l.substring(40, 47)) || 0,
|
||||
netWeight: parseInt(l.substring(47, 54)) || 0,
|
||||
};
|
||||
}
|
||||
|
||||
static parse713(l) {
|
||||
return {
|
||||
dnNo: l.substring(5, 13).trim(),
|
||||
date: l.substring(13, 19).trim(),
|
||||
unloadingPoint: l.substring(19, 24).trim(),
|
||||
qualifier: l.substring(24, 30).trim(),
|
||||
orderNo: l.substring(30, 38).trim(),
|
||||
};
|
||||
}
|
||||
|
||||
static parse714(l) {
|
||||
// Qty: [53-65] with 3 implied decimals (VDA Standard) → /1000
|
||||
const qtyRaw = parseInt(l.substring(52, 65)) || 0;
|
||||
const qty = qtyRaw / 1000;
|
||||
return {
|
||||
custMat: l.substring(5, 27).trim(),
|
||||
suppMat: l.substring(27, 49).trim(),
|
||||
qty: qty,
|
||||
unit: l.substring(65, 67).trim(),
|
||||
refNo: l.substring(77, 90).trim(),
|
||||
// VDA 4913 standard uses different fields for batch/refs, keeping compatibility
|
||||
batchNo: l.substring(90, 105).trim() || l.substring(113, 127).trim(),
|
||||
};
|
||||
}
|
||||
|
||||
static parse715(l) {
|
||||
const count = parseInt(l.substring(59, 62)) || 1;
|
||||
const labelFrom = l.substring(78, 87).trim();
|
||||
const labelTo = l.substring(87, 96).trim();
|
||||
return {
|
||||
packMatCust: l.substring(5, 27).trim(),
|
||||
packMatSupp: l.substring(27, 49).trim(),
|
||||
qty: count,
|
||||
labelFrom: labelFrom,
|
||||
labelTo: labelTo,
|
||||
};
|
||||
}
|
||||
|
||||
static parse719(l) {
|
||||
return { lineCount: parseInt(l.substring(5, 12)) || 0 };
|
||||
}
|
||||
}
|
||||
|
||||
window.EDIBridge.VDAParser = VDAParser;
|
||||
Reference in New Issue
Block a user