/** * 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);