indice-co / indice-co/EDI.Net

How to deal with possibility of SegmentGroup absence in the EDI file?

Open
#216 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
490
Forks
173
PR merge metrics
No merged PRs in 30d

Description

Hello :),

I am currently developing a solution for deserialization of IFCSUM D01B message using EDI.Net. The problem that I am facing has to do with the way that the library is handling SegmentGroups, which I probably just don't understand.

Given this sample D01B IFCSUM message:

```
UNA:+.? '
UNB+UNOY:3+Sample+Sample+211217:1234'
UNH+1+IFCSUM:D:01B:UN'
BGM+Sample+Sample+Sample'
DTM+Sample:Sample:Sample'
FTX+Sample+++Sample'
CNT+Sample:Sample'
CNT+Sample:Sample'
CNT+Sample:Sample'
CNT+Sample:Sample'
RFF+Sample:Sample'
RFF+Sample:Sample'
RFF+Sample:Sample'
NAD+Sample+Sample::Sample'
NAD+Sample+Sample'
TDT+Sample++Sample+Sample:Sample+Sample:Sample'
DTM+Sample:Sample:Sample'
DTM+Sample:Sample:Sample'
TSR+Sample+Sample'
TSR+Sample+Sample'
TSR+Sample+Sample'
CNI+Sample+Sample'
TPL+Sample'
MEA+Sample++Sample:Sample'
DTM+Sample:Sample:Sample'
DTM+Sample:Sample:Sample'
DTM+Sample:Sample:Sample'
DTM+Sample:Sample:Sample'
TSR+Sample+Sample'
TSR+Sample+Sample'
TSR+Sample+Sample'
TOD+Sample++Sample'
RFF+Sample:Sample'
RFF+Sample:Sample'
RFF+Sample:Sample'
RFF+Sample:Sample'
TDT+Sample++Sample'
NAD+Sample+Sample++Sample:Sample+Sample+Sample++Sample+Sample'
NAD+Sample+Sample++Sample:Sample+Sample+Sample++Sample+Sample'
NAD+Sample+Sample++Sample:Sample+Sample+Sample++Sample+Sample'
RFF+Sample:Sample'
NAD+Sample+Sample++Sample:Sample+Sample+Sample++Sample+Sample'
RFF+Sample:Sample'
NAD+Sample+Sample++Sample:Sample+Sample+Sample++Sample+Sample'
RFF+Sample:Sample'
GID+Sample+Sample:Sample:::Sample'
HAN+Sample:::Sample'
FTX+Sample+++Sample'
MEA+Sample+Sample+Sample:Sample'
MEA+Sample++Sample:Sample'
DIM+Sample+Sample:Sample:Sample:Sample'
RFF+Sample:Sample'
PCI+Sample+Sample'
UNT+52+1'
UNZ+1+1234'
```
Everything is working fine when I use SequenceEnd in the SegmentGroup attribute, and segment defined as the SequenceEnd acutally exists. Below are a few examples of my implementation of the message as of right now (passing child segments in the SegmentGroup attribute constructor):

```csharp
public class D01BIFCSUM
{
#region Interchange Header

// S001/0001
[EdiValue(Path = "UNB/0")]
public string UNB_SyntaxIdentifier { get; set; }

// S001/0002
[EdiValue(Path = "UNB/0/1")]
public string UNB_SyntaxVersionNumber { get; set; }

// S002/0004
[EdiValue(Path = "UNB/1")]
public string UNB_InterchangeSenderIdentification { get; set; }

// S003/0010
[EdiValue(Path = "UNB/2")]
public string UNB_InterchangeRecipient { get; set; }

// S004/0017
[EdiValue(Path = "UNB/3/0")]
public string UNB_Date { get; set; }

// S004/0019
[EdiValue(Path = "UNB/3/1")]
public string UNB_Time { get; set; }

// 050/0020
[EdiValue(Path = "UNB/4")]
public string UNB_InterchangeControlReference { get; set; }

#endregion Interchange Header

// D01B IFCSUM
public D01B_IFCSUM_MESSAGE Message { get; set; }

#region Interchange Trailer

// 0036
[EdiValue(Path = "UNZ/0")]
public int UNZ_InterchageControlCount { get; set; }

// 0020
[EdiValue(Path = "UNZ/1")]
public string UNZ_InterchangeControlReference { get; set; }

#endregion Interchange Trailer
}
```
```csharp
[EdiMessage]
public class D01B_IFCSUM_MESSAGE
{
#region Message Header Info

// 010/0062
[EdiValue(Path = "UNH/0")]
public string UNH_MessageReferenceNumber { get; set; }

// S009/0065
[EdiValue(Path = "UNH/1/0")]
public string UNH_MessageType { get; set; }

// S009/0052
[EdiValue(Path = "UNH/1/1")]
public string UNH_MessageVersionNumber { get; set; }

// S009/0054
[EdiValue(Path = "UNH/1/2")]
public string UNH_MessageReleaseNumber { get; set; }

// S009/0051
[EdiValue(Path = "UNH/1/3")]
public string UNH_ControllingAgency { get; set; }

#endregion Message Header Info

// x1
public D01B_BGM_SEGMENT BGM { get; set; }

// x0-9
public D01B_DTM_SEGMENT[] DTM { get; set; }

// x0-99
public D01B_MOA_SEGMENT[] MOA { get; set; }

// x0-99
public D01B_FTX_SEGMENT[] FTX { get; set; }

// x0-9
public D01B_CNT_SEGMENT[] CNT { get; set; }

// x0-9
public D01B_RFF_SEGMENTGROUP1[] RFF_SEGMENT_GROUP_1 { get; set; }

// x0-9
public D01B_NAD_SEGMENTGROUP4[] NAD_SEGMENT_GROUP_4 { get; set; }

// x0-9
public D01B_TDT_SEGMENTGROUP9[] TDT_SEGMENT_GROUP_9 { get; set; }

// x0-9999
public D01B_EQD_SEGMENTGROUP21[] EQD_SEGMENT_GROUP_21 { get; set; }

// x0-9999
public D01B_CNI_SEGMENTGROUP25[] CNI_SEGMENT_GROUP_25 { get; set; }

// 0074
[EdiValue(Path = "UNT/0")]
public string UNT_NumberOfSegments { get; set; }

// 0062
[EdiValue(Path = "UNT/1")]
public string UNT_MessageReferenceNumber { get; set; }
}
```

```csharp
[EdiSegment, EdiPath("BGM")]
public class D01B_BGM_SEGMENT
{
// C002/1001
[EdiValue(Path = "BGM/0")]
public string BGM_MessageName { get; set; }

// C106/1004
[EdiValue(Path = "BGM/1")]
public string BGM_MessageNumber { get; set; }

// 030/1225
[EdiValue(Path = "BGM/2")]
public string BGM_MessageFunction { get; set; }
}
```

```csharp
[EdiSegmentGroup("CNI", "TPL", "DTM", "TSR", "CUX", "MOA", "FTX", "GDS", "TOD", "RFF", "TDT", "NAD", "GID")]
public class D01B_CNI_SEGMENTGROUP25
{
// 010/1490
[EdiValue(Path = "CNI/0")]
public string CNI_ConsolidationItemNumber { get; set; }

// C503/1004
[EdiValue(Path = "CNI/1")]
public string CNI_DocumentIdentifier { get; set; }

public D01B_TPL_SEGMENTGROUP28[] TPL { get; set; }

public D01B_DTM_SEGMENT[] DTM { get; set; }

public D01B_TSR_SEGMENT[] TSR { get; set; }

public D01B_CUX_SEGMENT[] CUX { get; set; }

public D01B_MOA_SEGMENT[] MOA { get; set; }

public D01B_FTX_SEGMENT[] FTX { get; set; }

public D01B_GDS_SEGMENT[] GDS { get; set; }

public D01B_TOD_SEGMENTGROUP31[] TOD { get; set; }

public D01B_RFF_SEGMENTGROUP32[] RFF { get; set; }

public D01B_TDT_SEGMENTGROUP38[] TDT { get; set; }

public D01B_NAD_SEGMENTGROUP43[] NAD { get; set; }

public D01B_GID_SEGMENTGROUP50[] GID { get; set; }
}
```
I don't want to paste the whole code base for this because it would be massive, but I hope the picture of the situation is clear enough. Every other EdiSegment is nested like BGM in this example, and every other SegmentGroup is also nested like in this example, according to the structure of the EDI file above. When I assume that, for example, RFF SG1's SequenceEnd is "NAD" (NAD SG4), or NAD SG4's SequenceEnd is TDT SG9 etc. (even in far more nested SG's like CNI or GID it works perfectly fine) it's all good.

So after all this, what's the actual problem? I am in a situation when I can't be always sure what my EDI file will include, and there are some SegmentGroups that will not always be present, let's look at the example:

```
UNA:+.? '
UNB+UNOY:3+Sample+Sample+211217:1234'
UNH+1+IFCSUM:D:01B:UN'
BGM+Sample+Sample+Sample'
DTM+Sample:Sample:Sample'
FTX+Sample+++Sample'
CNT+Sample:Sample'
CNT+Sample:Sample'
CNT+Sample:Sample'
CNT+Sample:Sample'
RFF+Sample:Sample'
RFF+Sample:Sample'
RFF+Sample:Sample'
NAD+Sample+Sample::Sample'
NAD+Sample+Sample'
TDT+Sample++Sample+Sample:Sample+Sample:Sample'
DTM+Sample:Sample:Sample'
DTM+Sample:Sample:Sample'
TSR+Sample+Sample'
TSR+Sample+Sample'
TSR+Sample+Sample'
EQD+Sample+Sample'
CNI+Sample+Sample'
TPL+Sample'
MEA+Sample++Sample:Sample'
DTM+Sample:Sample:Sample'
DTM+Sample:Sample:Sample'
DTM+Sample:Sample:Sample'
DTM+Sample:Sample:Sample'
TSR+Sample+Sample'
TSR+Sample+Sample'
TSR+Sample+Sample'
TOD+Sample++Sample'
RFF+Sample:Sample'
RFF+Sample:Sample'
RFF+Sample:Sample'
RFF+Sample:Sample'
TDT+Sample++Sample'
NAD+Sample+Sample++Sample:Sample+Sample+Sample++Sample+Sample'
NAD+Sample+Sample++Sample:Sample+Sample+Sample++Sample+Sample'
NAD+Sample+Sample++Sample:Sample+Sample+Sample++Sample+Sample'
RFF+Sample:Sample'
NAD+Sample+Sample++Sample:Sample+Sample+Sample++Sample+Sample'
RFF+Sample:Sample'
NAD+Sample+Sample++Sample:Sample+Sample+Sample++Sample+Sample'
RFF+Sample:Sample'
GID+Sample+Sample:Sample:::Sample'
HAN+Sample:::Sample'
FTX+Sample+++Sample'
MEA+Sample+Sample+Sample:Sample'
MEA+Sample++Sample:Sample'
DIM+Sample+Sample:Sample:Sample:Sample'
RFF+Sample:Sample'
PCI+Sample+Sample'
UNT+53+1'
UNZ+1+1234'
```

The only difference between two provided EDIFACT's is the EQD SegmentGroup, after TDT SG9, it's there sometimes, sometimes it is not ;). So when I (wrongly) assume that TDT SG9's SequenceEnd is CNI, it fails when there is EQD segment present in the file, or when I assign EQD as SequenceEnd of TDT, and EQD is not present (ok otherwise). That's it, the only problem. I have looked at a lot of issues posted here, where providing child segments and SegmentGroups in the constructor of SegmentGroups would be the way to go, but then Deserialization fails, for example, the RFF SG1 which is defined in the EdiMessage attributed class collects all 10 RFF segments from the whole file, instead of 3 which are actually there in the main message context of EDIFACT.

I suspect that the solution for this problem is there, but I just can't quite find it, so I would very much appreciate some help with this examples. If needed, I will provide more implementation examples from the D01BIFCSUM class, and thanks in advance :).

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with D01B_IFCSUM_MESSAGE and the nested D01B segment-group classes, especially D01B_CNI_SEGMENTGROUP25, and reproduce deserialization with both supplied IFCSUM messages. Compare how the optional EQD group changes TDT and CNI boundaries, and verify that the main-message RFF collection does not include nested RFF segments. Done means both samples deserialize with their segments assigned to the correct groups.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.