indice-co / EDI.Net

EDI Serializer/Deserializer. Supports EDIFact, X12 and TRADACOMS formats

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to use SegmentGroup

FRConceicao opened this issue · comments

Hi everyone,

I´m trying to implement the EDIFACT VERMAS D16B, and I´m having a hard time understanding/using SegmentGroup.

image

I´ve created classes for Elements and Segments, for example my CTA Segment is defined as

    [EdiSegment, EdiPath("CTA")]
    public class CTA
    {
        [EdiValue("X(3)", Path = "CTA/0")]
        public string ContactFunctionCoded { get; set; }

        [EdiElement, EdiPath("CTA/1")]
        public C056 ContactDetails { get; set; }
    }

and the C506 Element

    [EdiElement]
    public class C056
    {
        [EdiValue("X(17)", Path = "*/*/0")]
        public string ContactIdentifier { get; set; }

        [EdiValue("X(256)", Path = "*/*/1")]
        public string ContactName { get; set; }
    }

My question is what would be the best/correct way to implement the GRP2 class?

  • NAD is mandatory, so should I use EdiSegment(Mandatory=true)? Wouldn´t that force GRP3 List to be mandatory also?
  • How should I define the SegmentGroup? EdiSegmentGroup("NAD", "GRP3") or EdiSegmentGroup("NAD", "CTA", "COM")
  • Should I decorate public List<GRP3> GRP3{ get; set; } with any attribute? For example [EdiSegment]
    [EdiSegment(Mandatory=true), EdiSegmentGroup("NAD", ""GRP3")]
    public class GRP2: NAD
    {
        public List<GRP3> GRP3{ get; set; }

        public GRP2()
        {
            GRP3= new List<GRP3>();
        }
    }

Thank you for your help!

Hi @FRConceicao and thanks for you interest in EDI.Net

I will try to answer your questions in bullets.

  • The Mandatory flag is available in all structure attributes as well as values but at the time of this writing is informational & not used by the library to validate any data either when reading or writing. That said it does not make any difference.
  • "GP3" is a made up name not present in the transmission so will not help the serializer in order to know which segments take part in the group. You will definitely need to use EdiSegmentGroup("NAD", "CTA", "COM"). One side note: when developing your segment groups usually one progresses from the outermost group to the inner ones . So in order for your group not to break you need to define all child segments regardless their nesting level. In the end when you will have all your child groups defined you can simplify the parents declaration attributes by having only the starting segment names of inner groups or singular segments. I hope this makes sense but I will throw an example below.
  • The "clean" Segment (NAD) class normally has the EdiSegment attribute while the segment group subclass GRP2 needs only the SegmentGroup attribute. The property in your case does not need any annotations since the classes are already sufficiently annotated. Also no need to EdiPath segment groups

example nesting:

  • GRP1: RFF. DTM
  • GRP2: NAD. GRP3
    • GRP3: CTA. COM
  • GRP4: EQD, RFF, LOC, SEL, GRP5, GRP6, GRP7

example mapping groups 1,2,3 only.

[EdiSegment, EdiPath("RFF")]
public class RFF { /* ... */ }

[EdiSegment, EdiPath("DTM")]
public class DTM { /* ... */ }

[EdiSegment, EdiPath("NAD")]
public class NAD { /* ... */ }

[EdiSegment, EdiPath("CTA")]
public class CTA { /* ... */ }

[EdiSegment, EdiPath("COM")]
public class COM { /* ... */ }

[EdiSegmentGroup("RFF", "DTM")]
public class GRP1 : RFF { /* ... */ }

// here COM is not needed explicitly because I already mapped the GRP3 and the serializer will know. 
// In the begining though until I create the GRP3 class the GRP2 group can break without it. 
[EdiSegmentGroup("NAD", "CTA")] 
public class GRP2 : NAD { /* ... */ }

[EdiSegmentGroup("CTA", "COM")] 
public class GRP3 : CTA { /* ... */ }

Hi @cleftheris ,

Thank you for your explanation and a big THANK YOU for your last update, especially on the segment count.

With the below definition:

  • GRP1: RFF DTM
  • GRP2: NAD. GRP3
    • GRP3: CTA COM
  • GRP4: EQD, RFF, LOC, SEL, GRP5, GRP6, GRP7

If I understand correctly, and for example sake, if I have GRP0 defined as GRP0 : RFF GRP1 GRP2 GRP4 , the class attribute should be:
[EdiSegmentGroup("RFF", "RFF (GRP1 1st Segment)", "NAD (GRP2 1st Segment)", "EQD (GRP4 1st Segment)")]


On a side note.
I work on Logistics/container control, and I´m using your wonderful work as an hobby to (try) create some EDIFACT tools for my personal usage. A while back you and I talked about the possibility to create a side project for EDI dictionaries.
For now my class definitions have some specific definitions for my usage, but if you are up to it, I could try to make them generic.
As you probably noticed, I´m not a specialist, so if you agree, I will send you my code to see if you agree with the structure / definitions

Once again a big thank you

Hi @FRConceicao,

first of all thank you for your kind words. The example you gave is correct, given you have all the other groups defined. If you miss one you have to put its segments in there.


On your side note: I love the idea of someone making something out of EDI.Net. I would suggest building yourself a new repo and taking a dependency to EDI.Net. There are still plenty of stuff I have not yet tackled inside the library and the idea of having the scope broaden is a bit overwhelming. Some examples might be

  1. Extracting a wiki/documentation by going through all answers to issues that are previously answered
  2. introducing the EDIFact (an1..10) value specification and making that a default.
  3. Solving the X12 ISA segment issue where the grammar is scattered out inside the first line in contrast to EDIFact where there is a definitive service string advice.
  4. Make use of the new dotnet apis for stream processing and lowering allocations. There are some tests that check for performance in very large transmissings over 100MB but I have not found the time to deepdive.
  5. Custom Value converters to and from string.

One more thing that may not be obvious is that we have little to do with the industry where EDI is still thriving in. We just sat one day with a client of ours that needed an EDI component for importing invoices. I was amazed by the fact that there where just few or no options at all in dotnet. This makes sometimes maintenance difficult since in order for the lib to advance there is no internal drive/need and all issues must come from the outside world. Contributions also are sparce and even when they come it is difficult to review if they are not small and targeted.

If you still want to share your code here then you should open a new issue where we can discuss scope and guidelines but it will be a slow process.