indice-co / EDI.Net

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

Separating groups with different segments #145

Open skhan-nacmgit opened 4 years ago

skhan-nacmgit commented 4 years ago

TP_REFERENCE I am trying to parse 820. Some of them have ADX before the RMR (According to the TP reference, this ADX loop contains adjustment items which are not netted to an RMR segment in this transaction set) while some of the ADX are part of the RMR (This ADX loop can only contain adjustment for the immediately preceding RMR segment and affects the amount RMR04. If this adjustment amount is not netted to the immediately preceding RMR, use the outer ADX loop (position 080).

SAMPLE ONE

ISA*00*          *00*          *08*TPTESTUS00     *ZZ*TESTCOMP       *191029*1900*:*00501*820101047*0*P*>
GS*RA*TPTESTUS00*TESTCOMP*20191029*1900*820101047*X*005010
ST*820*101053
BPR*I*21298.97*C*CHK************20191029*VEN
TRN*3*4529952
CUR*PR*USD
N1*PR*MART INC.*UL*1238742000008
N1*PE*Test Company, LLC
REF*IA*446963
ENT*1
RMR*IV*26801*PO*4408.75*4650.41*97.9
REF*DP*00040
REF*MR*0033
REF*PO*1016071221
REF*MC*858008293
REF*19*07
REF*ST*0078742031897
DTM*097*20190904
ADX*-143.76*59*CM*26801
REF*6O*022
REF*MC*000000025
RMR*IV*26927*PO*4653.84*4753.92*100.08
REF*DP*00040
REF*MR*0033
REF*PO*3016440142
REF*MC*884600831
REF*19*07
REF*ST*0078742029733
DTM*097*20190910
SE*28*101067
GE*1*820101061
IEA*1*820101061

SAMPLE TWO

ISA*00*          *00*          *08*TPTESTUS00     *ZZ*TESTCOMP       *191029*1900*:*00501*820101047*0*P*>
GS*RA*TPTESTUS00*TESTCOMP*20191029*1900*820101047*X*005010
ST*820*101053
BPR*I*21298.97*C*CHK************20191029*VEN
TRN*3*4529952
CUR*PR*USD
N1*PR*MART INC.*UL*1238742000008
N1*PE*Test Company, LLC
REF*IA*446963
ENT*1
ADX*143.76*59*DB*25248
REF*ST*0078742028651
REF*6O*022
REF*DP*00040
REF*MR*0033
REF*MC*777777777
ADX*236.04*59*DB*25252
REF*ST*0078742033815
REF*6O*022
REF*DP*00040
REF*MR*0033
REF*MC*777777777
RMR*IV*26565*PO*5121.83*5507.91*115.96
REF*DP*00040
REF*MR*0033
REF*PO*9915981131
REF*MC*796401455
REF*19*07
REF*ST*0078742029917
DTM*097*20190821
ADX*-270.12*59*CM*26565
REF*6O*022
REF*MC*000000025
RMR*IV*26567*PO*4011.69*4097.96*86.27
REF*DP*00040
REF*MR*0020
REF*PO*9958859372
REF*MC*796401457
REF*19*07
REF*ST*0078742030005
DTM*097*20190821
RMR*IV*26635*PO*3329.74*3401.97*72.23
REF*DP*00040
REF*MR*0033
REF*PO*1814609777
REF*MC*831108152
REF*19*07
REF*ST*0078742030999
DTM*097*20190828
SE*48*101067
GE*1*820101061
IEA*1*820101061

I am unable to extract and separate the ADX. If I follow the code below, it combines the ADX. I want to list out:

  1. ADX (not related to RMR) and their REFS
  2. RMR and their REFS
  3. ADX related to their preceding RMR and their REFS
    [EdiMessage]
    public class RemittanceDocument
    {
        #region Header Trailer

        [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; }

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

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

        #endregion
        public List<ADX> Adjustments { get; set; }

    }

    [EdiSegmentGroup("ADX")]
    public class ADX
    {
    }
skhan-nacmgit commented 4 years ago

I followed your advice from another post (issue) and this got me closer.

    [EdiMessage]
    public class RemittanceDocument
    {
        #region Header Trailer

        [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; }

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

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

        #endregion
        public List<ADX> Adjustments { get; set; }

    }

    [EdiSegmentGroup("ADX")]
    public class ADX
    {
    }

    [EdiSegment, EdiPath("REF")]
    public class REF
    {
        [EdiValue("X(35)", Path = "REF/0")]
        public string Identifier { get; set; }
    }

    [EdiSegmentGroup("ADX", "REF")]
    public class Adjustment : ADX
    {
        public List<REF> REF { get; set; }
    }

But still not clear on the looping in this 820.

skhan-nacmgit commented 4 years ago

Sender and Receiver (Party Identification) is blank.

        [EdiGroup]
        public class FunctionalGroup
        {

            [EdiValue("X(2)", Path = "GS/0", Description = "GS01 - Functional Identifier Code")]
            public string FunctionalIdentifierCode { get; set; }

            [EdiValue("X(10)", Path = "GS/1", Description = "GS02 - Application Sender's Code")]
            public string ApplicationSenderCode { get; set; }

            [EdiValue("X(6)", Path = "GS/2", Description = "GS03 - Application Receiver's Code")]
            public string ApplicationReceiverCode { get; set; }

            [EdiValue("9(8)", Path = "GS/3", Format = "yyyyMMdd", Description = "GS04 - Date")]
            [EdiValue("9(4)", Path = "GS/4", Format = "HHmm", Description = "GS05 - Time")]
            public DateTime Date { get; set; }

            [EdiValue("9(9)", Path = "GS/5", Format = "HHmm", Description = "GS06 - Group Control Number")]
            public int GroupControlNumber { get; set; }

            [EdiValue("X(1)", Path = "GS/6", Format = "HHmm", Description = "GS07 Responsible Agency Code")]
            public string AgencyCode { get; set; }

            [EdiValue("X(6)", Path = "GS/7", Format = "HHmm", Description = "GS08 Version / Release / Industry Identifier Code")]
            public string Version { get; set; }

            public List<RemittanceDocument> RADocument { get; set; }

            //[EdiValue("9(1)", Path = "GE/0", Description = "97 Number of Transaction Sets Included")]
            //public int TransactionsCount { get; set; }

            //[EdiValue("9(9)", Path = "GE/1", Description = "28 Group Control Number")]
            //public int GroupTrailerControlNumber { get; set; }
        }

        [EdiMessage]
        public class RemittanceDocument
        {

            #region Header Trailer

            [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; }

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

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

            [EdiValue("X(1)", Path = "BPR/0")]
            public string TransactionHandlingCode { get; set; }

            [EdiValue("9(18)", Path = "BPR/1")]
            public decimal MonetaryAmount { get; set; }

            [EdiValue("X(1)", Path = "BPR/2")]
            public string CreditDebitFlagCode { get; set; }

            [EdiValue("X(3)", Path = "BPR/3")]
            public string PaymentMethodCode { get; set; }

            [EdiValue("X(1)", Path = "BPR/4")]
            public string OriginatingCompanyIdentifier { get; set; }

            [EdiValue("9(8)", Path = "BPR/15", Format = "yyyyMMdd")]
            public string SettlementDate { get; set; }

            [EdiValue("X(10)", Path = "TRN/1")]
            public string CheckNumber { get; set; }

            [EdiCondition("PR", Path = "N1/0/0")]
            public PartyIdentification Sender { get; set; }

            [EdiCondition("PE", Path = "N1")]
            public PartyIdentification Receiver { get; set; }

            //[EdiValue("X(60)", Path = "N1/0/1")]
            //public string Sender { get; set; }

            public List<Adjustment> Adjustments { get; set; }
            public List<RemittanceAdvice> RAs { get; set; }
        }

        [EdiSegment, EdiPath("ADX")]
        public class ADX
        {

        }

        [EdiSegment, EdiPath("RMR")]
        public class RMR
        {

        }

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

            [EdiValue("X(35)", Path = "REF/1")]
            public string Value { get; set; }
        }

        [EdiSegmentGroup("ADX", "REF")]
        public class Adjustment : ADX
        {
            public List<REF> REF { get; set; }
        }

        [EdiSegmentGroup("RMR", "REF", "DTM")]
        public class RemittanceAdvice
        {
            public List<REF> REF { get; set; }
            public DateTimePeriod Date { get; set; }
        }

        [EdiSegment, EdiPath("DTM")]
        public class DateTimePeriod
        {
            [EdiValue(Path = "DTM/0")]
            public int Function { get; set; }

            [EdiValue("9(8)", Path = "DTM/1", Format = "yyyyMMdd")]
            public virtual DateTime Value { get; set; }

        }

        [EdiElement, EdiPath("N1")]
        public class PartyIdentification
        {
            [EdiValue("X(3)", Path = "N1/0")]
            public string EntityIdentifierCode { get; set; }

            [EdiValue("X(60)", Path = "N1/1")]
            public string Name { get; set; }

        }
skhan-nacmgit commented 4 years ago

Changing to this seems to work.

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

            [EdiValue("X(60)", Path = "N1/1")]
            public string Name { get; set; }

        }
cleftheris commented 4 years ago

That is because you can bind classes marked as elements only inside an segment.

PS If you ever need to reuse classes marked as element under a different segment context (different segment name) you can also use wildcards in paths

skhan-nacmgit commented 4 years ago

Can you provide me an adhoc example of such binding?

cleftheris commented 4 years ago

The wildcard in paths is used usualy on the EDIValue attribute. Lets say hypothetically you had the same structure PartyIdentitfication with the two same properties occurring under a different segment name. Lets say N1 and N2 where the segment names. Then you would do the following.


[EdiMessage]
public class MyExampleMessage
{

     [EdiPath("N1")]
     public PartyIdentification N1 { get; set; }
     [EdiPath("N2")]
     public PartyIdentification N2 { get; set; }
}

[EdiSegment]
public class PartyIdentification
{
     [EdiValue("X(3)", Path = "*/0")]
     public string EntityIdentifierCode { get; set; }
     [EdiValue("X(60)", Path = "*/1")]
     public string Name { get; set; }
}

PS: The X12 does not make much use of components inside elements so it would not make much sense for you to create element marked classes at all. In EDIFact on the other hand this is very common thing.

skhan-nacmgit commented 4 years ago

THANK YOU! With respect to this library, what is considered an EdiMessage? I am trying to understand how this library process loops.

skhan-nacmgit commented 4 years ago

THANK YOU! With respect to this library, what is considered an EdiMessage? I am trying to understand how this library process loops.

cleftheris commented 4 years ago

the message attribute is only used to encapsulate the well known structure segments ST & SE (in x12). Same goes for the functional group segments and EdiGroup. Every other loop can be bound to EdiSegmentGroup or plain EdiSegment