UNPKG

@makakwastaken/ts-edifact

Version:
414 lines (382 loc) 19.5 kB
"use strict"; /* eslint-disable @typescript-eslint/no-non-null-assertion */ /** * @author Stefan Partheymüller * @copyright 2021 Stefan Partheymüller * @license Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-call */ const node_fs_1 = require("node:fs"); const node_path_1 = require("node:path"); const legacyMessageStructureParser_1 = require("../src/edi/legacyMessageStructureParser"); const messageStructureParser_1 = require("../src/edi/messageStructureParser"); const util_1 = require("../src/util"); const D99A_INVOIC_METADATA_PAGE = ` <HTML><PRE><body bgcolor=ffffff><TITLE>UNTDID - D.99A - Message INVOIC</title> <! --- This document was created by Viorel Iordache - UN/ECE -----> UN/EDIFACT UNITED NATIONS STANDARD MESSAGE (UNSM) <B>Invoice message</B> Message Type : <B>INVOIC</B> Version : D Release : 99A Contr. Agency: UN Revision : 10 Date : 99-01-14 SOURCE: Joint Rapporteurs Message Design Group JM2 <B>CONTENTS</B> 0. <A HREF="invoic_d.htm#INTRODUCTION">INTRODUCTION</A> 1. <A HREF="invoic_d.htm#SCOPE">SCOPE</A> 1.1 <A HREF="invoic_d.htm#FUNDEF">Functional definition</A> 1.2 <A HREF="invoic_d.htm#FOA">Field of application</A> 1.3 <A HREF="invoic_d.htm#PRINCIP">Principles</A> 2. <A HREF="invoic_d.htm#REF">REFERENCES</A> 3. <A HREF="invoic_d.htm#TAD">TERMS AND DEFINITIONS</A> 3.1 <A HREF="invoic_d.htm#TAD1">Standard terms and definitions</A> 4. <A HREF="invoic_d.htm#MESDEF">MESSAGE DEFINITION</A> 4.1 <A HREF="invoic_d.htm#DSC">Data segment clarification</A> 4.1.1 <A HREF="invoic_d.htm#HS">Header section</A> 4.1.2 <A HREF="invoic_d.htm#DS">Detail section</A> 4.1.3 <A HREF="invoic_d.htm#SS">Summary section</A> 4.2 <A HREF="invoic_d.htm#DSGI">Data segment index</A>(alphabetical sequence) 4.3 <A HREF="invoic_s.htm">Message structure</A> 4.3.1 <A HREF="invoic_s.htm">Segment table</A> <A HREF="stand_1.htm">Standard text</A> <hr> </html> `; const D99A_INVOIC_STRUCTURE_PAGE = (0, node_fs_1.readFileSync)((0, node_path_1.join)(__dirname, 'data', 'd99a_invoic_s.html'), 'utf-8'); const D99A_APERAK_STRUCTURE_PAGE = (0, node_fs_1.readFileSync)((0, node_path_1.join)(__dirname, 'data', 'd99a_aperak_s.html'), 'utf-8'); const D96A_ORDERS_STRUCTURE_PAGE = (0, node_fs_1.readFileSync)((0, node_path_1.join)(__dirname, 'data', 'd96a_orders_s.html'), 'utf-8'); describe('UNECELegacyMessageStructureParser', () => { let sut; const expectedBGMEntry = { content: 'BGM', mandatory: true, repetition: 1, data: undefined, section: 'header', }; const expectedSegmentGroup27Entry = { name: 'Segment group 27', content: [ { content: 'MOA', mandatory: true, repetition: 1, data: undefined, section: undefined, }, { content: 'CUX', mandatory: false, repetition: 1, data: undefined, section: undefined, }, ], mandatory: false, repetition: 99, data: undefined, section: undefined, }; const expectedUNSEntry = { content: 'UNS', mandatory: true, repetition: 1, data: undefined, section: 'summary', }; beforeAll(() => { sut = new legacyMessageStructureParser_1.UNECELegacyMessageStructureParser('D99A', 'INVOIC'); }); describe('parseMetaDataPage', () => { it('should extract meta data correctly from D99A INVOIC meta data page', () => { const expectedSpec = new messageStructureParser_1.EdifactMessageSpecificationImpl('INVOIC', 'D', '99A', 'UN'); const spec = sut.parseMetaDataPage(D99A_INVOIC_METADATA_PAGE); expect(spec).toEqual(expectedSpec); }); }); describe('parseStructurePage', () => { it('should extract message structure correctly from D99A INVOIC structure page', () => { const expectedSegmentNames = [ 'BGM', 'DTM', 'PAI', 'ALI', 'IMD', 'FTX', 'LOC', 'GIS', 'DGS', 'RFF', 'GIR', 'MEA', 'QTY', 'MOA', 'NAD', 'FII', 'DOC', 'CTA', 'COM', 'TAX', 'CUX', 'PAT', 'PCD', 'TDT', 'TSR', 'TOD', 'EQD', 'SEL', 'PAC', 'PCI', 'GIN', 'ALC', 'RNG', 'RTE', 'RCS', 'AJT', 'INP', 'LIN', 'PIA', 'QVR', 'PRI', 'APR', 'CNT', ]; const spec = new messageStructureParser_1.EdifactMessageSpecificationImpl('INVOIC', 'D', '99A', 'UN'); const segmentNames = sut.parseStructurePage(D99A_INVOIC_STRUCTURE_PAGE, spec); expect(segmentNames).toEqual(expectedSegmentNames); expect(spec.messageStructureDefinition).toContainEqual(expectedBGMEntry); expect(spec.messageStructureDefinition).toContainEqual(expectedUNSEntry); const sg26 = spec.messageStructureDefinition.find((item) => item.name === 'Segment group 26'); expect(sg26).toBeDefined(); expect(sg26.content).toContainEqual(expectedSegmentGroup27Entry); }); it('should correctly parse D99A APERAK structure page (no header section)', () => { const expectedSegmentNames = [ 'BGM', 'DTM', 'FTX', 'CNT', 'DOC', 'RFF', 'NAD', 'CTA', 'COM', 'ERC', ]; const expectedBGMEntry_APERAK = { ...expectedBGMEntry, section: undefined, }; const expectedSegmentGroup5Entry = { name: 'Segment group 5', content: [ { content: 'RFF', mandatory: true, repetition: 1, data: undefined, section: undefined, }, { content: 'FTX', mandatory: false, repetition: 9, data: undefined, section: undefined, }, ], mandatory: false, repetition: 9, data: undefined, section: undefined, }; const spec = new messageStructureParser_1.EdifactMessageSpecificationImpl('APERAK', 'D', '99A', 'UN'); const segmentNames = sut.parseStructurePage(D99A_APERAK_STRUCTURE_PAGE, spec); expect(segmentNames).toEqual(expectedSegmentNames); expect(spec.messageStructureDefinition).toContainEqual(expectedBGMEntry_APERAK); const sg4 = spec.messageStructureDefinition.find((item) => item.name === 'Segment group 4'); expect(sg4).toBeDefined(); expect(sg4.content).toContainEqual(expectedSegmentGroup5Entry); }); it('should correctly parse D96A ORDERS structure page', () => { const spec = new messageStructureParser_1.EdifactMessageSpecificationImpl('ORDERS', 'D', '96A', 'UN'); sut.parseStructurePage(D96A_ORDERS_STRUCTURE_PAGE, spec); expect(spec.messageStructureDefinition).toContainEqual({ ...expectedBGMEntry, section: 'header', }); expect(spec.messageStructureDefinition).toContainEqual(expectedUNSEntry); expect(spec.messageStructureDefinition[7]).toBeDefined(); expect(spec.messageStructureDefinition[7].name).toBe('Segment group 1'); expect(spec.messageStructureDefinition[8]).toBeDefined(); expect(spec.messageStructureDefinition[8].name).toBe('Segment group 25'); const sg25 = spec.messageStructureDefinition.find((item) => item.name === 'Segment group 25'); expect(sg25).toBeDefined(); }); }); describe('parseSegmentDefinitionPage', () => { it('should parse segment definition page', (done) => { const page = ` <HTML><title>UNTDID - D.99A - Segment MEA</title> <! --- This document was created by Viorel Iordache - UN/ECE on 4/2/99 -----> <pre><body bgcolor=ffffff> <A HREF="trsd.htm">Change indicators</A> <HR> <A HREF="csegmea.htm">MEA</A> <B>MEASUREMENTS</B> Function: To specify physical measurements, including dimension tolerances, weights and counts. 010 <A HREF="../uncl/uncl6311.htm">6311</A> MEASUREMENT PURPOSE QUALIFIER M an..3 020 <A HREF="../trcd/trcdc502.htm">C502</A> MEASUREMENT DETAILS C <A HREF="../uncl/uncl6313.htm">6313</A> Property measured, coded C an..3 <A HREF="../uncl/uncl6321.htm">6321</A> Measurement significance, coded C an..3 <A HREF="../uncl/uncl6155.htm">6155</A> Measurement attribute identification C an..17 <A HREF="../uncl/uncl6154.htm">6154</A> Measurement attribute C an..70 030 <A HREF="../trcd/trcdc174.htm">C174</A> VALUE/RANGE C <A HREF="../uncl/uncl6411.htm">6411</A> Measure unit qualifier M an..3 <A HREF="../uncl/uncl6314.htm">6314</A> Measurement value C an..18 <A HREF="../uncl/uncl6162.htm">6162</A> Range minimum C n..18 <A HREF="../uncl/uncl6152.htm">6152</A> Range maximum C n..18 <A HREF="../uncl/uncl6432.htm">6432</A> Significant digits C n..2 040 <A HREF="../uncl/uncl7383.htm">7383</A> SURFACE/LAYER INDICATOR, CODED C an..3 <HR>`; const spec = new messageStructureParser_1.EdifactMessageSpecificationImpl('INVOIC', 'D', '99A', 'UN'); sut.parseSegmentDefinitionPage('MEA', page, spec).then(() => { const segments = spec.segmentTable; expect(segments.get('MEA')?.elements.map((element) => element.id)).toEqual(expect.arrayContaining(['6311', 'C502', 'C174', '7383'])); expect(segments.get('MEA')?.requires).toEqual(1); expect((0, util_1.findElement)(segments.get('MEA')?.elements, '6311')?.components).toEqual(expect.arrayContaining([ { id: '6311', format: 'an..3', name: 'measurementPurposeQualifier', }, ])); expect((0, util_1.findElement)(segments.get('MEA')?.elements, '6311')?.requires).toEqual(1); expect((0, util_1.findElement)(segments.get('MEA')?.elements, 'C174')?.components?.map((c) => c.format)).toEqual(expect.arrayContaining(['an..3', 'an..18', 'n..18', 'n..18', 'n..2'])); expect((0, util_1.findElement)(segments.get('MEA')?.elements, 'C174')?.requires).toEqual(1); // sub-components should not be stored expect((0, util_1.findElement)(segments.get('MEA')?.elements, '6411')).toBeUndefined(); done(); }); }); it('should add multiple element definitions only once', (done) => { const page = ` <HTML><title>UNTDID - D.99A - Segment CUX</title> <! --- This document was created by Viorel Iordache - UN/ECE on 4/2/99 -----> <pre><body bgcolor=ffffff> <A HREF="trsd.htm">Change indicators</A> <HR> <A HREF="csegcux.htm">CUX</A> <B>CURRENCIES</B> Function: To specify currencies used in the transaction and relevant details for the rate of exchange. 010 <A HREF="../trcd/trcdc504.htm">C504</A> CURRENCY DETAILS C <A HREF="../uncl/uncl6347.htm">6347</A> Currency details qualifier M an..3 <A HREF="../uncl/uncl6345.htm">6345</A> Currency, coded C an..3 <A HREF="../uncl/uncl6343.htm">6343</A> Currency qualifier C an..3 <A HREF="../uncl/uncl6348.htm">6348</A> Currency rate base C n..4 020 <A HREF="../trcd/trcdc504.htm">C504</A> CURRENCY DETAILS C <A HREF="../uncl/uncl6347.htm">6347</A> Currency details qualifier M an..3 <A HREF="../uncl/uncl6345.htm">6345</A> Currency, coded C an..3 <A HREF="../uncl/uncl6343.htm">6343</A> Currency qualifier C an..3 <A HREF="../uncl/uncl6348.htm">6348</A> Currency rate base C n..4 030 <A HREF="../uncl/uncl5402.htm">5402</A> RATE OF EXCHANGE C n..12 040 <A HREF="../uncl/uncl6341.htm">6341</A> CURRENCY MARKET EXCHANGE, CODED C an..3 <HR>`; const spec = new messageStructureParser_1.EdifactMessageSpecificationImpl('INVOIC', 'D', '99A', 'UN'); sut.parseSegmentDefinitionPage('CUX', page, spec).then(() => { const segments = spec.segmentTable; expect(segments.get('CUX')?.elements.map((e) => e.id)).toEqual(expect.arrayContaining(['C504', 'C504', '5402', '6341'])); expect(segments.get('CUX')?.requires).toEqual(0); expect((0, util_1.findElement)(segments.get('CUX')?.elements, 'C504')?.components.length).toEqual(4); expect((0, util_1.findElement)(segments.get('CUX')?.elements, 'C504')?.components).toEqual(expect.arrayContaining([ { id: '6347', format: 'an..3', name: 'currencyDetailsQualifier', }, { id: '6345', format: 'an..3', name: 'currencyCoded', }, { id: '6343', format: 'an..3', name: 'currencyQualifier', }, { id: '6348', format: 'n..4', name: 'currencyRateBase', }, ])); done(); }); }); }); describe('loadTypeSpec', () => { it('should parse remote UNECE specification', async () => { const spec = await sut.loadTypeSpec(); const segments = spec.segmentTable; // check meta-data expect(spec.controllingAgency).toBe('UN'); expect(spec.version).toBe('D'); expect(spec.release).toBe('99A'); expect(spec.messageType).toBe('INVOIC'); // check segments expect(segments.get('MEA')?.elements.map((e) => e.id)).toEqual(expect.arrayContaining(['6311', 'C502', 'C174', '7383'])); expect(segments.get('MEA')?.requires).toEqual(1); expect(segments.get('CUX')?.elements.map((e) => e.id)).toEqual(expect.arrayContaining(['C504', 'C504', '5402', '6341'])); expect(segments.get('CUX')?.requires).toEqual(0); // check elements // elements for segment MEA expect((0, util_1.findElement)(segments.get('MEA')?.elements, '6311')?.components).toEqual(expect.arrayContaining([ { id: '6311', name: 'measurementPurposeQualifier', format: 'an..3' }, ])); expect((0, util_1.findElement)(segments.get('MEA')?.elements, '6311')?.requires).toEqual(1); expect((0, util_1.findElement)(segments.get('MEA')?.elements, 'C174')?.components).toEqual(expect.arrayContaining([ { id: '6411', format: 'an..3', name: 'measureUnitQualifier' }, { id: '6314', format: 'an..18', name: 'measurementValue' }, { id: '6162', format: 'n..18', name: 'rangeMinimum' }, { id: '6152', format: 'n..18', name: 'rangeMaximum' }, { id: '6432', format: 'n..2', name: 'significantDigits' }, ])); expect((0, util_1.findElement)(segments.get('MEA')?.elements, 'C174')?.requires).toEqual(1); // elements for segment CUX expect((0, util_1.findElement)(segments.get('CUX')?.elements, 'C504')?.components.length).toEqual(4); expect((0, util_1.findElement)(segments.get('CUX')?.elements, 'C504')?.components).toEqual(expect.arrayContaining([ { id: '6347', format: 'an..3', name: 'currencyDetailsQualifier' }, { id: '6345', format: 'an..3', name: 'currencyCoded' }, { id: '6343', format: 'an..3', name: 'currencyQualifier' }, { id: '6348', format: 'n..4', name: 'currencyRateBase' }, ])); // sub-components should not be stored expect((0, util_1.findElement)(segments.get('MEA')?.elements, '6411')).toBeUndefined(); // check message structure expect(spec.messageStructureDefinition).toContainEqual(expectedBGMEntry); expect(spec.messageStructureDefinition).toContainEqual(expectedUNSEntry); const sg26 = spec.messageStructureDefinition.find((item) => item.name === 'Segment group 26'); expect(sg26).toBeDefined(); expect(sg26.content).toContainEqual(expectedSegmentGroup27Entry); }); }); }); //# sourceMappingURL=legacyMessageStructureParser.spec.js.map