247 lines
8.0 KiB
JavaScript
247 lines
8.0 KiB
JavaScript
/**
|
|
* 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;
|