132 lines
4.0 KiB
JavaScript
132 lines
4.0 KiB
JavaScript
/**
|
|
* EDIFACT Parser for DELFOR D04A
|
|
* Parses raw EDI string into structured JSON
|
|
*/
|
|
window.EDIBridge = window.EDIBridge || {};
|
|
|
|
class DelforParser {
|
|
static parse(content) {
|
|
// Defaults
|
|
let separator = '+';
|
|
let subSeparator = ':';
|
|
let decimal = '.';
|
|
let release = '?';
|
|
let terminator = "'";
|
|
|
|
// Clean raw content
|
|
let raw = content.replace(/\r\n/g, '').replace(/\n/g, '').trim();
|
|
|
|
// 1. Detect UNA
|
|
if (raw.startsWith('UNA')) {
|
|
subSeparator = raw[3];
|
|
separator = raw[4];
|
|
decimal = raw[5];
|
|
release = raw[6];
|
|
terminator = raw[8];
|
|
raw = raw.substring(9);
|
|
}
|
|
|
|
// 2. Split Segments (Simple approach usually sufficient for well-formed EDI)
|
|
// Advanced approach: Character-by-character to handle release chars
|
|
const segments = [];
|
|
let currentSeg = '';
|
|
let escaped = false;
|
|
|
|
for (let i = 0; i < raw.length; i++) {
|
|
const char = raw[i];
|
|
|
|
if (escaped) {
|
|
currentSeg += char;
|
|
escaped = false;
|
|
} else if (char === release) {
|
|
escaped = true;
|
|
} else if (char === terminator) {
|
|
if (currentSeg.trim().length > 0) {
|
|
segments.push(this.parseSegment(currentSeg, separator, subSeparator, release));
|
|
}
|
|
currentSeg = '';
|
|
} else {
|
|
currentSeg += char;
|
|
}
|
|
}
|
|
|
|
// Add final segment if no terminator at end
|
|
if (currentSeg.trim().length > 0) {
|
|
segments.push(this.parseSegment(currentSeg, separator, subSeparator, release));
|
|
}
|
|
|
|
return {
|
|
meta: { separator, subSeparator, release, terminator },
|
|
segments: segments
|
|
};
|
|
}
|
|
|
|
static parseSegment(segStr, sep, subSep, release) {
|
|
// Tokenize by separator
|
|
const tokenized = this.tokenize(segStr, sep, release);
|
|
const tag = tokenized.shift(); // First token is always Tag (e.g. UNH)
|
|
|
|
const elements = tokenized.map(token => {
|
|
// Check for sub-separator
|
|
if (token.includes(subSep)) {
|
|
// Determine if subSep is escaped?
|
|
// tokenize logic handles simple split.
|
|
// We should tokenize the token by subSep
|
|
const components = this.tokenize(token, subSep, release);
|
|
return components;
|
|
}
|
|
return token;
|
|
});
|
|
|
|
return { tag, elements };
|
|
}
|
|
|
|
// Helper: Split string by delimiter, respecting release char
|
|
static tokenize(str, delim, release) {
|
|
const tokens = [];
|
|
let currentToken = '';
|
|
let escaped = false;
|
|
|
|
for (let i = 0; i < str.length; i++) {
|
|
const char = str[i];
|
|
if (escaped) {
|
|
currentToken += char;
|
|
escaped = false;
|
|
} else if (char === release) {
|
|
escaped = true;
|
|
} else if (char === delim) {
|
|
tokens.push(currentToken);
|
|
currentToken = '';
|
|
} else {
|
|
currentToken += char;
|
|
}
|
|
}
|
|
tokens.push(currentToken);
|
|
return tokens;
|
|
}
|
|
|
|
/**
|
|
* Extracts a unique Customer/Sender ID for auto-detection
|
|
*/
|
|
static getCustomerId(content) {
|
|
if (!content) return null;
|
|
// Search for UNB sender
|
|
const unbMatch = content.match(/UNB\s*[\+\:]([^\+']+)[\+\:]([^\+']+)/i);
|
|
if (unbMatch) {
|
|
let sender = unbMatch[2];
|
|
if (sender.includes(':')) sender = sender.split(':')[0];
|
|
const clean = sender.trim();
|
|
if (clean && !clean.startsWith('000000')) return clean;
|
|
}
|
|
|
|
// Fallback to NAD+BY
|
|
const nadMatch = content.match(/NAD\+BY\+([^\+':]+)/i);
|
|
if (nadMatch) {
|
|
return nadMatch[1].trim();
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
window.EDIBridge.DelforParser = DelforParser;
|