///<summary>Set x835 to view all x835.ListClaims info. Otherwise set claimPaid to a specific Hx835_Claim to view.</summary>
 public FormEtrans835Print(X835 x835, Hx835_Claim claimPaid = null)
 {
     InitializeComponent();
     Lan.F(this);
     _x835      = x835;
     _claimPaid = claimPaid;
 }
Beispiel #2
0
        private void FormEtrans835Edit_Load(object sender, EventArgs e)
        {
            if (_form835 != null && !_form835.IsDisposed)
            {
                if (!MsgBox.Show(this, true, "Opening another ERA will close the current ERA you already have open.  Continue?"))
                {
                    //Form already exists and user wants to keep current instance.
                    TranSetId835   = _form835.TranSetId835;
                    EtransCur      = _form835.EtransCur;
                    MessageText835 = _form835.MessageText835;
                }
                _form835.Close();     //Always close old form and open new form, so the new copy will come to front, since BringToFront() does not always work.
            }
            _form835 = this;          //Set the static variable to this form because we're always going to show this form even if they're viewing old information.
            List <Etrans835Attach> listAttached = Etrans835Attaches.GetForEtrans(EtransCur.EtransNum);

            _x835 = new X835(EtransCur, MessageText835, TranSetId835, listAttached);
            RefreshFromDb();
            FillAll();
            Menu.MenuItemCollection menuItemCollection = new Menu.MenuItemCollection(gridClaimDetailsMenu);
            List <MenuItem>         listMenuItems      = new List <MenuItem>();

            listMenuItems.Add(new MenuItem(Lan.g(this, "Go to Account"), new EventHandler(gridClaimDetails_RightClickHelper)));
            listMenuItems.Add(new MenuItem(Lan.g(this, "Add Tracking Status"), new EventHandler(gridClaimDetails_RightClickHelper)));          //Enabled by default
            menuItemCollection.AddRange(listMenuItems.ToArray());
            gridClaimDetails.ContextMenu          = gridClaimDetailsMenu;
            gridClaimDetails.AllowSortingByColumn = true;
        }
Beispiel #3
0
 ///<summary>Returns if given claim is already recieved. Currently ERA test do not consider supplemental.</summary>
 public static void TryEnterPayment(X835 x835, Hx835_Claim claimPaid, Claim claim, bool isAutomatic)
 {
     if (claim.ClaimStatus == "R")           //Currently we do not have test for supplemental payments.
     {
         return;
     }
     EtransL.ImportEraClaimData(x835, claimPaid, claim, isAutomatic);
 }
Beispiel #4
0
        public void SetupTest()
        {
            #region Create Patient and claim: Justin Smith
            Patient patJustinSmith = PatientT.CreatePatient(lName: "Smith", fName: "Justin");
            List <EraTestProcCodeData> listProcData = new List <EraTestProcCodeData>();
            listProcData.Add(new EraTestProcCodeData("D0120", ProcStat.TP, 43, new DateTime(2017, 09, 26)));
            listProcData.Add(new EraTestProcCodeData("D1110", ProcStat.TP, 110, new DateTime(2017, 09, 26)));
            listProcData.Add(new EraTestProcCodeData("D0602", ProcStat.TP, 5, new DateTime(2017, 09, 26)));
            _claimPrimaryJustinSmith = EtransT.SetupEraClaim(patJustinSmith, listProcData, "P", "217308827", out List <InsuranceInfo> _listJustinSmithInsuranceInfo);
            #endregion
            #region Create Patient and claim: Jacob Jones
            Patient patJacobJones = PatientT.CreatePatient(lName: "Jones", fName: "Jacob");
            listProcData.Clear();
            listProcData.Add(new EraTestProcCodeData("D0120", ProcStat.TP, 43, new DateTime(2017, 09, 26)));
            listProcData.Add(new EraTestProcCodeData("D1110", ProcStat.TP, 110, new DateTime(2017, 09, 26)));
            listProcData.Add(new EraTestProcCodeData("D1206", ProcStat.TP, 68, new DateTime(2017, 09, 26)));
            _claimPrimaryJacobJones = EtransT.SetupEraClaim(patJacobJones, listProcData, "P", "217180995", out List <InsuranceInfo> _listJacobJonesInsuranceInfo);
            #endregion
            #region Create Patient and claim: Stephanie Mayer
            Patient patStephanieMayer = PatientT.CreatePatient(lName: "Mayer", fName: "Stephanie");
            listProcData.Clear();
            listProcData.Add(new EraTestProcCodeData("D0120", ProcStat.TP, 43, new DateTime(2017, 09, 26)));
            listProcData.Add(new EraTestProcCodeData("D1110", ProcStat.TP, 110, new DateTime(2017, 09, 26)));
            listProcData.Add(new EraTestProcCodeData("D0602", ProcStat.TP, 5, new DateTime(2017, 09, 26)));
            listProcData.Add(new EraTestProcCodeData("D1206", ProcStat.TP, 68, new DateTime(2017, 09, 26)));
            _claimPrimaryStephanieMayer = EtransT.SetupEraClaim(patStephanieMayer, listProcData, "P", "217439125", out List <InsuranceInfo> _listStephanieMayerInsuranceInfo);
            #endregion
            //Create and insert etrans entry
            Etrans etrans835 = EtransT.Insert835Etrans(Properties.Resources.JustinSmithERA, new DateTime(2017, 09, 30));       //Spoof etrans imported 4 days after claim sent.
            List <ODTuple <Patient, long> > listPats = new List <ODTuple <Patient, long> >()
            {
                new ODTuple <Patient, long>(patJustinSmith, _claimPrimaryJustinSmith.ClaimNum),
                new ODTuple <Patient, long>(patJacobJones, _claimPrimaryJacobJones.ClaimNum),
                new ODTuple <Patient, long>(patStephanieMayer, _claimPrimaryStephanieMayer.ClaimNum)
            };
            _x835 = EtransT.Construct835(etrans835, Properties.Resources.JustinSmithERA, listPats, out _listEtrans835Attaches);
            foreach (Hx835_Claim eraClaim in _x835.ListClaimsPaid)
            {
                switch (eraClaim.PatientName.Fname.ToLower())
                {
                case "justin":
                    _eraJustinSmithClaim = eraClaim;
                    break;

                case "jacob":
                    _eraJacobJonesClaim = eraClaim;
                    break;

                case "stephanie":
                    _eraStephanieMayerClaim = eraClaim;
                    break;
                }
            }
        }
Beispiel #5
0
        private void butPrint_Click(object sender, EventArgs e)
        {
            Sheet sheet = SheetUtil.CreateSheet(SheetDefs.GetInternalOrCustom(SheetInternalType.ERA));
            X835  x835  = _x835.Copy();

            x835.ListClaimsPaid = new List <Hx835_Claim>()
            {
                _claimPaid
            };                                                                                      //Only print the current claim.
            SheetParameter.GetParamByName(sheet.Parameters, "ERA").ParamValue = x835;               //Required param
            SheetParameter.GetParamByName(sheet.Parameters, "IsSingleClaimPaid").ParamValue = true; //Value is null if not set
            SheetFiller.FillFields(sheet);
            SheetPrinting.Print(sheet, isPreviewMode: true);
        }
Beispiel #6
0
        ///<summary>Builds the X835 for given etrans835 and etransMessageText.
        ///Also attempts to create attaches for patients in listPatients using their first/last name and the claim num in their tuple entry.</summary>
        public static X835 Construct835(Etrans etrans835, string etransMessageText, List <ODTuple <Patient, long> > listPatients, out List <Etrans835Attach> listEtrans835Attaches)
        {
            listEtrans835Attaches = new List <Etrans835Attach>();
            //Construct the inital X835 so that we can find the ERA claim we are testing against, needed for attach information.
            X835 x835 = new X835(etrans835, etransMessageText, etrans835.TranSetId835);

            foreach (ODTuple <Patient, long> data in listPatients)
            {
                Patient pat      = data.Item1;
                long    claimNum = data.Item2;
                //Then using that ERA claim we will spoof the Etrans835Attach logic that would run when associating an OD claim to the ERA claim.
                Hx835_Claim eraClaim = x835.ListClaimsPaid.First(x => x.PatientName.Fname.ToLower() == pat.FName.ToLower() && x.PatientName.Lname.ToLower() == pat.LName.ToLower());
                //Spoof ERA claim attachement.
                Etrans835Attach attach = Insert835Attach(etrans835.EtransNum, claimNum, eraClaim.ClpSegmentIndex, etrans835.DateTimeTrans);
                listEtrans835Attaches.Add(attach);
            }
            //Finally we must reconstruct the X835 with the new spoofed attach.
            return(new X835(etrans835, etransMessageText, etrans835.TranSetId835, listEtrans835Attaches));
        }
Beispiel #7
0
        ///<summary>Fills grid based on values in _listEtrans.
        ///Set isRefreshNeeded to true when we need to reinitialize local dictionarys after in memory list is also updated. Required true for first time running.
        ///Also allows you to passed in predetermined filter options.</summary>
        private void FillGrid(bool isRefreshNeeded, List <string> listSelectedStatuses, List <long> listSelectedClinicNums,
                              string carrierName, string checkTraceNum, string amountMin, string amountMax, string controlId)
        {
            Cursor = Cursors.WaitCursor;
            labelControlId.Visible = PrefC.GetBool(PrefName.EraShowControlIdFilter);
            textControlId.Visible  = PrefC.GetBool(PrefName.EraShowControlIdFilter);
            Action actionCloseProgress = null;

            if (isRefreshNeeded)
            {
                actionCloseProgress = ODProgress.Show(ODEventType.Etrans, typeof(EtransEvent), Lan.g(this, "Gathering data") + "...");
                _dictEtrans835s.Clear();
                _dictEtransClaims.Clear();
                List <Etrans835Attach>    listAttached        = Etrans835Attaches.GetForEtrans(_listAllEtrans.Select(x => x.EtransNum).ToArray());
                Dictionary <long, string> dictEtransMessages  = new Dictionary <long, string>();
                List <X12ClaimMatch>      list835ClaimMatches = new List <X12ClaimMatch>();
                Dictionary <long, int>    dictClaimMatchCount = new Dictionary <long, int>(); //1:1 with _listEtranss. Stores how many claim matches each 835 has.
                int batchQueryInterval = 500;                                                 //Every 500 rows we get the next 500 message texts to save memory.
                int rowCur             = 0;
                foreach (Etrans etrans in _listAllEtrans)
                {
                    if (rowCur % batchQueryInterval == 0)
                    {
                        int range = Math.Min(batchQueryInterval, _listAllEtrans.Count - rowCur);                   //Either the full batchQueryInterval amount or the remaining amount of etrans.
                        dictEtransMessages = EtransMessageTexts.GetMessageTexts(_listAllEtrans.GetRange(rowCur, range).Select(x => x.EtransMessageTextNum).ToList(), false);
                    }
                    rowCur++;
                    EtransEvent.Fire(ODEventType.Etrans, Lan.g(this, "Processing 835: ") + ": " + rowCur + " out of " + _listAllEtrans.Count);
                    List <Etrans835Attach> listAttachedTo835 = listAttached.FindAll(x => x.EtransNum == etrans.EtransNum);
                    X835 x835 = new X835(etrans, dictEtransMessages[etrans.EtransMessageTextNum], etrans.TranSetId835, listAttachedTo835, true);
                    _dictEtrans835s.Add(etrans.EtransNum, x835);
                    List <X12ClaimMatch> listClaimMatches = x835.GetClaimMatches();
                    dictClaimMatchCount.Add(etrans.EtransNum, listClaimMatches.Count);
                    list835ClaimMatches.AddRange(listClaimMatches);
                }
                #region Set 835 unattached in batch and build _dictEtransClaims and _dictClaimPayCheckNums.
                EtransEvent.Fire(ODEventType.Etrans, Lan.g(this, "Gathering internal claim matches."));
                List <long> listClaimNums = Claims.GetClaimFromX12(list835ClaimMatches);             //Can return null.
                EtransEvent.Fire(ODEventType.Etrans, Lan.g(this, "Building data sets."));
                int         claimIndexCur        = 0;
                List <long> listMatchedClaimNums = new List <long>();
                foreach (Etrans etrans in _listAllEtrans)
                {
                    X835 x835 = _dictEtrans835s[etrans.EtransNum];
                    if (listClaimNums != null)
                    {
                        x835.SetClaimNumsForUnattached(listClaimNums.GetRange(claimIndexCur, dictClaimMatchCount[etrans.EtransNum]));
                    }
                    claimIndexCur += dictClaimMatchCount[etrans.EtransNum];
                    listMatchedClaimNums.AddRange(x835.ListClaimsPaid.FindAll(x => x.ClaimNum != 0).Select(x => x.ClaimNum).ToList());
                }
                List <Claim> listClaims = Claims.GetClaimsFromClaimNums(listMatchedClaimNums.Distinct().ToList());
                //The following line includes manually detached and split attaches.
                _listAllAttaches   = Etrans835Attaches.GetForEtransNumOrClaimNums(false, _listAllEtrans.Select(x => x.EtransNum).ToList(), listMatchedClaimNums.ToArray());
                _listAllClaimProcs = ClaimProcs.RefreshForClaims(listMatchedClaimNums);
                foreach (Etrans etrans in _listAllEtrans)
                {
                    X835 x835 = _dictEtrans835s[etrans.EtransNum];
                    #region _dictEtransClaims, _dictClaimPayCheckNums
                    _dictEtransClaims.Add(etrans.EtransNum, new List <Claim>());
                    List <long>  listSubClaimNums = x835.ListClaimsPaid.FindAll(x => x.ClaimNum != 0).Select(y => y.ClaimNum).ToList();
                    List <Claim> listClaimsFor835 = listClaims.FindAll(x => listSubClaimNums.Contains(x.ClaimNum));
                    foreach (Hx835_Claim claim in x835.ListClaimsPaid)
                    {
                        Claim claimCur = listClaimsFor835.FirstOrDefault(x => x.ClaimNum == claim.ClaimNum);                    //Can be null.
                        _dictEtransClaims[etrans.EtransNum].Add(claimCur);
                    }
                    #endregion
                }
                EtransEvent.Fire(ODEventType.Etrans, Lan.g(this, "Filling Grid."));
                #endregion
            }
            gridMain.BeginUpdate();
            #region Initilize columns
            gridMain.ListGridColumns.Clear();
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Patient Name"), 250));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Carrier Name"), 190));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Status"), 80));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Date"), 80, GridSortingStrategy.DateParse));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Amount"), 80, GridSortingStrategy.AmountParse));
            if (PrefC.HasClinicsEnabled)
            {
                gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Clinic"), 70));
            }
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Code"), 37, HorizontalAlignment.Center));
            if (PrefC.GetBool(PrefName.EraShowControlIdFilter))
            {
                gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "ControlID"), -1));
            }
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableEtrans835s", "Note"), -2));
            #endregion
            gridMain.ListGridRows.Clear();
            foreach (Etrans etrans in _listAllEtrans)
            {
                X835 x835 = _dictEtrans835s[etrans.EtransNum];
                #region Filter: Carrier Name
                if (carrierName != "" && !x835.PayerName.ToLower().Contains(carrierName.ToLower().Trim()))
                {
                    continue;
                }
                #endregion
                string status = GetStringStatus(etrans.EtransNum);
                #region Filter: Status
                if (!listSelectedStatuses.Contains(status.Replace("*", "")))                //The filter will ignore finalized with detached claims.
                {
                    continue;
                }
                #endregion
                //List of ClinicNums for the current etrans.ListClaimsPaid from the DB.
                List <long> listClinicNums = _dictEtransClaims[etrans.EtransNum].Select(x => x == null? 0 :x.ClinicNum).Distinct().ToList();
                #region Filter: Clinics
                if (PrefC.HasClinicsEnabled && !listClinicNums.Exists(x => listSelectedClinicNums.Contains(x)))
                {
                    continue;                    //The ClinicNums associated to the 835 do not match any of the selected ClinicNums, so nothing to show in this 835.
                }
                #endregion
                #region Filter: Check and Trace Value
                if (checkTraceNum != "" && !x835.TransRefNum.ToLower().Contains(checkTraceNum.ToLower().Trim()))               //Trace Number does not match
                {
                    continue;
                }
                #endregion
                #region Filter: Insurance Check Range Min and Max
                if (amountMin != "" && x835.InsPaid < PIn.Decimal(amountMin) || amountMax != "" && x835.InsPaid > PIn.Decimal(amountMax))
                {
                    continue;                    //Either the InsPaid is below or above our range.
                }
                #endregion
                #region Filter: ControlID
                if (controlId != "" && !x835.ControlId.ToLower().Contains(controlId.ToLower()))
                {
                    continue;
                }
                #endregion
                GridRow row = new GridRow();
                #region Column: Patient Name
                List <string> listPatNames = x835.ListClaimsPaid.Select(x => x.PatientName.ToString()).Distinct().ToList();
                string        patName      = (listPatNames.Count > 0 ? listPatNames[0] : "");
                if (listPatNames.Count > 1)
                {
                    patName = "(" + POut.Long(listPatNames.Count) + ")";
                }
                row.Cells.Add(patName);
                #endregion
                row.Cells.Add(x835.PayerName);
                row.Cells.Add(status);                //See GetStringStatus(...) for possible values.
                row.Cells.Add(POut.Date(etrans.DateTimeTrans));
                row.Cells.Add(POut.Decimal(x835.InsPaid));
                #region Column: Clinic
                if (PrefC.HasClinicsEnabled)
                {
                    string clinicAbbr = "";
                    if (listClinicNums.Count == 1)
                    {
                        if (listClinicNums[0] == 0)
                        {
                            clinicAbbr = Lan.g(this, "Unassigned");
                        }
                        else
                        {
                            clinicAbbr = Clinics.GetAbbr(listClinicNums[0]);
                        }
                    }
                    else if (listClinicNums.Count > 1)
                    {
                        clinicAbbr = "(" + Lan.g(this, "Multiple") + ")";
                    }
                    row.Cells.Add(clinicAbbr);
                }
                #endregion
                row.Cells.Add(x835._paymentMethodCode);
                if (PrefC.GetBool(PrefName.EraShowControlIdFilter))
                {
                    row.Cells.Add(x835.ControlId);
                }
                row.Cells.Add(etrans.Note);
                row.Tag = etrans;
                gridMain.ListGridRows.Add(row);
            }
            gridMain.EndUpdate();
            actionCloseProgress?.Invoke();            //When this function executes quickly this can fail rarely, fail silently because of WaitCursor.
            Cursor = Cursors.Default;
        }
Beispiel #8
0
 private void FormEtrans835Edit_Load(object sender, EventArgs e)
 {
     MessageText = EtransMessageTexts.GetMessageText(EtransCur.EtransMessageTextNum);
     x835        = new X835(MessageText);
     FillAll();
 }
Beispiel #9
0
        ///<summary>Throws exceptions. The insplan that's passed in need not be properly updated to the database first.</summary>
        ///<returns>The Etrans created from the request. Will be null if the request failed in any way.</returns>
        public static Etrans RequestBenefits(Clearinghouse clearinghouseClin, InsPlan plan, long patNum, Carrier carrier, InsSub insSub, out string error)
        {
            error = "";
            Patient  pat      = Patients.GetPat(patNum);
            Patient  subsc    = Patients.GetPat(insSub.Subscriber);
            Clinic   clinic   = Clinics.GetClinic(pat.ClinicNum);
            Provider billProv = Providers.GetProv(Providers.GetBillingProvNum(pat.PriProv, pat.ClinicNum));
            //validation.  Throw exception if missing info----------------------------------------
            string validationResult = X270.Validate(clearinghouseClin, carrier, billProv, clinic, plan, subsc, insSub, pat);

            if (validationResult != "")
            {
                throw new Exception(Lans.g("FormInsPlan", "Please fix the following errors first:") + "\r\n" + validationResult);
            }
            //create a 270 message---------------------------------------------------------------
            string            x12message        = X270.GenerateMessageText(clearinghouseClin, carrier, billProv, clinic, plan, subsc, insSub, pat);
            EtransMessageText etransMessageText = new EtransMessageText();

            etransMessageText.MessageText = x12message;
            EtransMessageTexts.Insert(etransMessageText);
            //attach it to an etrans-------------------------------------------------------------
            Etrans etrans = new Etrans();

            etrans.PatNum               = patNum;
            etrans.DateTimeTrans        = DateTime.Now;
            etrans.ClearingHouseNum     = clearinghouseClin.HqClearinghouseNum;
            etrans.Etype                = EtransType.BenefitInquiry270;
            etrans.PlanNum              = plan.PlanNum;
            etrans.InsSubNum            = insSub.InsSubNum;
            etrans.EtransMessageTextNum = etransMessageText.EtransMessageTextNum;
            Etranss.Insert(etrans);
            //send the 270----------------------------------------------------------------------
            string x12response = "";
            Etrans etransHtml  = null;

            //a connection error here needs to bubble up
            try {
                if (!String.IsNullOrWhiteSpace(FakeResponseOverride271))
                {
                    x12response = FakeResponseOverride271;
                }
                else if (clearinghouseClin.CommBridge == EclaimsCommBridge.ClaimConnect)
                {
                    x12response = ClaimConnect.Benefits270(clearinghouseClin, x12message);
                }
                else if (clearinghouseClin.CommBridge == EclaimsCommBridge.EDS)
                {
                    x12response = EDS.Benefits270(clearinghouseClin, x12message, out etransHtml);
                }
                else if (clearinghouseClin.CommBridge == EclaimsCommBridge.WebMD)
                {
                    x12response = WebMD.Benefits270(clearinghouseClin, x12message);
                }
            }
            catch (Exception ex) {
                EtransMessageTexts.Delete(etrans.EtransMessageTextNum);
                Etranss.Delete(etrans.EtransNum);
                throw new ApplicationException(Lans.g("FormInsPlan", "Connection Error:") + "\r\n" + ex.GetType().Name + "\r\n" + ex.Message);
            }
            //start to process the 271----------------------------------------------------------
            X271 x271 = null;

            if (X12object.IsX12(x12response))
            {
                X12object x12obj = new X12object(x12response);
                if (x12obj.Is271())
                {
                    x271 = new X271(x12response);
                }
            }
            else              //not a 997, 999, 277 or 271
            {
                EtransMessageTexts.Delete(etrans.EtransMessageTextNum);
                Etranss.Delete(etrans.EtransNum);
                throw new ApplicationException(Lans.g("FormInsPlan", "Error:") + "\r\n" + x12response);
            }

            /*
             * //In realtime mode, X12 limits the request to one patient.
             * //We will always use the subscriber.
             * //So all EB segments are for the subscriber.
             * List<EB271> listEB=new List<EB271>();
             * EB271 eb;
             * if(x271 != null) {
             *      for(int i=0;i<x271.Segments.Count;i++) {
             *              if(x271.Segments[i].SegmentID != "EB") {
             *                      continue;
             *              }
             *              eb=new EB271(x271.Segments[i]);
             *              listEB.Add(eb);
             *      }
             * }*/
            //create an etrans for the 271------------------------------------------------------
            etransMessageText             = new EtransMessageText();
            etransMessageText.MessageText = x12response;
            EtransMessageTexts.Insert(etransMessageText);
            Etrans etrans271 = new Etrans();

            etrans271.PatNum           = patNum;
            etrans271.DateTimeTrans    = DateTime.Now;
            etrans271.ClearingHouseNum = clearinghouseClin.HqClearinghouseNum;
            etrans271.Etype            = EtransType.TextReport;
            if (X12object.IsX12(x12response))             //this shouldn't need to be tested because it was tested above.
            {
                if (x271 == null)
                {
                    X12object Xobj = new X12object(x12response);
                    if (Xobj.Is997())
                    {
                        etrans271.Etype = EtransType.Acknowledge_997;
                    }
                    else if (Xobj.Is999())
                    {
                        etrans271.Etype = EtransType.Acknowledge_999;
                    }
                    else if (X277.Is277(Xobj))
                    {
                        etrans271.Etype = EtransType.StatusNotify_277;
                    }
                    else if (X835.Is835(Xobj))
                    {
                        etrans271.Etype = EtransType.ERA_835;
                    }
                    else if (Xobj.IsAckInterchange())
                    {
                        etrans271.Etype = EtransType.Ack_Interchange;
                    }
                }
                else
                {
                    etrans271.Etype = EtransType.BenefitResponse271;
                }
            }
            etrans271.PlanNum              = plan.PlanNum;
            etrans271.InsSubNum            = insSub.InsSubNum;
            etrans271.EtransMessageTextNum = etransMessageText.EtransMessageTextNum;
            etrans271.MessageText          = etransMessageText.MessageText; //Not a DB column, used to save queries for some calling methods (OpenDentalService).
            if (etransHtml != null)
            {
                etrans271.AckEtransNum = etransHtml.EtransNum;
            }
            Etranss.Insert(etrans271);
            etrans.AckEtransNum = etrans271.EtransNum;
            etrans.AckEtrans    = etrans271;       //Not a DB column, used to save queries for some calling methods (OpenDentalService).
            if (etrans271.Etype == EtransType.Acknowledge_997)
            {
                X997   x997     = new X997(x12response);
                string error997 = x997.GetHumanReadable();
                etrans.Note = "Error: " + error997;            //"Malformed document sent.  997 error returned.";
                Etranss.Update(etrans);
                error = etrans.Note;
                return(null);
            }
            else if (etrans271.Etype == EtransType.Acknowledge_999)
            {
                X999   x999     = new X999(x12response);
                string error999 = x999.GetHumanReadable();
                etrans.Note = "Error: " + error999;            //"Malformed document sent.  999 error returned.";
                Etranss.Update(etrans);
                error = etrans.Note;
                return(null);
            }
            else if (etrans271.Etype == EtransType.StatusNotify_277)
            {
                X277   x277     = new X277(x12response);
                string error277 = x277.GetHumanReadable();
                etrans.Note = "Error: " + error277;            //"Malformed document sent.  277 error returned.";
                Etranss.Update(etrans);
                error = etrans.Note;
                return(null);
            }
            else if (etrans271.Etype == EtransType.ERA_835)
            {
                X835   x835     = new X835(etrans271, x12response, "");
                string error835 = x835.GetHumanReadable();
                etrans.Note = "Error: " + error835;            //"Malformed document sent.  835 error returned.";
                Etranss.Update(etrans);
                error = etrans.Note;
                return(null);
            }
            else if (etrans271.Etype == EtransType.BenefitResponse271)            //271
            {
                string processingerror = x271.GetProcessingError();
                if (processingerror != "")
                {
                    etrans.Note = processingerror;
                    Etranss.Update(etrans);
                    error = etrans.Note;
                    return(null);
                }
                else
                {
                    etrans.Note = "Normal 271 response.";                  //change this later to be explanatory of content.
                }
            }
            else if (etrans271.Etype == EtransType.Ack_Interchange)           //See document "X092 Elig 270-271.pdf" pages 388 and 401.
            {
                X12object  xobj   = new X12object(x12response);
                X12Segment segTa1 = xobj.GetNextSegmentById(0, "TA1");
                if (segTa1.Get(4) == "A")
                {
                    etrans.Note = "The request was accepted, but the response is empty.";
                }
                else
                {
                    if (segTa1.Get(4) == "E")
                    {
                        etrans.Note = "The request was accepted with errors: ";
                    }
                    else if (segTa1.Get(4) == "R")
                    {
                        etrans.Note = "The request was rejected with errors: ";
                    }
                    switch (segTa1.Get(5))
                    {
                    case "000": etrans.Note += "No error"; break;

                    case "001": etrans.Note += "The Interchange Control Number in the Header and Trailer Do Not Match. "
                                               + "The Value From the Header is Used in the Acknowledgment."; break;

                    case "002": etrans.Note += "This Standard as Noted in the Control Standards Identifier is Not Supported."; break;

                    case "003": etrans.Note += "This Version of the Controls is Not Supported"; break;

                    case "004": etrans.Note += "The Segment Terminator is Invalid"; break;

                    case "005": etrans.Note += "Invalid Interchange ID Qualifier for Sender"; break;

                    case "006": etrans.Note += "Invalid Interchange Sender ID"; break;

                    case "007": etrans.Note += "Invalid Interchange ID Qualifier for Receiver"; break;

                    case "008": etrans.Note += "Invalid Interchange Receiver ID"; break;

                    case "009": etrans.Note += "Unknown Interchange Receiver ID"; break;

                    case "010": etrans.Note += "Invalid Authorization Information Qualifier Value"; break;

                    case "011": etrans.Note += "Invalid Authorization Information Value"; break;

                    case "012": etrans.Note += "Invalid Security Information Qualifier Value"; break;

                    case "013": etrans.Note += "Invalid Security Information Value"; break;

                    case "014": etrans.Note += "Invalid Interchange Date Value"; break;

                    case "015": etrans.Note += "Invalid Interchange Time Value"; break;

                    case "016": etrans.Note += "Invalid Interchange Standards Identifier Value"; break;

                    case "017": etrans.Note += "Invalid Interchange Version ID Value"; break;

                    case "018": etrans.Note += "Invalid Interchange Control Number Value"; break;

                    case "019": etrans.Note += "Invalid Acknowledgment Requested Value"; break;

                    case "020": etrans.Note += "Invalid Test Indicator Value"; break;

                    case "021": etrans.Note += "Invalid Number of Included Groups Value"; break;

                    case "022": etrans.Note += "Invalid Control Structure"; break;

                    case "023": etrans.Note += "Improper (Premature) End-of-File (Transmission)"; break;

                    case "024": etrans.Note += "Invalid Interchange Content (e.g., Invalid GS Segment)"; break;

                    case "025": etrans.Note += "Duplicate Interchange Control Number"; break;

                    case "026": etrans.Note += "Invalid Data Element Separator"; break;

                    case "027": etrans.Note += "Invalid Component Element Separator"; break;

                    case "028": etrans.Note += "Invalid Delivery Date in Deferred Delivery Request"; break;

                    case "029": etrans.Note += "Invalid Delivery Time in Deferred Delivery Request"; break;

                    case "030": etrans.Note += "Invalid Delivery Time Code in Deferred Delivery Request"; break;

                    case "031": etrans.Note += "Invalid Grade of Service Code"; break;
                    }
                }
            }
            else
            {
                throw new Exception("Unknown response");
            }
            Etranss.Update(etrans);
            return(etrans);
        }
Beispiel #10
0
        ///<summary>Fills grid based on values in _listEtrans.
        ///Set isRefreshNeeded to true when we need to reinitialize local dictionarys after in memory list is also updated. Required true for first time running.
        ///Also allows you to passed in predetermined filter options.</summary>
        private void FillGrid(bool isRefreshNeeded, List <string> listSelectedStatuses, List <long> listSelectedClinicNums,
                              string carrierName, string checkTraceNum, string amountMin, string amountMax)
        {
            Action actionCloseProgress = null;

            if (isRefreshNeeded)
            {
                actionCloseProgress = ODProgressOld.ShowProgressStatus("Etrans835", this, Lan.g(this, "Gathering data") + "...", false);
                _dictEtrans835s.Clear();
                _dictEtransClaims.Clear();
                _dictClaimPayExists.Clear();
                List <Etrans835Attach>    listAttached        = Etrans835Attaches.GetForEtrans(_listEtranss.Select(x => x.EtransNum).ToArray());
                Dictionary <long, string> dictEtransMessages  = new Dictionary <long, string>();
                List <X12ClaimMatch>      list835ClaimMatches = new List <X12ClaimMatch>();
                Dictionary <long, int>    dictClaimMatchCount = new Dictionary <long, int>(); //1:1 with _listEtranss. Stores how many claim matches each 835 has.
                int batchQueryInterval = 500;                                                 //Every 500 rows we get the next 500 message texts to save memory.
                int rowCur             = 0;
                foreach (Etrans etrans in _listEtranss)
                {
                    if (rowCur % batchQueryInterval == 0)
                    {
                        int range = Math.Min(batchQueryInterval, _listEtranss.Count - rowCur);                   //Either the full batchQueryInterval amount or the remaining amount of etrans.
                        dictEtransMessages = EtransMessageTexts.GetMessageTexts(_listEtranss.GetRange(rowCur, range).Select(x => x.EtransMessageTextNum).ToList(), false);
                    }
                    rowCur++;
                    ODEvent.Fire(new ODEventArgs("Etrans835", Lan.g(this, "Processing 835: ") + ": " + rowCur + " out of " + _listEtranss.Count));
                    List <Etrans835Attach> listAttachedTo835 = listAttached.FindAll(x => x.EtransNum == etrans.EtransNum);
                    X835 x835 = new X835(etrans, dictEtransMessages[etrans.EtransMessageTextNum], etrans.TranSetId835, listAttachedTo835, true);
                    _dictEtrans835s.Add(etrans.EtransNum, x835);
                    List <X12ClaimMatch> listClaimMatches = x835.GetClaimMatches();
                    dictClaimMatchCount.Add(etrans.EtransNum, listClaimMatches.Count);
                    list835ClaimMatches.AddRange(listClaimMatches);
                }
                #region Set 835 unattached in batch and build _dictEtransClaims and _dictClaimPayCheckNums.
                ODEvent.Fire(new ODEventArgs("Etrans835", Lan.g(this, "Gathering internal claim matches.")));
                List <long> listClaimNums = Claims.GetClaimFromX12(list835ClaimMatches);             //Can return null.
                ODEvent.Fire(new ODEventArgs("Etrans835", Lan.g(this, "Building data sets.")));
                int         claimIndexCur        = 0;
                List <long> listMatchedClaimNums = new List <long>();
                foreach (Etrans etrans in _listEtranss)
                {
                    X835 x835 = _dictEtrans835s[etrans.EtransNum];
                    if (listClaimNums != null)
                    {
                        x835.SetClaimNumsForUnattached(listClaimNums.GetRange(claimIndexCur, dictClaimMatchCount[etrans.EtransNum]));
                    }
                    claimIndexCur += dictClaimMatchCount[etrans.EtransNum];
                    listMatchedClaimNums.AddRange(x835.ListClaimsPaid.FindAll(x => x.ClaimNum != 0).Select(x => x.ClaimNum).ToList());
                }
                List <Claim> listClaims = Claims.GetClaimsFromClaimNums(listMatchedClaimNums.Distinct().ToList());
                _dictClaimPayExists = ClaimPayments.HasClaimPayment(listMatchedClaimNums);              //Every claim num is associated to a bool. True when there is an existing claimPayment.
                foreach (Etrans etrans in _listEtranss)
                {
                    X835 x835 = _dictEtrans835s[etrans.EtransNum];
                    #region _dictEtransClaims, _dictClaimPayCheckNums
                    _dictEtransClaims.Add(etrans.EtransNum, new List <Claim>());
                    List <long>  listSubClaimNums = x835.ListClaimsPaid.FindAll(x => x.ClaimNum != 0).Select(y => y.ClaimNum).ToList();
                    List <Claim> listClaimsFor835 = listClaims.FindAll(x => listSubClaimNums.Contains(x.ClaimNum));
                    foreach (Hx835_Claim claim in x835.ListClaimsPaid)
                    {
                        Claim claimCur = listClaimsFor835.FirstOrDefault(x => x.ClaimNum == claim.ClaimNum);                    //Can be null.
                        if (claimCur == null && claim.IsAttachedToClaim && claim.ClaimNum == 0)
                        {
                            claimCur = new Claim();                          //Create empty claim since user detached claim manually, will not be considered in GetStringStatus(...).
                        }
                        if (claimCur != null && claim.IsPreauth)             //User attached preauth to internal claim, no payment needed to be considered 'Finalized' in GetStringStatus(...).
                        {
                            _dictClaimPayExists[claim.ClaimNum] = true;
                        }
                        _dictEtransClaims[etrans.EtransNum].Add(claimCur);
                    }
                    #endregion
                }
                ODEvent.Fire(new ODEventArgs("Etrans835", Lan.g(this, "Filling Grid.")));
                #endregion
            }
            gridMain.BeginUpdate();
            #region Initilize columns only once
            if (gridMain.Columns.Count == 0)
            {
                ODGridColumn col;
                col = new ODGridColumn(Lan.g("TableEtrans835s", "Patient Name"), 250);
                gridMain.Columns.Add(col);
                col = new ODGridColumn(Lan.g("TableEtrans835s", "Carrier Name"), 190);
                gridMain.Columns.Add(col);
                col = new ODGridColumn(Lan.g("TableEtrans835s", "Status"), 80);
                gridMain.Columns.Add(col);
                col = new ODGridColumn(Lan.g("TableEtrans835s", "Date"), 80);
                gridMain.Columns.Add(col);
                col = new ODGridColumn(Lan.g("TableEtrans835s", "Amount"), 80);
                gridMain.Columns.Add(col);
                if (PrefC.HasClinicsEnabled)
                {
                    col = new ODGridColumn(Lan.g("TableEtrans835s", "Clinic"), 70);
                    gridMain.Columns.Add(col);
                }
                col = new ODGridColumn(Lan.g("TableEtrans835s", "Code"), 37, HorizontalAlignment.Center);
                gridMain.Columns.Add(col);
                col = new ODGridColumn(Lan.g("TableEtrans835s", "Note"), 0);
                gridMain.Columns.Add(col);
            }
            #endregion
            gridMain.Rows.Clear();
            foreach (Etrans etrans in _listEtranss)
            {
                X835 x835 = _dictEtrans835s[etrans.EtransNum];
                #region Filter: Carrier Name
                if (carrierName != "" && !x835.PayerName.ToLower().Contains(carrierName.ToLower()))
                {
                    continue;
                }
                #endregion
                string status = GetStringStatus(etrans.EtransNum);
                #region Filter: Status
                if (!listSelectedStatuses.Contains(status.Replace("*", "")))                //The filter will ignore finalized with detached claims.
                {
                    continue;
                }
                #endregion
                //List of ClinicNums for the current etrans.ListClaimsPaid from the DB.
                List <long> listClinicNums = _dictEtransClaims[etrans.EtransNum].Select(x => x == null? 0 :x.ClinicNum).Distinct().ToList();
                #region Filter: Clinics
                if (PrefC.HasClinicsEnabled && !listClinicNums.Exists(x => listSelectedClinicNums.Contains(x)))
                {
                    continue;                    //The ClinicNums associated to the 835 do not match any of the selected ClinicNums, so nothing to show in this 835.
                }
                #endregion
                #region Filter: Check and Trace Value
                if (checkTraceNum != "" && !x835.TransRefNum.Contains(checkTraceNum))               //Trace Number does not match
                {
                    continue;
                }
                #endregion
                #region Filter: Insurance Check Range Min and Max
                if (amountMin != "" && x835.InsPaid < PIn.Decimal(amountMin) || amountMax != "" && x835.InsPaid > PIn.Decimal(amountMax))
                {
                    continue;                    //Either the InsPaid is below or above our range.
                }
                #endregion
                ODGridRow row = new ODGridRow();
                #region Column: Patient Name
                List <string> listPatNames = x835.ListClaimsPaid.Select(x => x.PatientName.ToString()).Distinct().ToList();
                string        patName      = (listPatNames.Count > 0 ? listPatNames[0] : "");
                if (listPatNames.Count > 1)
                {
                    patName = "(" + POut.Long(listPatNames.Count) + ")";
                }
                row.Cells.Add(patName);
                #endregion
                row.Cells.Add(x835.PayerName);
                row.Cells.Add(status);                //See GetStringStatus(...) for possible values.
                row.Cells.Add(POut.Date(etrans.DateTimeTrans));
                row.Cells.Add(POut.Decimal(x835.InsPaid));
                #region Column: Clinic
                if (PrefC.HasClinicsEnabled)
                {
                    string clinicAbbr = "";
                    if (listClinicNums.Count == 1)
                    {
                        if (listClinicNums[0] == 0)
                        {
                            clinicAbbr = Lan.g(this, "Unassigned");
                        }
                        else
                        {
                            clinicAbbr = Clinics.GetAbbr(listClinicNums[0]);
                        }
                    }
                    else if (listClinicNums.Count > 1)
                    {
                        clinicAbbr = "(" + Lan.g(this, "Multiple") + ")";
                    }
                    row.Cells.Add(clinicAbbr);
                }
                #endregion
                row.Cells.Add(x835._paymentMethodCode);
                row.Cells.Add(etrans.Note);
                row.Tag = etrans;
                gridMain.Rows.Add(row);
            }
            gridMain.EndUpdate();
            actionCloseProgress?.Invoke();
        }
Beispiel #11
0
		///<summary>Etrans type will be figured out by this class.  Either TextReport, Acknowledge_997, Acknowledge_999, or StatusNotify_277.</summary>
		public static void ProcessIncomingReport(DateTime dateTimeTrans,long hqClearinghouseNum,string messageText,long userNum) {
			if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
				Meth.GetVoid(MethodBase.GetCurrentMethod(),dateTimeTrans,hqClearinghouseNum,messageText,userNum);
				return;
			}
			Etrans etrans=CreateEtrans(dateTimeTrans,hqClearinghouseNum,messageText,userNum);
			string command;
			X12object Xobj=X12object.ToX12object(messageText);
			if(Xobj!=null) {//Is a correctly formatted X12 message.
				if(Xobj.IsAckInterchange()) {
					etrans.Etype=EtransType.Ack_Interchange;
					Etranss.Insert(etrans);
					//At some point in the future, we should use TA101 to match to batch number and TA104 to get the ack code, 
					//then update historic etrans entries like we do for 997s, 999s and 277s.
				}
				else if(Xobj.Is997()) {
					X997 x997=new X997(messageText);
					etrans.Etype=EtransType.Acknowledge_997;
					etrans.BatchNumber=x997.GetBatchNumber();
					Etranss.Insert(etrans);
					string batchack=x997.GetBatchAckCode();
					if(batchack=="A"||batchack=="R") {//accepted or rejected
						command="UPDATE etrans SET AckCode='"+batchack+"', "
							+"AckEtransNum="+POut.Long(etrans.EtransNum)
							+" WHERE BatchNumber="+POut.Long(etrans.BatchNumber)
							+" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
							+" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
							+" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1))
							+" AND AckEtransNum=0";
						Db.NonQ(command);
					}
					else {//partially accepted
						List<int> transNums=x997.GetTransNums();
						string ack;
						for(int i=0;i<transNums.Count;i++) {
							ack=x997.GetAckForTrans(transNums[i]);
							if(ack=="A"||ack=="R") {//accepted or rejected
								command="UPDATE etrans SET AckCode='"+ack+"', "
									+"AckEtransNum="+POut.Long(etrans.EtransNum)
									+" WHERE BatchNumber="+POut.Long(etrans.BatchNumber)
									+" AND TransSetNum="+POut.Long(transNums[i])
									+" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
									+" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
									+" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1))
									+" AND AckEtransNum=0";
								Db.NonQ(command);
							}
						}
					}
					//none of the other fields make sense, because this ack could refer to many claims.
				}
				else if(Xobj.Is999()) {
					X999 x999=new X999(messageText);
					etrans.Etype=EtransType.Acknowledge_999;
					etrans.BatchNumber=x999.GetBatchNumber();
					Etranss.Insert(etrans);
					string batchack=x999.GetBatchAckCode();
					if(batchack=="A"||batchack=="R") {//accepted or rejected
					  command="UPDATE etrans SET AckCode='"+batchack+"', "
					    +"AckEtransNum="+POut.Long(etrans.EtransNum)
					    +" WHERE BatchNumber="+POut.Long(etrans.BatchNumber)
					    +" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
					    +" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
					    +" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1))
					    +" AND AckEtransNum=0";
					  Db.NonQ(command);
					}
					else {//partially accepted
					  List<int> transNums=x999.GetTransNums();
					  string ack;
					  for(int i=0;i<transNums.Count;i++) {
					    ack=x999.GetAckForTrans(transNums[i]);
					    if(ack=="A"||ack=="R") {//accepted or rejected
					      command="UPDATE etrans SET AckCode='"+ack+"', "
					        +"AckEtransNum="+POut.Long(etrans.EtransNum)
					        +" WHERE BatchNumber="+POut.Long(etrans.BatchNumber)
					        +" AND TransSetNum="+POut.Long(transNums[i])
					        +" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
					        +" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
					        +" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1))
					        +" AND AckEtransNum=0";
					      Db.NonQ(command);
					    }
					  }
					}
					//none of the other fields make sense, because this ack could refer to many claims.
				}
				else if(X277.Is277(Xobj)) {
					X277 x277=new X277(messageText);
					etrans.Etype=EtransType.StatusNotify_277;
					Etranss.Insert(etrans);
					List<string> listClaimIdentifiers=x277.GetClaimTrackingNumbers();
					//Dictionary to run one update command per ack code for many claims.
					Dictionary <string,List<X12ClaimMatch>> dictClaimMatchesByAck=new Dictionary<string,List<X12ClaimMatch>>();
					for(int i=0;i<listClaimIdentifiers.Count;i++) {
						X12ClaimMatch claimMatch=new X12ClaimMatch();
						claimMatch.ClaimIdentifier=listClaimIdentifiers[i];
						string[] arrayClaimInfo=x277.GetClaimInfo(claimMatch.ClaimIdentifier);
						claimMatch.PatFname=PIn.String(arrayClaimInfo[0]);
						claimMatch.PatLname=PIn.String(arrayClaimInfo[1]);
						claimMatch.DateServiceStart=PIn.DateT(arrayClaimInfo[6]);
						claimMatch.DateServiceEnd=PIn.DateT(arrayClaimInfo[7]);
						claimMatch.ClaimFee=PIn.Double(arrayClaimInfo[9]);
						claimMatch.SubscriberId=PIn.String(arrayClaimInfo[10]);
						claimMatch.EtransNum=etrans.EtransNum;
						string ack=arrayClaimInfo[3];
						if(!dictClaimMatchesByAck.ContainsKey(ack)) {
							dictClaimMatchesByAck.Add(ack,new List<X12ClaimMatch>());
						}
						dictClaimMatchesByAck[ack].Add(claimMatch);
					}
					foreach(string ack in dictClaimMatchesByAck.Keys) {
						List <long> listClaimNums=Claims.GetClaimFromX12(dictClaimMatchesByAck[ack]);
						if(listClaimNums!=null) {
							listClaimNums=listClaimNums.Where(x => x!=0).ToList();
							if(listClaimNums.Count > 0) {
								//Locate the latest etrans entries for the claims based on DateTimeTrans with EType of ClaimSent or Claim_Ren and update the AckCode and AckEtransNum.
								//We overwrite existing acks from 997s, 999s and older 277s.
								command="UPDATE etrans SET AckCode='"+ack+"', "
									+"AckEtransNum="+POut.Long(etrans.EtransNum)
									+" WHERE EType IN ("+POut.Int((int)EtransType.ClaimSent)+","+POut.Int((int)EtransType.Claim_Ren)+") "
									+" AND ClaimNum IN("+String.Join(",",listClaimNums.Select(x => POut.Long(x)))+")"
									+" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
									+" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
									+" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1));
								Db.NonQ(command);
							}
						}
						//none of the other fields make sense, because this ack could refer to many claims.
					}
				}
				else if(X835.Is835(Xobj)) {
					etrans.Etype=EtransType.ERA_835;
					List <string> listTranSetIds=Xobj.GetTranSetIds();
					List <Etrans> listEtrans=new List<Etrans>();
					List <X835> list835s=new List<X835>();
					//We pull in the 835 data in two loops so that we can ensure the 835 is fully parsed before we create any etrans entries.
					for(int i=0;i<listTranSetIds.Count;i++) {
						etrans.TranSetId835=listTranSetIds[i];
						if(i>0) {
							etrans.EtransNum=0;//To get a new record to insert.
						}
						X835 x835=new X835(etrans,messageText,etrans.TranSetId835);//parse. If parsing fails, then no etrans entries will be inserted.
						etrans.CarrierNameRaw=x835.PayerName;
						List<string> listUniquePatientNames=new List<string>();
						for(int j=0;j<x835.ListClaimsPaid.Count;j++) {
							string patName=x835.ListClaimsPaid[j].PatientName.ToString(false);
							if(!listUniquePatientNames.Contains(patName)) {
								listUniquePatientNames.Add(patName);
							}
						}
						if(listUniquePatientNames.Count==1) {
							etrans.PatientNameRaw=listUniquePatientNames[0];
						}
						else {
							etrans.PatientNameRaw="("+listUniquePatientNames.Count+" "+Lans.g("Etranss","patients")+")";
						}
						listEtrans.Add(etrans.Copy());
						list835s.Add(x835);
					}
					//The 835 was completely parsed.  Create etrans entries.
					for(int i=0;i<listEtrans.Count;i++) {
						etrans=listEtrans[i];
						X835 x835=list835s[i];
						Etranss.Insert(etrans);//insert
						List<long> listClaimNums=x835.ListClaimsPaid.Select(x => x.ClaimNum).Where(x => x!=0).ToList();
						if(listClaimNums.Count > 0) {
							//Locate the latest etrans entries for the claim based on DateTimeTrans with EType of ClaimSent or Claim_Ren and update the AckCode and AckEtransNum.
							//We overwrite existing acks from 997s, 999s, and 277s.
							command="UPDATE etrans SET AckCode='A', "
								+"AckEtransNum="+POut.Long(etrans.EtransNum)
								+" WHERE EType IN (0,3) "//ClaimSent and Claim_Ren
								+" AND ClaimNum IN("+String.Join(",",listClaimNums.Select(x => POut.Long(x)))+")"
								+" AND ClearinghouseNum="+POut.Long(hqClearinghouseNum)
								+" AND DateTimeTrans > "+POut.DateT(dateTimeTrans.AddDays(-14))
								+" AND DateTimeTrans < "+POut.DateT(dateTimeTrans.AddDays(1));
							Db.NonQ(command);
						}
						//none of the other fields make sense, because this ack could refer to many claims.
					}
				}
				else {//unknown type of X12 report.
					etrans.Etype=EtransType.TextReport;
					Etranss.Insert(etrans);
				}
			}
			else {//not X12
				etrans.Etype=EtransType.TextReport;
				Etranss.Insert(etrans);
			}
		}