indice-co / EDI.Net

EDI Serializer/Deserializer. Supports EDIFact, X12 and TRADACOMS formats
MIT License
452 stars 169 forks source link

Question on loops #143

Open marcino239 opened 4 years ago

marcino239 commented 4 years ago

I have 873 which looks roughly like this:

ISA
GS
ST
   BGN
   DTM
   N1
   DTM
     SLN
         QTY
     SLN
         QTY
   DTM
     SLN
         QTY
     SLN
         QTY
SE
GE
IEA

I was trying to structure the Data Map by doing the following

            public DTM DateTimeReference { get; set; }
            public List<N1> PartyIdentification { get; set; }
            public List<Detail> Details { get; set; }

Where Detail:

        [EdiSegmentGroup("DTM")]
        public class Detail
        {
            public DTM DateTimeReference { get; set; }
            public List<Subline> Sublines { get; set; }
        }

        [EdiSegment, EdiPath("DTM")]
        public class DTM
        {
            [EdiValue("X(3)", Path = "DTM/0", Description = "Date/Time Qualifier")]
            public string DateTimeQualifier { get; set; }

            [EdiValue("X(3)", Path = "DTM/1", Description = "Date/Time/Period Qualifier")]
            public string DateTimePeriodQualifier { get; set; }
            ....

However DTM segments are not getting populated. I like the implementation however tracking through the internal state machine is really hard and I would be grateful for pointers.

Thanks vm!

cleftheris commented 4 years ago

Basically the whenever you see a SegmentGroup you should have two rules in mind.

  1. Your group should always subclass of the starting segment class. That said you need your Detail to subclass DTM. Same goes for your SLN+QTY group
  2. Your other concern is regarding group item termination. How does the group item terminate and when the loop (list) ends.
    • If your loop has a unique staring element not occuring anywhere else in the transmission & at the same time there is a clear escape element following the end of the loop or your loop is at the end of the message wrapping segments (ST,SE), then you could simply use the single argument attribute like you did with an optional SequenceEnd when needed [EdiSegmentGroup("DTM")]
    • In 90% of the cases you are better off defining all same level elements enclosed. for example [EdiSegmentGroup("DTM", "SLN")] for the DTM group and [EdiSegmentGroup("SLN", "QTY")] for the subline group.

Hope this helped.

marcino239 commented 4 years ago

Great - thank you sir! I'll check and report tomorrow.

marcino239 commented 4 years ago

I think I'm a little bit lost. I've tried subclassing of a whole segment and also just a single element, but still get nulls on Data.DateTimeReference and Details show 2 groups. Should I add some conditional fields based how this is done in EDIFact_D01B_IFCSUM.cs ?

        [EdiMessage]
        public class Headers
        {
            [EdiValue("X(3)", Path = "ST/0", Description = "ST01 - Transaction set ID code")]
            public string TransactionSetCode { get; set; }

            [EdiValue("X(9)", Path = "ST/1", Description = "ST02 - Transaction set control number")]
            public string TransactionSetControlNumber { get; set; }
            //Optional
            [EdiValue("X(35)", Path = "ST/2", Description = "ST03 - Transaction set control number")]
            public string ImplementationConventionReference { get; set; }

            [EdiValue(Path = "SE/0", Description = "SE01 - Number of included segments")]
            public int SegmentCounts { get; set; }

            [EdiValue("X(9)", Path = "SE/1", Description = "SE02 - Transaction set control number (same as ST02)")]
            public string TrailerTransactionSetControlNumber { get; set; }

            public Data Data { get; set; }
        }

        [EdiSegmentGroup("BGN", "DTM", "N1")]
        public class Data
        {
            [EdiValue("X(2)", Path = "BGN/0", Description = "Transaction Set Purpose Code")]
            public string TransactionSetPurposeCode { get; set; }

            [EdiValue("X(50)", Path = "BGN/1", Description = "Reference Identification")]
            public string ReferenceIdentification { get; set; }

            [EdiValue("9(8)", Path = "BGN/2", Format = "yyyyMMdd", Description = "Date")]
            public DateTime Date { get; set; }

            [EdiValue("9(8)", Path = "BGN/3", Format = "HHmm", Description = "Time")]
            public TimeSpan Time { get; set; }

            [EdiValue("X(2)", Path = "BGN/4", Description = "Time Code")]
            public string TimeCode { get; set; }

            [EdiValue("X(50)", Path = "BGN/5", Description = "Reference Identification")]
            public string ReferenceIdentification1 { get; set; }

            [EdiValue("X(2)", Path = "BGN/6", Description = "Transaction Type Code")]
            public string TransactionTypeCode { get; set; }

            [EdiValue("X(2)", Path = "BGN/7", Description = "Action Code")]
            public string ActionCode { get; set; }

            [EdiValue("X(2)", Path = "BGN/8", Description = "Security Level Code")]
            public string SecurityLevelCode { get; set; }

            public DTM DateTimeReference { get; set; }
            public List<N1> PartyIdentification { get; set; }
            public List<Detail> Details { get; set; }

        }

        [EdiSegmentGroup("DTM", "CS", "SLN", "N1")]
        public class Detail
        {
            [EdiValue("X(3)", Path = "DTM/0", Description = "Date/Time Qualifier")]
            public string DateTimeQualifier { get; set; }

            [EdiValue("X(3)", Path = "DTM/1", Description = "Date/Time/Period Qualifier")]
            public string DateTimePeriodQualifier { get; set; }

            [EdiValue("9(8)", Path = "DTM/2", Description = "Date")]
            public DateTime Date { get; set; }

            [EdiValue("X(35)", Path = "DTM/3", Description = "Date/Time/Period")]
            public string DateTimePeriod { get; set; }

            [EdiValue("9(8)", Path = "DTM/4", Description = "Time")]
            public TimeSpan Time { get; set; }

            [EdiValue("X(3)", Path = "DTM/5", Description = "Date/Time/Period Format Qualifier")]
            public string DateTimePeriodFormatQualifier { get; set; }

            [EdiValue("X(2)", Path = "DTM/6", Description = "Time Code")]
            public string TimeCode { get; set; }

            [EdiValue("X(3)", Path = "DTM/7", Description = "Date Time Period Format Qualifier")]
            public string DateTimePeriodFormatQualifier1 { get; set; }

            [EdiValue("X(35)", Path = "DTM/8", Description = "Date Time Period")]
            public string DateTimePeriod1 { get; set; }

            public CS CS { get; set; }
            public SLN SLN { get; set; }
            public List<LQ> LQ { get; set; }

            public N9 N9 { get; set; }
            public N1 N1 { get; set; }
            public LCD LCD { get; set; }
        }

        [EdiSegment, EdiPath("DTM")]
        public class DTM
        {
            [EdiValue("X(3)", Path = "DTM/0", Description = "Date/Time Qualifier")]
            public string DateTimeQualifier { get; set; }

            [EdiValue("X(3)", Path = "DTM/1", Description = "Date/Time/Period Qualifier")]
            public string DateTimePeriodQualifier { get; set; }
            ...

Example Data:

ISA*00* *00* *01*999999999 *12*6309246701*060926*1242*U*00401*000000030*0*T*>~
GS*SC*999999999*6309246701T*20060926*1242*1*X*004010~
ST*873*013326301~
BGN*00*01332631518619252*20180808****G1~
DTM*102****DT*081808081518~
N1*SJ**1*046077343~
N1*78**1*808703524~
DTM*007****RD8*20180809-20180831~
CS*FT18380***NMT*P~
SLN*3579923**I~
LQ*QT*R~
LQ*TT*01~
N9*PKG*3~
N1*US**1*248799413~
LCD**M2***SV*33975~
SE*22*013326301~
GE*1*1~
IEA*1*000000030~