Skip to content

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

BR-003 Requested format must match a declared configuration

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

BR-006 Header record skipped when declared

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

BR-009 Header field must have a property or title

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

BR-045 DTP format defaults

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

BR-046 DTP values interpreted by format qualifier

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

BR-058 EDI date range format

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