468 lines
15 KiB
JavaScript
468 lines
15 KiB
JavaScript
/**
|
|
* ifm electronic DELFOR D04A to VDA 4905 Converter
|
|
* Converts EDIFACT DELFOR D04A (ifm electronic format) to VDA 4905
|
|
*
|
|
* Uses:
|
|
* - DelforParser: Parses EDIFACT DELFOR into structured segments
|
|
* - VDA4905Generator: Generates VDA 4905 output
|
|
*
|
|
* Based on ifm_electronic_DELFOR_D04A specification
|
|
*/
|
|
window.EDIBridge = window.EDIBridge || {};
|
|
|
|
class DelforToVDA4905Converter {
|
|
|
|
/**
|
|
* Main conversion function
|
|
* @param {string} delforContent - Raw EDIFACT DELFOR D04A content
|
|
* @returns {string} VDA 4905 formatted output
|
|
*/
|
|
static convert(delforContent) {
|
|
const DelforParser = window.EDIBridge.DelforParser;
|
|
const VDA4905Generator = window.EDIBridge.VDA4905Generator;
|
|
|
|
if (!DelforParser) {
|
|
throw new Error('DelforParser not found. Please include delfor-parser.js');
|
|
}
|
|
if (!VDA4905Generator) {
|
|
throw new Error('VDA4905Generator not found. Please include vda4905-generator.js');
|
|
}
|
|
|
|
// Step 1: Parse DELFOR
|
|
const parsed = DelforParser.parse(delforContent);
|
|
|
|
// Step 2: Transform to VDA4905-compatible structure
|
|
const transformed = this.transformDelforStructure(parsed);
|
|
|
|
// Step 3: Generate VDA 4905
|
|
return VDA4905Generator.generate(transformed);
|
|
}
|
|
|
|
/**
|
|
* Transform DELFOR D04A structure to match VDA4905Generator expectations
|
|
* Handles ifm electronic specific segment mappings
|
|
*/
|
|
static transformDelforStructure(parsed) {
|
|
const segments = parsed.segments;
|
|
const result = { segments: [] };
|
|
|
|
// Helper to get segment value
|
|
const getVal = (seg, elIdx, compIdx) => {
|
|
if (!seg || !seg.elements) return '';
|
|
const el = seg.elements[elIdx];
|
|
if (!el) return '';
|
|
if (Array.isArray(el)) return el[compIdx] || '';
|
|
if (compIdx === 0) return el;
|
|
return '';
|
|
};
|
|
|
|
// Copy all segments but enhance/transform as needed
|
|
for (const seg of segments) {
|
|
const transformed = this.transformSegment(seg, segments);
|
|
if (transformed) {
|
|
result.segments.push(transformed);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Transform individual segment according to ifm electronic DELFOR D04A spec
|
|
*/
|
|
static transformSegment(seg, allSegments) {
|
|
// Most segments pass through unchanged
|
|
// Add specific transformations based on ifm electronic requirements
|
|
|
|
switch (seg.tag) {
|
|
case 'UNH':
|
|
// Message Header - verify DELFOR type
|
|
return this.validateUNH(seg);
|
|
|
|
case 'BGM':
|
|
// Beginning of Message - Document code 241 expected
|
|
return this.transformBGM(seg);
|
|
|
|
case 'DTM':
|
|
// Date/Time/Period - handle various qualifiers
|
|
return this.transformDTM(seg);
|
|
|
|
case 'RFF':
|
|
// Reference - handle ON (Order Number), AAN, etc.
|
|
return this.transformRFF(seg);
|
|
|
|
case 'NAD':
|
|
// Name and Address - BY, SE, etc.
|
|
return this.transformNAD(seg);
|
|
|
|
case 'LIN':
|
|
// Line Item - Article information
|
|
return this.transformLIN(seg);
|
|
|
|
case 'QTY':
|
|
// Quantity - handle 194 (cumulative), 113 (schedule), etc.
|
|
return this.transformQTY(seg);
|
|
|
|
case 'SCC':
|
|
// Scheduling Conditions
|
|
return this.transformSCC(seg);
|
|
|
|
case 'GEI':
|
|
// Processing Information
|
|
return this.transformGEI(seg);
|
|
|
|
case 'LOC':
|
|
// Location - Plant, Unloading Point
|
|
return seg;
|
|
|
|
case 'CTA':
|
|
case 'COM':
|
|
// Contact information - pass through
|
|
return seg;
|
|
|
|
default:
|
|
return seg;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate UNH segment - must be DELFOR:D:04A:UN
|
|
*/
|
|
static validateUNH(seg) {
|
|
const elements = seg.elements || [];
|
|
// UNH+172354030+DELFOR:D:04A:UN
|
|
// elements[0] = message reference number
|
|
// elements[1] = [DELFOR, D, 04A, UN]
|
|
|
|
if (elements[1]) {
|
|
const msgType = Array.isArray(elements[1]) ? elements[1][0] : elements[1];
|
|
if (msgType !== 'DELFOR') {
|
|
console.warn('Warning: Expected DELFOR message type, got:', msgType);
|
|
}
|
|
}
|
|
|
|
return seg;
|
|
}
|
|
|
|
/**
|
|
* Transform BGM segment
|
|
* Expected: BGM+241+177754999+9
|
|
* - 241 = Delivery schedule message
|
|
* - Document identifier
|
|
* - 9 = Original
|
|
*/
|
|
static transformBGM(seg) {
|
|
// Pass through - VDA4905Generator handles this
|
|
return seg;
|
|
}
|
|
|
|
/**
|
|
* Transform DTM segment
|
|
* Handle ifm electronic specific date qualifiers:
|
|
* - 137: Document date
|
|
* - 4: Order date
|
|
* - 171: Reference date/time
|
|
* - 64: Earliest delivery date
|
|
*/
|
|
static transformDTM(seg) {
|
|
const elements = seg.elements || [];
|
|
const qualifier = Array.isArray(elements[0]) ? elements[0][0] : elements[0];
|
|
|
|
// Map ifm electronic qualifiers to VDA4905 expected qualifiers
|
|
const qualifierMap = {
|
|
'137': '137', // Document date -> Document date
|
|
'4': '4', // Order date
|
|
'171': '171', // Reference date
|
|
'64': '64', // Earliest delivery date
|
|
'63': '63', // Latest delivery date
|
|
'2': '2', // Delivery date
|
|
'10': '10', // Shipment date
|
|
'11': '11', // Dispatch date
|
|
'50': '50', // Goods receipt date
|
|
'131': '131', // Tax point date
|
|
'192': '192', // Previous document date
|
|
'242': '242' // Actual date
|
|
};
|
|
|
|
return seg;
|
|
}
|
|
|
|
/**
|
|
* Transform RFF segment
|
|
* Handle ifm electronic references:
|
|
* - ON: Order number (5500002000)
|
|
* - AAN: Delivery schedule number
|
|
* - AIF: Previous release number
|
|
*/
|
|
static transformRFF(seg) {
|
|
const elements = seg.elements || [];
|
|
const qualifier = Array.isArray(elements[0]) ? elements[0][0] : elements[0];
|
|
|
|
// RFF+ON:5500002000 -> Order reference
|
|
// RFF+AAN:55 -> Delivery schedule number
|
|
|
|
return seg;
|
|
}
|
|
|
|
/**
|
|
* Transform NAD segment
|
|
* ifm electronic format:
|
|
* NAD+BY+1100+ifm electronic gmbh+ifm electronic gmbh+ifm-Straße 1:Halle 16+Tettnang+88069+DE
|
|
*/
|
|
static transformNAD(seg) {
|
|
const elements = seg.elements || [];
|
|
const qualifier = Array.isArray(elements[0]) ? elements[0][0] : elements[0];
|
|
|
|
// Ensure proper structure for VDA4905Generator
|
|
// BY = Buyer, SE = Seller, ST = Ship-to
|
|
|
|
return seg;
|
|
}
|
|
|
|
/**
|
|
* Transform LIN segment
|
|
* ifm electronic format:
|
|
* LIN+00010++AK2258921:BP
|
|
* - Line item number
|
|
* - (empty)
|
|
* - Item identifier:BP (Buyer's part number)
|
|
*/
|
|
static transformLIN(seg) {
|
|
const elements = seg.elements || [];
|
|
|
|
// Ensure item identifier is properly extracted
|
|
// elements[2] should contain [ItemNumber, 'BP']
|
|
|
|
return seg;
|
|
}
|
|
|
|
/**
|
|
* Transform QTY segment
|
|
* ifm electronic qualifiers:
|
|
* - 194: Cumulative quantity received
|
|
* - 113: Quantity to be delivered (schedule)
|
|
* - 1: Discrete quantity
|
|
* - 12: Despatch quantity
|
|
* - 21: Ordered quantity
|
|
* - 48: Received quantity
|
|
* - 70: Minimum stock quantity
|
|
*/
|
|
static transformQTY(seg) {
|
|
const elements = seg.elements || [];
|
|
const qualifier = Array.isArray(elements[0]) ? elements[0][0] : elements[0];
|
|
|
|
// Map ifm electronic quantity qualifiers
|
|
const qualifierMap = {
|
|
'194': '194', // Cumulative received
|
|
'113': '113', // Schedule quantity (maps to VDA 4905 schedule)
|
|
'1': '1', // Discrete quantity
|
|
'12': '12', // Despatch quantity
|
|
'21': '21', // Ordered quantity
|
|
'48': '48', // Received quantity
|
|
'70': '70' // Minimum stock
|
|
};
|
|
|
|
return seg;
|
|
}
|
|
|
|
/**
|
|
* Transform SCC segment
|
|
* Scheduling Conditions:
|
|
* SCC+1 = Firm schedule
|
|
* SCC+4 = Planning schedule
|
|
*/
|
|
static transformSCC(seg) {
|
|
return seg;
|
|
}
|
|
|
|
/**
|
|
* Transform GEI segment
|
|
* Processing Information:
|
|
* GEI+3++35 = Process type
|
|
*/
|
|
static transformGEI(seg) {
|
|
return seg;
|
|
}
|
|
|
|
/**
|
|
* Extract schedule data from DELFOR for VDA 4905 records 513/514
|
|
* Groups QTY segments with their associated DTM dates
|
|
*/
|
|
static extractSchedules(segments) {
|
|
const schedules = [];
|
|
let currentLin = null;
|
|
|
|
const getVal = (seg, elIdx, compIdx) => {
|
|
if (!seg || !seg.elements) return '';
|
|
const el = seg.elements[elIdx];
|
|
if (!el) return '';
|
|
if (Array.isArray(el)) return el[compIdx] || '';
|
|
if (compIdx === 0) return el;
|
|
return '';
|
|
};
|
|
|
|
for (let i = 0; i < segments.length; i++) {
|
|
const seg = segments[i];
|
|
|
|
if (seg.tag === 'LIN') {
|
|
currentLin = {
|
|
itemNumber: getVal(seg, 2, 0),
|
|
schedules: []
|
|
};
|
|
}
|
|
|
|
if (seg.tag === 'QTY' && currentLin) {
|
|
const qualifier = getVal(seg, 0, 0);
|
|
const quantity = getVal(seg, 0, 1);
|
|
const unit = getVal(seg, 0, 2);
|
|
|
|
// Look for associated DTM
|
|
let deliveryDate = '';
|
|
for (let j = i + 1; j < segments.length; j++) {
|
|
const next = segments[j];
|
|
if (next.tag === 'QTY' || next.tag === 'LIN' || next.tag === 'UNT') break;
|
|
if (next.tag === 'DTM') {
|
|
const dtmQual = getVal(next, 0, 0);
|
|
if (['64', '2', '10', '11', '171'].includes(dtmQual)) {
|
|
deliveryDate = getVal(next, 0, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Only include schedule quantities (113, 1, 12, 21)
|
|
if (['113', '1', '12', '21'].includes(qualifier)) {
|
|
currentLin.schedules.push({
|
|
qualifier,
|
|
quantity,
|
|
unit,
|
|
date: deliveryDate
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return schedules;
|
|
}
|
|
|
|
/**
|
|
* Validate DELFOR content before conversion
|
|
*/
|
|
static validate(delforContent) {
|
|
const errors = [];
|
|
const warnings = [];
|
|
|
|
// Check for required segments
|
|
const requiredSegments = ['UNH', 'BGM', 'DTM', 'NAD', 'LIN', 'QTY', 'UNT'];
|
|
|
|
for (const tag of requiredSegments) {
|
|
if (!delforContent.includes(tag + '+') && !delforContent.includes(tag + "'")) {
|
|
errors.push(`Missing required segment: ${tag}`);
|
|
}
|
|
}
|
|
|
|
// Check for DELFOR message type
|
|
if (!delforContent.includes('DELFOR')) {
|
|
errors.push('Not a DELFOR message');
|
|
}
|
|
|
|
// Check for D04A version (optional warning)
|
|
if (!delforContent.includes('D:04A') && !delforContent.includes(':D:04A:')) {
|
|
warnings.push('Expected DELFOR D04A version');
|
|
}
|
|
|
|
return {
|
|
valid: errors.length === 0,
|
|
errors,
|
|
warnings
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Convert with validation
|
|
*/
|
|
static convertWithValidation(delforContent) {
|
|
const validation = this.validate(delforContent);
|
|
|
|
if (!validation.valid) {
|
|
return {
|
|
success: false,
|
|
errors: validation.errors,
|
|
warnings: validation.warnings,
|
|
output: null
|
|
};
|
|
}
|
|
|
|
try {
|
|
const output = this.convert(delforContent);
|
|
return {
|
|
success: true,
|
|
errors: [],
|
|
warnings: validation.warnings,
|
|
output
|
|
};
|
|
} catch (e) {
|
|
return {
|
|
success: false,
|
|
errors: [e.message],
|
|
warnings: validation.warnings,
|
|
output: null
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse DELFOR and return structured data for inspection
|
|
*/
|
|
static parseOnly(delforContent) {
|
|
const DelforParser = window.EDIBridge.DelforParser;
|
|
if (!DelforParser) {
|
|
throw new Error('DelforParser not found');
|
|
}
|
|
return DelforParser.parse(delforContent);
|
|
}
|
|
|
|
/**
|
|
* Get mapping info for debugging
|
|
*/
|
|
static getMappingInfo() {
|
|
return {
|
|
name: 'DELFOR D04A to VDA 4905',
|
|
source: 'EDIFACT DELFOR D04A (ifm electronic)',
|
|
target: 'VDA 4905',
|
|
version: '1.0.0',
|
|
segments: {
|
|
'UNH': 'Message Header -> VDA 511 (Header)',
|
|
'BGM': 'Beginning of Message -> VDA 511',
|
|
'DTM': 'Date/Time -> VDA 511, 512, 513',
|
|
'RFF': 'Reference -> VDA 511, 512',
|
|
'NAD': 'Name and Address -> VDA 511 (Customer/Supplier)',
|
|
'LIN': 'Line Item -> VDA 512 (Article)',
|
|
'QTY': 'Quantity -> VDA 513/514 (Schedules)',
|
|
'SCC': 'Scheduling Conditions -> VDA 513/514',
|
|
'UNT': 'Message Trailer -> VDA 519'
|
|
},
|
|
quantityQualifiers: {
|
|
'194': 'Cumulative received -> VDA 513 (Cumulative)',
|
|
'113': 'Schedule quantity -> VDA 513/514 (Schedule lines)',
|
|
'1': 'Discrete quantity -> VDA 513/514',
|
|
'12': 'Despatch quantity -> VDA 513',
|
|
'48': 'Received quantity -> VDA 513',
|
|
'70': 'Minimum stock -> VDA 513 (EFZ)'
|
|
},
|
|
dateQualifiers: {
|
|
'137': 'Document date -> VDA 511',
|
|
'171': 'Reference date -> VDA 513',
|
|
'64': 'Earliest delivery -> VDA 513/514',
|
|
'192': 'Previous document date -> VDA 512'
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
// Register in EDIBridge namespace
|
|
window.EDIBridge.DelforToVDA4905Converter = DelforToVDA4905Converter;
|
|
|
|
// Convenience alias
|
|
window.EDIBridge.convertDelforToVDA4905 = (content) => DelforToVDA4905Converter.convert(content);
|