public SqlTransactionRepository(string dsn, ISpecificationFinder specFinder, string[] indexedSegments, string schema = "dbo", string commonSchema = "dbo", int segmentBatchSize = 1000, string sqlDateType = "date") : base(dsn, schema) { _commonDb = new DbCreation <T>(dsn, commonSchema, sqlDateType); _transactionDb = new DbCreation <T>(dsn, schema, sqlDateType); _schemaEnsured = false; _batchSize = segmentBatchSize; _segmentBatch = new SegmentBatch <T>(this); _specs = new Dictionary <string, SegmentSpecification>(); foreach (var segmentId in indexedSegments) { var spec = specFinder.FindSegmentSpec("5010", segmentId.Trim()); _specs.Add(segmentId.Trim(), spec); } }
/// <summary> /// Initializes a new instance of the <see cref="SqlTransactionRepository"/> class /// </summary> /// <param name="dsn">Data source information</param> /// <param name="specFinder">Specification finder for data structure information</param> /// <param name="indexedSegments">Segments stored in database</param> /// <param name="identityType">Identity type</param> /// <param name="schema">Database schema for data access</param> /// <param name="commonSchema">Common database schema</param> /// <param name="segmentBatchSize">Number of segments to pull from database at a time</param> /// <param name="sqlDateType">"Date" type used by database</param> public SqlTransactionRepository( string dsn, ISpecificationFinder specFinder, string[] indexedSegments, Type identityType, string schema = "dbo", string commonSchema = "dbo", int segmentBatchSize = 1000, string sqlDateType = "date") : base(dsn, identityType, schema) { this.CommonDb = new DbCreation(dsn, commonSchema, identityType, sqlDateType); this.TransactionDb = new DbCreation(dsn, schema, identityType, sqlDateType); this.idProvider = this.GetIdProvider(dsn, commonSchema, identityType, segmentBatchSize / 10); this.schemaEnsured = false; this.batchSize = segmentBatchSize; this.SegmentBatch = new SegmentBatch(this, identityType); this.specs = new Dictionary <string, SegmentSpecification>(); foreach (var segmentId in indexedSegments) { var spec = specFinder.FindSegmentSpec("5010", segmentId.Trim()); this.specs.Add(segmentId.Trim(), spec); } }
protected virtual TransactionSetResponse AcknowledgeTransaction(X12StreamReader reader, string functionalCode, string versionIdentifierCode, string transaction) { string[] stElements = reader.SplitSegment(transaction); var response = new TransactionSetResponse { TransactionSetIdentifierCode = stElements[1], TransactionSetControlNumber = stElements[2] }; if (stElements.Length >= 4) { response.ImplementationConventionReference = stElements[3]; } var transactionSpec = _specFinder.FindTransactionSpec(functionalCode, versionIdentifierCode, response.TransactionSetIdentifierCode); if (transactionSpec == null) { response.SyntaxErrorCodes.Add("1"); // Transaction Set Not Supported response.AcknowledgmentCode = AcknowledgmentCodeEnum.R_Rejected; return(response); } #region Validate against transaction specification Stack <ContainerInformation> containers = new Stack <ContainerInformation>(); var transactionContainer = new ContainerInformation { Spec = transactionSpec }; containers.Push(transactionContainer); List <SegmentInformation> segmentInfos = new List <SegmentInformation>(); string[] segments = transaction.Split(new char[] { reader.Delimiters.SegmentTerminator }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < segments.Length; i++) { string[] elements = segments[i].Split(reader.Delimiters.ElementSeparator); var segmentInfo = new SegmentInformation { SegmentId = elements[0], SegmentPosition = i + 1, Elements = elements }; segmentInfo.Spec = _specFinder.FindSegmentSpec(versionIdentifierCode, segmentInfo.SegmentId); segmentInfos.Add(segmentInfo); ContainerInformation currentContainer = containers.Peek(); switch (segmentInfo.SegmentId) { case "ST": case "SE": segmentInfo.LoopId = ""; transactionContainer.Segments.Add(segmentInfo); break; case "HL": string hlNumber = segmentInfo.Elements[1]; string hlParentNumber = segmentInfo.Elements[2]; string hlLevelCode = segmentInfo.Elements[3]; var hlSpec = transactionSpec.HierarchicalLoopSpecifications.FirstOrDefault(hls => hls.LevelCode == hlLevelCode); if (hlSpec != null) { while (!(containers.Peek().Spec is TransactionSpecification)) { if (containers.Peek().HLoopNumber == hlParentNumber) { break; } containers.Pop(); } segmentInfo.LoopId = hlSpec.LoopId; var hlContainer = new ContainerInformation { Spec = hlSpec, HLoopNumber = hlNumber }; hlContainer.Segments.Add(segmentInfo); containers.Peek().Containers.Add(hlContainer); containers.Push(hlContainer); } else { response.SegmentErrors.Add(CreateDataElementError(segmentInfo, 3, "I6", hlLevelCode)); //Code Value Not Used in Implementation response.AcknowledgmentCode = AcknowledgmentCodeEnum.X_Rejected_ContentCouldNotBeAnalyzed; return(response); // end validation if HL cannot be recognized since hl spec will not be available } break; default: bool matchFound = false; do { var matchingLoopSpecs = currentContainer.Spec.LoopSpecifications.Where(ls => ls.StartingSegment.SegmentId == segmentInfo.SegmentId).ToList(); if (matchingLoopSpecs.Count > 0) { IContainerSpecification matchingLoopSpec = null; if (matchingLoopSpecs.Count == 1) { matchingLoopSpec = matchingLoopSpecs.First(); } else { string entityCode = elements[1]; matchingLoopSpec = matchingLoopSpecs.FirstOrDefault(ls => ls.StartingSegment.EntityIdentifiers.Exists(ei => ei.Code == entityCode)); } if (matchingLoopSpec != null) { segmentInfo.LoopId = matchingLoopSpec.LoopId; var loopContainer = new ContainerInformation { Spec = matchingLoopSpec }; loopContainer.Segments.Add(segmentInfo); containers.Peek().Containers.Add(loopContainer); containers.Push(loopContainer); matchFound = true; } else { response.SegmentErrors.Add(CreateSegmentError(segmentInfo, "6")); //Segment Not in Defined Transaction Set response.AcknowledgmentCode = AcknowledgmentCodeEnum.X_Rejected_ContentCouldNotBeAnalyzed; return(response); } } else if (currentContainer.Spec.SegmentSpecifications.Exists(ss => ss.SegmentId == segmentInfo.SegmentId)) { segmentInfo.LoopId = currentContainer.Spec.LoopId; currentContainer.Segments.Add(segmentInfo); matchFound = true; } else { if (currentContainer.Spec is TransactionSpecification) { response.SegmentErrors.Add(CreateSegmentError(segmentInfo, "2")); // Unexpected segment response.AcknowledgmentCode = AcknowledgmentCodeEnum.X_Rejected_ContentCouldNotBeAnalyzed; return(response); // end validation if unrecognized segment encountered (cannot guarantee we are pointing at correct container) } else { containers.Pop(); currentContainer = containers.Peek(); } } } while (!matchFound); break; } response.SegmentErrors.AddRange(ValidateSegmentAgainstSpec(segmentInfo)); } response.SegmentErrors.AddRange(ValidateContainerAgainstSpec(transactionContainer)); #endregion #region Validate transaction trailer var trailerSegment = segmentInfos.FirstOrDefault(si => si.SegmentId == "SE"); if (trailerSegment == null) { response.SyntaxErrorCodes.Add("2"); //Transaction Set Trailer Missing } else { if (trailerSegment.Elements.Length <= 2 || trailerSegment.Elements[2] != response.TransactionSetControlNumber) { response.SyntaxErrorCodes.Add("3"); // Transaction Set Control Number in Header and Trailer Do Not Match } if (trailerSegment.Elements.Length >= 2) { int segmentCount; int.TryParse(trailerSegment.Elements[1], out segmentCount); if (segmentCount != segmentInfos.Count) { response.SyntaxErrorCodes.Add("4"); // Number of Included Segments Does Not Match Actual Count } } else { response.SyntaxErrorCodes.Add("4"); // Number of Included Segments Does Not Match Actual Count } } #endregion if (response.SegmentErrors.Count > 0 || response.SyntaxErrorCodes.Count > 0) { if (response.SegmentErrors.Count > 0) { response.SyntaxErrorCodes.Add("5"); //One or More Segments in Error } if (response.AcknowledgmentCode == AcknowledgmentCodeEnum.A_Accepted) { response.AcknowledgmentCode = AcknowledgmentCodeEnum.E_Accepted_ButErrorsWereNoted; } } return(response); }