SAIF.Framework.Common.Files business rules
This page captures the 62 business rules enforced by SAIF.Framework.Common.Files. All rules are enforced by this library's own code (no rule is enforced by an inherited BOF/NHibernate base class). Rules BR-001 –BR-016 govern the flat-file subsystem; BR-017 –BR-037 govern EDI structural parsing/building/grouping; BR-038 –BR-062 govern individual typed segments and date conversion.
BR-001 Default configuration required
Field
Value
Statement
A record type must supply at least one file-format configuration before it can be read or written without an explicit format.
Trigger
Read(path) / Write(path, data) called with no resolvable configuration.
Enforcement
FileReader<TRecord>.Read(string); FileWriter<TRecord>.Write(string, IEnumerable<TRecord>)
Outcome
ApplicationException("No default configuration found.")
Source
Common\SAIF.Common.Files\Core\FileReader.cs, Common\SAIF.Common.Files\Core\FileWriter.cs
BR-002 Single IsDefault configuration required among multiple
Field
Value
Statement
When a record type declares more than one format attribute, exactly one must be marked IsDefault for the format-less overload to resolve.
Trigger
Multiple FormatBase attributes on TRecord.
Enforcement
FileReader<TRecord>.Read(string); FileWriter<TRecord>.Write(string, IEnumerable<TRecord>)
Outcome
The IsDefault configuration is used; otherwise ApplicationException.
Source
Common\SAIF.Common.Files\Core\FileReader.cs, Common\SAIF.Common.Files\Core\FileWriter.cs
Field
Value
Statement
A requested FileFormats value must match a declared configuration.
Trigger
Read(path, format) / Write(path, data, format).
Enforcement
FileReader<TRecord>.Read(string, FileFormats); FileWriter<TRecord>.Write(string, IEnumerable<TRecord>, FileFormats)
Outcome
ApplicationException("No Configuration found for requested format.")
Source
Common\SAIF.Common.Files\Core\FileReader.cs, Common\SAIF.Common.Files\Core\FileWriter.cs
BR-004 TrimAll trims field values on read
Field
Value
Statement
Field values are whitespace-trimmed on read when the configuration sets TrimAll.
Trigger
Reading any file.
Enforcement
FileReader<TRecord>.PrepareParser (parser.TrimWhiteSpace = configuration.TrimAll)
Outcome
Leading/trailing whitespace removed from every field.
Source
Common\SAIF.Common.Files\Core\FileReader.cs
BR-005 Quoted-field handling is CSV-only
Field
Value
Statement
Quoted-field handling is enabled only for the CSV format; other delimited formats treat quotes as literal characters.
Trigger
Reading a delimited file.
Enforcement
FileReader<TRecord>.PrepareParser (HasFieldsEnclosedInQuotes = (Format == FileFormats.Csv))
Outcome
CSV honours "value" field enclosure; Delimited/TabDelimited do not.
Source
Common\SAIF.Common.Files\Core\FileReader.cs
Field
Value
Statement
When the configuration declares HasHeaderRecord, the first physical row of the file is a header and is not materialised as a data record.
Trigger
Reading a file whose configuration sets HasHeaderRecord.
Enforcement
FileReader<TRecord>.Read(string, IFileConfiguration) (if (configuration.HasHeaderRecord && first))
Outcome
First row skipped.
Source
Common\SAIF.Common.Files\Core\FileReader.cs
BR-007 Record-build failures report layout id and row data
Field
Value
Statement
Any failure to map a row to the record type is reported with the offending layout id and the raw row data.
Trigger
Exception thrown while building a record.
Enforcement
FileReader<TRecord>.BuildRecord catch block
Outcome
ApplicationException("Configuration Layout Error: Unable to build data record. (<layoutId>) [Row data: <rowData>]", innerException)
Source
Common\SAIF.Common.Files\Core\FileReader.cs
BR-008 Fixed-width values forced to layout length
Field
Value
Statement
Fixed-width output values are forced to the layout length: longer values are truncated, shorter values are padded on the pad side implied by the alignment (left-aligned with a space by default), and a zero length yields an empty value.
Trigger
Writing a FileFormats.Fixed record or header.
Enforcement
FileWriter<TRecord>.AlignValue; defaults in FileRecordLayout constructor (AlignLeft = true, pads ' ')
Outcome
Every fixed field occupies exactly Length characters.
Source
Common\SAIF.Common.Files\Core\FileWriter.cs, Common\SAIF.Common.Files\Core\Configurations\FileRecordLayout.cs
Field
Value
Statement
A header field must have either a bound property or a non-blank Title.
Trigger
Writing a header record.
Enforcement
FileWriter<TRecord>.BuildHeaderRecord
Outcome
ApplicationException("Configuration Layout Error: No Property or Title defined for Header. (<displayId>)")
Source
Common\SAIF.Common.Files\Core\FileWriter.cs
BR-010 Writable layout must resolve to a property
Field
Value
Statement
A writable layout must resolve to a property, either directly (Property) or by Name, unless a custom writer is supplied.
Trigger
Writing a data record.
Enforcement
FileWriter<TRecord>.GetPropertyValue
Outcome
ApplicationException("Configuration Layout Error: No Property or Name assigned to set value. (<displayId>)")
Source
Common\SAIF.Common.Files\Core\FileWriter.cs
BR-011 Record-derived types round-trip the raw line
Field
Value
Statement
A record type deriving from Record round-trips the raw line: the whole line is stored in Value on read and written back verbatim on write, bypassing layout mapping.
Trigger
TRecord derives from Core.Record.
Enforcement
FileReader<TRecord>.BuildRecord (binds Value/Index); FileWriter<TRecord>.BuildRecord (returns Value)
Outcome
Raw-line pass-through.
Source
Common\SAIF.Common.Files\Core\FileReader.cs, Common\SAIF.Common.Files\Core\FileWriter.cs, Common\SAIF.Common.Files\Core\Record.cs
BR-012 Delimited layouts use 1-based element ordinals
Field
Value
Statement
Delimited layouts address fields by 1-based element ordinal; a custom reader runs before, and a custom read converter instead of, the default Convert.ChangeType.
Trigger
Reading each readable layout.
Enforcement
FileReader<TRecord>.BuildRecord (fields[lo.Element - 1]), ConvertAndSetValue
Outcome
Value converted to the property type and assigned.
Source
Common\SAIF.Common.Files\Core\FileReader.cs
BR-013 TabDelimitedRecord always splits on tab
Field
Value
Statement
TabDelimitedRecord always splits on a tab character, regardless of the delimiter requested by the caller.
Trigger
FileReader.ReadDelimited(path, delimiter) or direct construction.
Enforcement
TabDelimitedRecord constructors (Delimiter = "\t" in both)
Outcome
Non-tab delimiters passed to ReadDelimited are ignored for field splitting.
Source
Common\SAIF.Common.Files\Core\TabDelimitedRecord.cs
BR-014 No trailing delimiter in delimited output
Field
Value
Statement
In delimited output the delimiter separates fields and is never emitted after the final field; fixed-width output emits no delimiter at all.
Trigger
Writing a record or header.
Enforcement
FileWriter<TRecord>.BuildRecord, BuildHeaderRecord (if (lo != layouts.Last() && Format != Fixed))
Outcome
No trailing delimiter.
Source
Common\SAIF.Common.Files\Core\FileWriter.cs
BR-015 Output value resolution order
Field
Value
Statement
Output value resolution order is: custom writer, then property value, then custom write converter, then the layout format string, then ToString().
Trigger
Writing each writable layout.
Enforcement
FileWriter<TRecord>.GetPropertyValue
Outcome
Formatted string value.
Source
Common\SAIF.Common.Files\Core\FileWriter.cs
BR-016 ReadCustom and WriteCustom force layout direction
Field
Value
Statement
A layout configured with ReadCustom becomes read-only and one configured with WriteCustom becomes write-only.
Trigger
Fluent configuration.
Enforcement
FileLayoutBuilder.ReadCustom, WriteCustom (also ReadOnly(), WriteOnly())
Outcome
Layout excluded from the opposite direction's layout set.
Source
Common\SAIF.Common.Files\Core\Configurations\FileLayoutBuilder.cs
BR-017 Physical line breaks are not significant
Field
Value
Statement
Physical line breaks in an EDI file are not significant; the whole file is treated as one continuous segment stream.
Trigger
Reading an EDI file.
Enforcement
EdiFileReader.Read (trims and concatenates all lines before parsing)
Outcome
Wrapped or single-line files parse identically.
Source
Common\SAIF.Common.Files\Edi\Core\Readers\EdiFileReader.cs
BR-018 Segments delimited by tilde empty segments discarded
Field
Value
Statement
Segments are delimited by ~, and empty segments are discarded.
Trigger
Parsing EDI text.
Enforcement
EdiSegmentParser.Parse (Split(SegmentDelimiter, RemoveEmptyEntries)); delimiter in EdiRecordBase / Delimiters.Segment
Outcome
One EdiSegment per non-empty token.
Source
Common\SAIF.Common.Files\Edi\Core\Parsers\EdiSegmentParser.cs, Common\SAIF.Common.Files\Edi\EdiRecordBase.cs
BR-019 Colon-containing elements become composite elements
Field
Value
Statement
A data element containing : is treated as a composite element and split into sub-elements.
Trigger
Parsing a segment's elements.
Enforcement
EdiDataElementParser.Parse (if (item.Contains(":"))) → EdiCompositeDataElementParser.Parse
Outcome
EdiCompositeDataElement with child EdiDataElements.
Source
Common\SAIF.Common.Files\Edi\Core\Parsers\EdiDataElementParser.cs, Common\SAIF.Common.Files\Edi\Core\Parsers\EdiCompositeDataElementParser.cs
BR-020 First element is the segment identifier
Field
Value
Statement
The first data element of a segment is element 0 and is the segment identifier.
Trigger
Parsing or building a segment.
Enforcement
EdiDataElementParser.Parse (indexValue = first ? 0 : IndexingSequence.NextValue); EdiSegmentParser.Parse (SegmentId = GetChildValue(0)); SegmentBuilder(string)
Outcome
SegmentId populated from element 0.
Source
Common\SAIF.Common.Files\Edi\Core\Parsers\EdiDataElementParser.cs, Common\SAIF.Common.Files\Edi\Core\Parsers\EdiSegmentParser.cs, Common\SAIF.Common.Files\Edi\Core\Builders\SegmentBuilder.cs
BR-021 Segment construction requires a non-null element list
Field
Value
Statement
Segment construction requires its inputs: a non-null element list, and (for Build(IList<>)) an element at index 0 to supply the segment id.
Trigger
SegmentBuilder.Build(IList<IEdiDataElement>).
Enforcement
SegmentBuilder.Build(IList<IEdiDataElement>) via Enforce.ArgumentNotNull
Outcome
Argument exception when null (Origin: SAIF.Framework.Common, Enforce).
Source
Common\SAIF.Common.Files\Edi\Core\Builders\SegmentBuilder.cs
BR-022 Only one identifying element at index 0
Field
Value
Statement
A segment may contain only one identifying element at index 0.
Trigger
Adding a second element with index 0.
Enforcement
SegmentBuilder.Add(int, string) and Add(IEdiDataElement)
Outcome
ApplicationException("Segment already contains an identifying Element")
Source
Common\SAIF.Common.Files\Edi\Core\Builders\SegmentBuilder.cs
BR-023 Segment id must not be blank
Field
Value
Statement
A segment id must be supplied and must not be blank.
Trigger
new SegmentBuilder(segmentId).
Enforcement
SegmentBuilder(string) via Enforce.ArgumentNotNullOrWhiteSpace
Outcome
Argument exception when null/blank (Origin: SAIF.Framework.Common, Enforce).
Source
Common\SAIF.Common.Files\Edi\Core\Builders\SegmentBuilder.cs
BR-024 Null element values are omitted
Field
Value
Statement
Null element values are omitted from a segment rather than written as empty elements.
Trigger
Adding an element with a null value.
Enforcement
SegmentBuilder.Add(int, string), Add(IEdiDataElement); EdiCompositeDataElement.SetChildElement (null removes an existing child)
Outcome
Optional elements absent from output.
Source
Common\SAIF.Common.Files\Edi\Core\Builders\SegmentBuilder.cs, Common\SAIF.Common.Files\Edi\EdiCompositeDataElement.cs
BR-025 Composite sub-elements require a composite parent
Field
Value
Statement
A composite sub-element can only be added to an element that is itself composite.
Trigger
Add(elementIndex, compositeIndex, value) where the parent exists but is a simple data element.
Enforcement
SegmentBuilder.Add(int, int, string)
Outcome
ApplicationException("Element at index {0} is not a composite element")
Source
Common\SAIF.Common.Files\Edi\Core\Builders\SegmentBuilder.cs
BR-026 Composite element values joined with colon
Field
Value
Statement
Composite element values are joined with :, the trailing : is removed, and the composite is terminated with *.
Trigger
Serialising a composite element.
Enforcement
EdiRecordBuilder.BuildCompositeDataElementValue; EdiCompositeDataElement.SetChildElement / ToString
Outcome
Canonical composite text.
Source
Common\SAIF.Common.Files\Edi\Core\Builders\EdiRecordBuilder.cs, Common\SAIF.Common.Files\Edi\EdiCompositeDataElement.cs
BR-027 Skipped element ordinals preserved with placeholders
Field
Value
Statement
Skipped element ordinals are preserved by emitting * placeholders, and a trailing element delimiter is removed from the finished segment.
Trigger
Serialising a segment whose elements are non-contiguous.
Enforcement
EdiRecordBuilder.BuildSegmentRecord
Outcome
Element positions remain X12-correct.
Source
Common\SAIF.Common.Files\Edi\Core\Builders\EdiRecordBuilder.cs
BR-028 Simple data element terminated by asterisk
Field
Value
Statement
A simple data element is terminated by *.
Trigger
Serialising a data element.
Enforcement
EdiRecordBuilder.BuildDataElementValue; EdiDataElement.ToString
Outcome
value*
Source
Common\SAIF.Common.Files\Edi\Core\Builders\EdiRecordBuilder.cs, Common\SAIF.Common.Files\Edi\EdiDataElement.cs
BR-029 First ISA and IEA are the interchange header and trailer
Field
Value
Statement
The first ISA segment is the interchange header and the first IEA segment is the interchange trailer.
Trigger
RefreshGroupings.
Enforcement
EdiFile.RefreshGroupings (FirstOrDefault(x => x.SegmentId == "ISA" / "IEA"), then IsaSegment.Parse / IeaSegment.Parse)
Outcome
EdiFile.Header / EdiFile.Trailer populated.
Source
Common\SAIF.Common.Files\Edi\EdiFile.cs
BR-030 Functional groups built only when all four control segments present
Field
Value
Statement
The functional-group hierarchy is built only when the interchange contains all four control segments ISA, IEA, GS and GE.
Trigger
RefreshGroupings.
Enforcement
EdiFile.RefreshGroupings
Outcome
Incomplete interchanges expose segments but no eagerly-built group tree.
Source
Common\SAIF.Common.Files\Edi\EdiFile.cs
BR-031 Every added segment receives the next sequential index
Field
Value
Statement
Every segment added to a file receives the next sequential index, and index order defines document order.
Trigger
EdiFile.Add(segment).
Enforcement
EdiFile.Add (segment.Index = IndexingSequence.NextValue; Origin of Sequence: SAIF.Framework.Common)
Outcome
Deterministic ordering for grouping and writing.
Source
Common\SAIF.Common.Files\Edi\EdiFile.cs
BR-032 Adding a control segment re-derives envelope groupings
Field
Value
Statement
Adding any of the control segments ISA, IEA, GS, GE re-derives the envelope groupings.
Trigger
EdiFile.Add with a control segment id.
Enforcement
EdiFile.Add (segment.SegmentId.IsIn("ISA","IEA","GS","GE"); Origin of IsIn: SAIF.Framework.Common)
Outcome
Header/trailer/groups refreshed.
Source
Common\SAIF.Common.Files\Edi\EdiFile.cs
BR-033 Control segments excluded from member Segments collections
Field
Value
Statement
Control segments are excluded from the member Segments collection of the group they delimit: ISA/IEA/GS/GE from a functional group, ST/SE from a transaction set, HL/ST/SE from a hierarchical level, and BHT/HL/ST/SE from a hierarchical transaction.
Trigger
Building groups.
Enforcement
EdiGroupParser.CreateFunctionalGroups, CreateTransactionSets, CreateHierarchialTransactions
Outcome
Group Segments contain business segments only.
Source
Common\SAIF.Common.Files\Edi\Core\Parsers\EdiGroupParser.cs
BR-034 Group keys derived from control-number elements
Field
Value
Statement
A functional group is keyed by GS element 6, a transaction set by ST element 2, and a hierarchical transaction/level by element 1 of BHT/HL.
Trigger
Building groups.
Enforcement
EdiGroupParser.ParseSegmentGroup calls in CreateFunctionalGroups (6), CreateTransactionSets (2), CreateHierarchialTransactions (1)
Outcome
ISegmentGroup.Key populated from the control number.
Source
Common\SAIF.Common.Files\Edi\Core\Parsers\EdiGroupParser.cs
BR-035 Hierarchical levels nested inside hierarchical transaction
Field
Value
Statement
Hierarchical levels (HL) are nested inside the hierarchical transaction (BHT) of their transaction set.
Trigger
Building a transaction set.
Enforcement
EdiGroupParser.CreateHierarchialTransactions
Outcome
HierarchialTransaction.Levels populated.
Source
Common\SAIF.Common.Files\Edi\Core\Parsers\EdiGroupParser.cs
BR-036 Segment group ownership determined by position
Field
Value
Statement
A segment group owns every segment from its own index up to (but excluding) the next occurrence of the break segment, or the end of the parent list when there is no next occurrence.
Trigger
ParseSegmentGroup.
Enforcement
EdiGroupParser.ParseSegmentGroup + GetNext + MoveSegmentsToSegmentGroup
Outcome
Segment membership determined by position.
Source
Common\SAIF.Common.Files\Edi\Core\Parsers\EdiGroupParser.cs
BR-037 EDI interchange written as a single line overwriting existing file
Field
Value
Statement
An EDI interchange is written as a single line of ~-terminated segments, overwriting any existing file.
Trigger
Writing an EDI file.
Enforcement
EdiFileWriter.Write (File.WriteAllText)
Outcome
Single-line output file.
Source
Common\SAIF.Common.Files\Edi\Core\Writers\EdiFileWriter.cs
BR-038 ISA header fixed qualifiers and padding
Field
Value
Statement
The ISA header is emitted with fixed authorization/security qualifiers 00, ten-space authorization and security fields, ZZ interchange id qualifiers, sender and receiver ids right-padded to 15 characters, a yyMMdd/HHmm date-time, and a 9-digit zero-padded control number.
Trigger
Building an ISA segment.
Enforcement
IsaSegment.Build
Outcome
Fixed-width X12 interchange header.
Source
Common\SAIF.Common.Files\Edi\Segments\IsaSegment.cs
BR-039 ISA acknowledgement request flag
Field
Value
Statement
The ISA acknowledgement request flag is 1 when requested and 0 otherwise, and is read back as true only for 1.
Trigger
Building/filling an ISA segment.
Enforcement
IsaSegment.Build / IsaSegment.Fill (element 14)
Outcome
AcknowledgementRequest round-trips.
Source
Common\SAIF.Common.Files\Edi\Segments\IsaSegment.cs
BR-040 GS header responsible agency code and batch date-time
Field
Value
Statement
The GS header emits the responsible agency code X at element 7 and a yyyyMMdd/HHmm batch date-time; the version control number is read from element 8.
Trigger
Building/filling a GS segment.
Enforcement
GsSegment.Build / GsSegment.Fill
Outcome
X12-compliant functional group header.
Source
Common\SAIF.Common.Files\Edi\Segments\GsSegment.cs
BR-041 ST and SE control numbers zero-padded to four digits
Field
Value
Statement
ST and SE transaction-set control numbers are zero-padded to at least four digits, preserving longer values.
Trigger
Building an ST or SE segment.
Enforcement
StSegment.Build, SeSegment.Build (len = ControlNumber.ToString().Length; if (len < 4) len = 4;)
Outcome
Control numbers match between ST and SE.
Source
Common\SAIF.Common.Files\Edi\Segments\StSegment.cs, Common\SAIF.Common.Files\Edi\Segments\SeSegment.cs
BR-042 AK2 control number zero-padded to four digits
Field
Value
Statement
The AK2 transaction-set control number is zero-padded to four digits.
Trigger
Building an AK2 segment.
Enforcement
Ak2Segment.Build (PadLeft(4, '0'))
Outcome
Acknowledgement references the original control number format.
Source
Common\SAIF.Common.Files\Edi\Segments\Ak2Segment.cs
BR-043 IEA control number emitted as nine digits
Field
Value
Statement
The IEA interchange control number is emitted as exactly nine digits.
Trigger
Building an IEA segment.
Enforcement
IeaSegment.Build (ToString("D9"))
Outcome
Matches the ISA control number format (BR-038 ).
Source
Common\SAIF.Common.Files\Edi\Segments\IeaSegment.cs
BR-044 BHT original vs reissue flag
Field
Value
Statement
A BHT transaction is flagged 00 when it is an original submission and 08 otherwise; on read, only 00 sets IsOriginal.
Trigger
Building/filling a BHT segment.
Enforcement
BhtSegment.Build / BhtSegment.Fill (element 2)
Outcome
Original vs. reissue distinction preserved.
Source
Common\SAIF.Common.Files\Edi\Segments\BhtSegment.cs
Field
Value
Statement
When no DTP format is supplied, the format defaults to D8 for a single date and RD8 for a date range; format TM writes a time value instead of a date.
Trigger
Building a DTP segment.
Enforcement
DtpSegment.Build
Outcome
Correct X12 date/time format qualifier.
Source
Common\SAIF.Common.Files\Edi\Segments\DtpSegment.cs
Field
Value
Statement
DTP values are interpreted by their format qualifier: RD8 splits a start/end range on -, D8 is a single date, DT is date + time in one string, and TM yields DateTime.MinValue with the raw time retained as a string.
Trigger
Filling a DTP segment.
Enforcement
DtpSegment.Fill switch
Outcome
Format-appropriate parsing.
Source
Common\SAIF.Common.Files\Edi\Segments\DtpSegment.cs
BR-047 NM1 person vs organization name layout
Field
Value
Statement
An NM1 entity is a person when entity type is 1: person names emit last, first and optional middle/prefix/suffix; all other entity types emit a single organization name.
Trigger
Building/filling an NM1 segment.
Enforcement
Nm1Segment.Build / Nm1Segment.Fill (IsForPerson = (EntityType == "1"))
Outcome
Person vs. organization name layout.
Source
Common\SAIF.Common.Files\Edi\Segments\Nm1Segment.cs
BR-048 NM1 complete name composition
Field
Value
Statement
A person's display name is composed as Last + Suffix + ", " + First + " " + Middle; an organization's display name is the organization name.
Trigger
Filling an NM1 segment.
Enforcement
Nm1Segment.Fill (CompleteName)
Outcome
Derived CompleteName.
Source
Common\SAIF.Common.Files\Edi\Segments\Nm1Segment.cs
BR-049 N4 postal code split into ZIP and extension
Field
Value
Statement
A postal code longer than five characters is split into a five-digit ZIP and the remainder as the ZIP extension.
Trigger
Filling an N4 segment.
Enforcement
N4Segment.Fill (element 3)
Outcome
ZipCode / ZipCodeExtension separated; written back concatenated in Build.
Source
Common\SAIF.Common.Files\Edi\Segments\N4Segment.cs
BR-050 CTX amounts scaled to cents CAS amounts unscaled
Field
Value
Statement
CTX monetary amounts are exchanged in cents: written as truncate(amount × 100) and read back divided by 100. CAS amounts are exchanged unscaled.
Trigger
Building/filling a CTX or CAS segment.
Enforcement
CtxSegment.Build / CtxSegment.Fill; CasSegment.Build / CasSegment.Fill
Outcome
Scaled vs. unscaled amounts.
Source
Common\SAIF.Common.Files\Edi\Segments\CtxSegment.cs, Common\SAIF.Common.Files\Edi\Segments\CasSegment.cs
BR-051 SVC adjudication suppression rules
Field
Value
Statement
In an SVC adjudication segment: the revenue code is suppressed when the adjudicated procedure qualifier is NU; the adjudicated quantity is omitted when it equals 1 and defaults to 1 when absent; the billed procedure is emitted only when it differs from the adjudicated procedure; and the billed quantity is emitted only when it differs from the adjudicated quantity, defaulting to it when absent.
Trigger
Building/filling an SVC segment.
Enforcement
SvcSegment.Build / SvcSegment.Fill (comparison via CompositeProcedureCodeElement.Equals)
Outcome
Minimal, non-redundant SVC output.
Source
Common\SAIF.Common.Files\Edi\Segments\SvcSegment.cs, Common\SAIF.Common.Files\Edi\Segments\CompositeProcedureCodeElement.cs
BR-052 HL child level indicator
Field
Value
Statement
An HL level reports child levels via element 4: an explicit child code is written when supplied, otherwise 1/0 derived from the child-exists flag; on read, ChildExists is true only when the child code is 1.
Trigger
Building/filling an HL segment.
Enforcement
HlSegment.Build / HlSegment.Fill
Outcome
Hierarchy child indicator.
Source
Common\SAIF.Common.Files\Edi\Segments\HlSegment.cs
BR-053 IK5 acknowledgement or reject response codes
Field
Value
Statement
A functional acknowledgement reports A to accept and R to reject.
Trigger
Ik5Segment.Acknowledgement() / Reject().
Enforcement
Ik5Segment.Acknowledgement, Ik5Segment.Reject
Outcome
IK5 segment with response code A or R.
Source
Common\SAIF.Common.Files\Edi\Segments\Ik5Segment.cs
BR-054 DMG HI SV1 SV2 SV3 are inbound-only segments
Field
Value
Statement
The DMG, HI, SV1, SV2 and SV3 segments are inbound-only and cannot be serialised.
Trigger
Calling Build() on those types.
Enforcement
DmgSegment.Build, HiSegment.Build, Sv1Segment.Build, Sv2Segment.Build, Sv3Segment.Build
Outcome
NotImplementedException
Source
Common\SAIF.Common.Files\Edi\Segments\DmgSegment.cs, Common\SAIF.Common.Files\Edi\Segments\HiSegment.cs, Common\SAIF.Common.Files\Edi\Segments\Sv1Segment.cs, Common\SAIF.Common.Files\Edi\Segments\Sv2Segment.cs, Common\SAIF.Common.Files\Edi\Segments\Sv3Segment.cs
BR-055 Generated EDI file name pattern
Field
Value
Statement
Generated EDI file names follow {yyyyMMddHHmmss}_SAIF_{P\|T}_{fileType}.txt, where P marks production and T marks test.
Trigger
NameBuilder.GetFileName(fileType, isProd).
Enforcement
NameBuilder.GetFileName
Outcome
Environment-tagged, timestamped file name.
Source
Common\SAIF.Common.Files\Edi\NameBuilder.cs
BR-056 Two-digit EDI years interpreted as 21st century
Field
Value
Statement
Two-digit EDI years are always interpreted as 21st-century dates (prefixed with 20); no 20th-century handling exists.
Trigger
Converting any EDI date.
Enforcement
DateMaker.MakeDateTime (documented in the method's <comments> block)
Outcome
20yy dates.
Source
Common\SAIF.Common.Files\Edi\Core\DateMaker.cs
BR-057 EDI time value right-padded before conversion
Field
Value
Statement
An EDI time value is right-padded with zeros to HHmmss before conversion, so partial times default their missing components to zero.
Trigger
Converting an EDI date-time.
Enforcement
DateMaker.MakeDateTime (time.PadRight(6, '0'))
Outcome
Deterministic time component.
Source
Common\SAIF.Common.Files\Edi\Core\DateMaker.cs
Field
Value
Statement
An EDI date range is expressed as yyyyMMdd-yyyyMMdd with - as the separator; a single date omits the separator and the second date.
Trigger
Writing/reading a date range.
Enforcement
DateMaker.EdiFileDateString, DateMaker.ExtractDateRange (DateSeperator = '-', DateFormat = "yyyyMMdd")
Outcome
D8 / RD8 compatible values.
Source
Common\SAIF.Common.Files\Edi\Core\DateMaker.cs
BR-059 Optional segment elements written only when populated
Field
Value
Statement
Optional segment elements are written only when populated: ST03 version reference, TRN03/TRN04, CLP05 patient responsibility and CLP09 frequency type, NM105–NM109, and CAS/CTX reason-code triplets with an empty reason code.
Trigger
Building those segments.
Enforcement
StSegment.Build, TrnSegment.Build, ClpSegment.Build, Nm1Segment.Build, CasSegment.Build, CtxSegment.Build (guards use IsNullOrEmpty/IsNull; Origin: SAIF.Framework.Common string/generic extensions)
Outcome
Absent optional elements rather than empty ones.
Source
Common\SAIF.Common.Files\Edi\Segments\StSegment.cs, Common\SAIF.Common.Files\Edi\Segments\TrnSegment.cs, Common\SAIF.Common.Files\Edi\Segments\ClpSegment.cs, Common\SAIF.Common.Files\Edi\Segments\Nm1Segment.cs, Common\SAIF.Common.Files\Edi\Segments\CasSegment.cs, Common\SAIF.Common.Files\Edi\Segments\CtxSegment.cs
BR-060 SV1 emergency indicator conditions
Field
Value
Statement
An SV1 service line is flagged as an emergency only when element 9 is exactly Y, and only when the segment actually carries more than eight elements.
Trigger
Filling an SV1 segment.
Enforcement
Sv1Segment.Fill
Outcome
EmergencyIndicator set.
Source
Common\SAIF.Common.Files\Edi\Segments\Sv1Segment.cs
BR-061 CAS and CTX adjustment triplets
Field
Value
Statement
CAS and CTX adjustments are repeating triplets of (reason code, amount, quantity) starting at element 2; the count is derived as floor((elementCount + 1) / 3) and the quantity position is deliberately not implemented.
Trigger
Building/filling a CAS or CTX segment.
Enforcement
CasSegment.Build/Fill, CtxSegment.Build/Fill
Outcome
Up to six adjustment triplets per segment*; quantity always ignored.
Source
Common\SAIF.Common.Files\Edi\Segments\CasSegment.cs, Common\SAIF.Common.Files\Edi\Segments\CtxSegment.cs
BR-062 Procedure composite equality excludes description
Field
Value
Statement
A service procedure code composite carries qualifier, code and up to four modifier codes; two composites are considered equal when qualifier, code and all four modifiers match (description is excluded from the comparison).
Trigger
Comparing or building a procedure composite.
Enforcement
CompositeProcedureCodeElement.BuildElement, Equals; SvSegmentBase.BuildElement, FillServiceCode
Outcome
Equality drives SVC billed-vs-adjudicated suppression (BR-051 ).
Source
Common\SAIF.Common.Files\Edi\Segments\CompositeProcedureCodeElement.cs, Common\SAIF.Common.Files\Edi\Segments\SvSegmentBase.cs
Notes
Rule BR-061 is marked inferred (*) because the "up to six triplets" figure is derived from the element-count formula rather than an explicit constant in source.
No rule on this page is enforced by an inherited BOF/NHibernate base class; all enforcement is local to SAIF.Framework.Common.Files.
Note: Statements marked with * were inferred from code structure, naming
conventions, or contextual evidence where direct confirmation was not available
in source artifacts.
Sources
Common\SAIF.Common.Files\Core\FileReader.cs
Common\SAIF.Common.Files\Core\FileWriter.cs
Common\SAIF.Common.Files\Core\TabDelimitedRecord.cs
Common\SAIF.Common.Files\Core\Record.cs
Common\SAIF.Common.Files\Core\Configurations\FileRecordLayout.cs
Common\SAIF.Common.Files\Core\Configurations\FileLayoutBuilder.cs
Common\SAIF.Common.Files\Edi\Core\Readers\EdiFileReader.cs
Common\SAIF.Common.Files\Edi\Core\Writers\EdiFileWriter.cs
Common\SAIF.Common.Files\Edi\Core\Parsers\EdiSegmentParser.cs
Common\SAIF.Common.Files\Edi\Core\Parsers\EdiDataElementParser.cs
Common\SAIF.Common.Files\Edi\Core\Parsers\EdiCompositeDataElementParser.cs
Common\SAIF.Common.Files\Edi\Core\Parsers\EdiGroupParser.cs
Common\SAIF.Common.Files\Edi\Core\Builders\SegmentBuilder.cs
Common\SAIF.Common.Files\Edi\Core\Builders\EdiRecordBuilder.cs
Common\SAIF.Common.Files\Edi\Core\DateMaker.cs
Common\SAIF.Common.Files\Edi\EdiFile.cs
Common\SAIF.Common.Files\Edi\EdiCompositeDataElement.cs
Common\SAIF.Common.Files\Edi\EdiDataElement.cs
Common\SAIF.Common.Files\Edi\Segments\IsaSegment.cs
Common\SAIF.Common.Files\Edi\Segments\GsSegment.cs
Common\SAIF.Common.Files\Edi\Segments\StSegment.cs
Common\SAIF.Common.Files\Edi\Segments\SeSegment.cs
Common\SAIF.Common.Files\Edi\Segments\Ak2Segment.cs
Common\SAIF.Common.Files\Edi\Segments\IeaSegment.cs
Common\SAIF.Common.Files\Edi\Segments\BhtSegment.cs
Common\SAIF.Common.Files\Edi\Segments\DtpSegment.cs
Common\SAIF.Common.Files\Edi\Segments\Nm1Segment.cs
Common\SAIF.Common.Files\Edi\Segments\N4Segment.cs
Common\SAIF.Common.Files\Edi\Segments\CtxSegment.cs
Common\SAIF.Common.Files\Edi\Segments\CasSegment.cs
Common\SAIF.Common.Files\Edi\Segments\SvcSegment.cs
Common\SAIF.Common.Files\Edi\Segments\CompositeProcedureCodeElement.cs
Common\SAIF.Common.Files\Edi\Segments\HlSegment.cs
Common\SAIF.Common.Files\Edi\Segments\Ik5Segment.cs
Common\SAIF.Common.Files\Edi\Segments\DmgSegment.cs
Common\SAIF.Common.Files\Edi\Segments\HiSegment.cs
Common\SAIF.Common.Files\Edi\Segments\Sv1Segment.cs
Common\SAIF.Common.Files\Edi\Segments\Sv2Segment.cs
Common\SAIF.Common.Files\Edi\Segments\Sv3Segment.cs
Common\SAIF.Common.Files\Edi\NameBuilder.cs
Common\SAIF.Common.Files\Edi\Segments\TrnSegment.cs
Common\SAIF.Common.Files\Edi\Segments\ClpSegment.cs
Common\SAIF.Common.Files\Edi\Segments\SvSegmentBase.cs