private void gridInsPlans_CellDoubleClick(object sender, UI.ODGridClickEventArgs e)
        {
            Hx834_Member         member         = null;
            Hx834_HealthCoverage healthCoverage = null;

            if (gridInsPlans.ListGridRows[e.Row].Tag is Hx834_Member)
            {
                member = (Hx834_Member)gridInsPlans.ListGridRows[e.Row].Tag;
            }
            else
            {
                healthCoverage = (Hx834_HealthCoverage)gridInsPlans.ListGridRows[e.Row].Tag;
                member         = healthCoverage.Member;
            }
            FormPatientSelect FormPS = new FormPatientSelect(member.Pat);

            if (FormPS.ShowDialog() == DialogResult.OK)
            {
                member.Pat.PatNum = FormPS.SelectedPatNum;
                gridInsPlans.BeginUpdate();
                //Refresh all rows for this member to show the newly selected PatNum.
                //There will be multiple rows if there are multiple insurance plans for the member.
                for (int i = 0; i < gridInsPlans.ListGridRows.Count; i++)
                {
                    Hx834_Member memberRefresh = null;
                    if (gridInsPlans.ListGridRows[i].Tag is Hx834_Member)
                    {
                        memberRefresh = (Hx834_Member)gridInsPlans.ListGridRows[i].Tag;
                    }
                    else
                    {
                        memberRefresh = ((Hx834_HealthCoverage)gridInsPlans.ListGridRows[i].Tag).Member;
                    }
                    if (memberRefresh == member)
                    {
                        FillGridRow(gridInsPlans.ListGridRows[e.Row], member, healthCoverage);
                    }
                }
                gridInsPlans.EndUpdate();
            }
        }
        private void Load834_Unsafe()
        {
            Cursor = Cursors.WaitCursor;
            ShowStatus("Loading patient information");
            const int previewLimitCount = 40;

            gridInsPlans.BeginUpdate();
            gridInsPlans.ListGridRows.Clear();
            gridInsPlans.EndUpdate();
            Application.DoEvents();
            if (_listPatients == null)
            {
                _listPatients = Patients.GetAllPatients();              //Testing this on an average sized database took about 1 second to run on a dev machine.
                _listPatients.Sort();
            }
            int rowCount = 0;

            for (int i = 0; i < _x834.ListTransactions.Count; i++)
            {
                Hx834_Tran tran = _x834.ListTransactions[i];
                for (int k = 0; k < tran.ListMembers.Count; k++)
                {
                    rowCount++;
                }
            }
            for (int i = 0; i < _x834.ListTransactions.Count; i++)
            {
                Hx834_Tran tran = _x834.ListTransactions[i];
                for (int j = 0; j < tran.ListMembers.Count; j++)
                {
                    Hx834_Member member = tran.ListMembers[j];
                    ShowStatus("Loading " + (gridInsPlans.ListGridRows.Count + 1).ToString().PadLeft(6) + "/" + rowCount.ToString().PadLeft(6)
                               + "  Patient " + member.Pat.GetNameLF());
                    if (gridInsPlans.ListGridRows.Count < previewLimitCount)
                    {
                        gridInsPlans.BeginUpdate();
                    }
                    if (member.ListHealthCoverage.Count == 0)
                    {
                        UI.GridRow row = new UI.GridRow();
                        gridInsPlans.ListGridRows.Add(row);
                        FillGridRow(row, member, null);
                    }
                    else                      //There is at least one insurance plan.
                    {
                        for (int a = 0; a < member.ListHealthCoverage.Count; a++)
                        {
                            Hx834_HealthCoverage healthCoverage = member.ListHealthCoverage[a];
                            UI.GridRow           row            = new UI.GridRow();
                            gridInsPlans.ListGridRows.Add(row);
                            FillGridRow(row, null, healthCoverage);
                        }
                    }
                    if (gridInsPlans.ListGridRows.Count < previewLimitCount)
                    {
                        gridInsPlans.EndUpdate();                        //Also invalidates grid.
                        Application.DoEvents();
                    }
                }
            }
            gridInsPlans.BeginUpdate();
            gridInsPlans.SortForced(_sortedByColumnIdx, _isSortAscending);
            gridInsPlans.EndUpdate();            //Also invalidates grid.
            ShowStatus("");
            Cursor = Cursors.Default;
            Application.DoEvents();
        }
Esempio n. 3
0
        private void Import834_Unsafe()
        {
            if (!MsgBox.Show(this, true, "Importing insurance plans is a database intensive operation and can take 10 minutes or more to run.  "
                             + "It is best to import insurance plans after hours or during another time period when database usage is otherwise low.\r\n"
                             + "Click OK to import insurance plans now, or click Cancel."))
            {
                return;
            }
            checkIsPatientCreate.Enabled = false;
            gridInsPlans.Enabled         = false;
            butOK.Enabled     = false;
            butCancel.Enabled = false;
            Cursor            = Cursors.WaitCursor;
            Prefs.UpdateBool(PrefName.Ins834IsPatientCreate, checkIsPatientCreate.Checked);
            int           rowIndex             = 1;
            int           createdPatsCount     = 0;
            int           updatedPatsCount     = 0;
            int           skippedPatsCount     = 0;
            int           createdCarrierCount  = 0;
            int           createdPlanCount     = 0;
            int           droppedPlanCount     = 0;
            int           updatedPlanCount     = 0;
            StringBuilder sbErrorMessages      = new StringBuilder();
            List <int>    listImportedSegments = new List <int> ();      //Used to reconstruct the 834 with imported patients removed.

            for (int i = 0; i < _x834.ListTransactions.Count; i++)
            {
                Hx834_Tran tran = _x834.ListTransactions[i];
                for (int j = 0; j < tran.ListMembers.Count; j++)
                {
                    Hx834_Member member = tran.ListMembers[j];
                    ShowStatus("Progress " + (rowIndex).ToString().PadLeft(6) + "/" + gridInsPlans.Rows.Count.ToString().PadLeft(6)
                               + "  Importing plans for patient " + member.Pat.GetNameLF());
                    //The patient's status is not affected by the maintenance code.  After reviewing all of the possible maintenance codes in
                    //member.MemberLevelDetail.MaintenanceTypeCode, we believe that all statuses suggest either insert or update, except for "Cancel".
                    //Nathan and Derek feel that archiving the patinet in response to a Cancel request is a bit drastic.
                    //Thus we ignore the patient maintenance code and always assume insert/update.
                    //Even if the status was "Cancel", then updating the patient does not hurt.
                    bool isMemberImported = false;
                    bool isMultiMatch     = false;
                    if (member.Pat.PatNum == 0)
                    {
                        //The patient may need to be created below.  However, the patient may have already been inserted in a pervious iteration of this loop
                        //in following scenario: Two different 834s include updates for the same patient and both documents are being imported at the same time.
                        //If the patient was already inserted, then they would show up in _listPatients and also in the database.  Attempt to locate the patient
                        //in _listPatients again before inserting.
                        List <Patient> listPatientMatches = Patients.GetPatientsByNameAndBirthday(member.Pat, _listPatients);
                        if (listPatientMatches.Count == 1)
                        {
                            member.Pat.PatNum = listPatientMatches[0].PatNum;
                        }
                        else if (listPatientMatches.Count > 1)
                        {
                            isMultiMatch = true;
                        }
                    }
                    if (isMultiMatch)
                    {
                        skippedPatsCount++;
                    }
                    else if (member.Pat.PatNum == 0 && checkIsPatientCreate.Checked)
                    {
                        //The code here mimcs the behavior of FormPatientSelect.butAddPt_Click().
                        Patients.Insert(member.Pat, false);
                        Patient memberPatOld = member.Pat.Copy();
                        member.Pat.PatStatus   = PatientStatus.Patient;
                        member.Pat.BillingType = PrefC.GetLong(PrefName.PracticeDefaultBillType);
                        if (!PrefC.GetBool(PrefName.PriProvDefaultToSelectProv))
                        {
                            //Set the patients primary provider to the practice default provider.
                            member.Pat.PriProv = Providers.GetDefaultProvider().ProvNum;
                        }
                        member.Pat.ClinicNum = Clinics.ClinicNum;
                        member.Pat.Guarantor = member.Pat.PatNum;
                        Patients.Update(member.Pat, memberPatOld);
                        int patIdx    = _listPatients.BinarySearch(member.Pat); //Preserve sort order by locating the index in which to insert the newly added patient.
                        int insertIdx = ~patIdx;                                //According to MSDN, the index returned by BinarySearch() is a "bitwise compliment", since not currently in list.
                        _listPatients.Insert(insertIdx, member.Pat);
                        SecurityLogs.MakeLogEntry(Permissions.PatientCreate, member.Pat.PatNum, "Created from Import Ins Plans 834.", LogSources.InsPlanImport834);
                        isMemberImported = true;
                        createdPatsCount++;
                    }
                    else if (member.Pat.PatNum == 0 && !checkIsPatientCreate.Checked)
                    {
                        skippedPatsCount++;
                    }
                    else                                                                                  //member.Pat.PatNum!=0
                    {
                        Patient patDb = _listPatients.FirstOrDefault(x => x.PatNum == member.Pat.PatNum); //Locate by PatNum, in case user selected manually.
                        member.MergePatientIntoDbPatient(patDb);                                          //Also updates the patient to the database and makes log entry.
                        _listPatients.Remove(patDb);                                                      //Remove patient from list so we can add it back in the correct location (in case name or bday changed).
                        int patIdx = _listPatients.BinarySearch(patDb);                                   //Preserve sort order by locating the index in which to insert the newly added patient.
                        //patIdx could be positive if the user manually selected a patient when there were multiple matches found.
                        //If patIdx is negative, then according to MSDN, the index returned by BinarySearch() is a "bitwise compliment".
                        //If there were mult instances of patDb BinarySearch() would return 0, which should not be complimented (OutOfRangeException)
                        int insertIdx = (patIdx >= 0)?patIdx:~patIdx;
                        _listPatients.Insert(insertIdx, patDb);
                        isMemberImported = true;
                        updatedPatsCount++;
                    }
                    if (isMemberImported)
                    {
                        //Import insurance changes for patient.
                        for (int k = 0; k < member.ListHealthCoverage.Count; k++)
                        {
                            Hx834_HealthCoverage healthCoverage = member.ListHealthCoverage[k];
                            if (k > 0)
                            {
                                rowIndex++;
                            }
                            List <Carrier> listCarriers = Carriers.GetByNameAndTin(tran.Payer.Name, tran.Payer.IdentificationCode);
                            if (listCarriers.Count == 0)
                            {
                                Carrier carrier = new Carrier();
                                carrier.CarrierName = tran.Payer.Name;
                                carrier.TIN         = tran.Payer.IdentificationCode;
                                Carriers.Insert(carrier);
                                DataValid.SetInvalid(InvalidType.Carriers);
                                listCarriers.Add(carrier);
                                SecurityLogs.MakeLogEntry(Permissions.CarrierCreate, 0, "Carrier '" + carrier.CarrierName
                                                          + "' created from Import Ins Plans 834.", LogSources.InsPlanImport834);
                                createdCarrierCount++;
                            }
                            //Update insurance plans.  Match based on carrier and SubscriberId.
                            bool isDropping = false;
                            if (healthCoverage.HealthCoverage.MaintenanceTypeCode == "002")
                            {
                                isDropping = true;
                            }
                            //The insPlanNew will only be inserted if necessary.  Created temporarily in order to determine if insert is needed.
                            InsPlan insPlanNew = InsertOrUpdateInsPlan(null, member, listCarriers[0], false);
                            //Since the insurance plans in the 834 do not include very much information, it is likely that many patients will share the same exact plan.
                            //We look for an existing plan being used by any other patinents which match the fields we typically import.
                            List <InsPlan> listInsPlans = InsPlans.GetAllByCarrierNum(listCarriers[0].CarrierNum);
                            InsPlan        insPlanMatch = null;
                            for (int p = 0; p < listInsPlans.Count; p++)
                            {
                                //Set the PlanNums equal so that AreEqualValue() will ignore this field.  We must ignore PlanNum, since we do not know the PlanNum.
                                insPlanNew.PlanNum = listInsPlans[p].PlanNum;
                                if (InsPlans.AreEqualValue(listInsPlans[p], insPlanNew))
                                {
                                    insPlanMatch = listInsPlans[p];
                                    break;
                                }
                            }
                            Family         fam          = Patients.GetFamily(member.Pat.PatNum);
                            List <InsSub>  listInsSubs  = InsSubs.RefreshForFam(fam);
                            List <PatPlan> listPatPlans = PatPlans.Refresh(member.Pat.PatNum);
                            InsSub         insSubMatch  = null;
                            PatPlan        patPlanMatch = null;
                            for (int p = 0; p < listInsSubs.Count; p++)
                            {
                                InsSub insSub = listInsSubs[p];
                                //According to section 1.4.3 of the standard, the preferred method of matching a dependent to a subscriber is to use the subscriberId.
                                if (insSub.SubscriberID.Trim() != member.SubscriberId.Trim())
                                {
                                    continue;
                                }
                                insSubMatch  = insSub;
                                patPlanMatch = PatPlans.GetFromList(listPatPlans, insSub.InsSubNum);
                                break;
                            }
                            if (patPlanMatch == null && isDropping)                           //No plan match and dropping plan.
                            //Nothing to do.  The plan either never existed or is already dropped.
                            {
                            }
                            else if (patPlanMatch == null && !isDropping)                           //No plan match and not dropping plan.  Create the plan.
                            {
                                insPlanMatch = InsertOrUpdateInsPlan(insPlanMatch, member, listCarriers[0]);
                                insSubMatch  = InsertOrUpdateInsSub(insSubMatch, insPlanMatch, member, healthCoverage, listCarriers[0]);
                                patPlanMatch = InsertOrUpdatePatPlan(patPlanMatch, insSubMatch, insPlanMatch, member, listCarriers[0], listPatPlans);
                                createdPlanCount++;
                            }
                            else if (patPlanMatch != null && isDropping)                           //Plan matched and dropping plan.  Drop the plan.
                            //This code mimics the behavior of FormInsPlan.butDrop_Click(), except here we do not care if there are claims for this plan today.
                            //We need this feature to be as streamlined as possible so that it might become an automated process later.
                            //Testing for claims on today's date does not seem that useful anyway, or at least not as useful as checking for any claims
                            //associated to the plan, instead of just today's date.
                            {
                                PatPlans.Delete(patPlanMatch.PatPlanNum);                                //Estimates recomputed within Delete()
                                SecurityLogs.MakeLogEntry(Permissions.InsPlanDropPat, patPlanMatch.PatNum,
                                                          "Insurance plan dropped from patient for carrier '" + listCarriers[0].CarrierName + "' and groupnum "
                                                          + "'" + insPlanMatch.GroupNum + "' and subscriber ID '" + insSubMatch.SubscriberID + "' "
                                                          + "from Import Ins Plans 834.", insPlanMatch.PlanNum, LogSources.InsPlanImport834, insPlanMatch.SecDateTEdit);
                                droppedPlanCount++;
                            }
                            else if (patPlanMatch != null && !isDropping)                            //Plan matched and not dropping plan.  Update the plan.
                            {
                                insPlanMatch = InsertOrUpdateInsPlan(insPlanMatch, member, listCarriers[0]);
                                insSubMatch  = InsertOrUpdateInsSub(insSubMatch, insPlanMatch, member, healthCoverage, listCarriers[0]);
                                patPlanMatch = InsertOrUpdatePatPlan(patPlanMatch, insSubMatch, insPlanMatch, member, listCarriers[0], listPatPlans);
                                updatedPlanCount++;
                            }
                        }                        //end loop k
                        //Remove the member from the X834.
                        int endSegIndex = 0;
                        if (j < tran.ListMembers.Count - 1)
                        {
                            endSegIndex = tran.ListMembers[j + 1].MemberLevelDetail.SegmentIndex - 1;
                        }
                        else
                        {
                            X12Segment segSe = _x834.GetNextSegmentById(member.MemberLevelDetail.SegmentIndex + 1, "SE");                       //SE segment is required.
                            endSegIndex = segSe.SegmentIndex - 1;
                        }
                        for (int s = member.MemberLevelDetail.SegmentIndex; s <= endSegIndex; s++)
                        {
                            listImportedSegments.Add(s);
                        }
                    }
                    rowIndex++;
                }                                                       //end loop j
            }                                                           //end loop i
            if (listImportedSegments.Count > 0 && skippedPatsCount > 0) //Some patients imported, while others did not.
            {
                if (MoveFileToArchiveFolder())
                {
                    //Save the unprocessed members back to the import directory, so the user can try to import them again.
                    File.WriteAllText(_x834.FilePath, _x834.ReconstructRaw(listImportedSegments));
                }
            }
            else if (listImportedSegments.Count > 0)             //All patinets imported.
            {
                MoveFileToArchiveFolder();
            }
            else if (skippedPatsCount > 0)             //No patients imported.  All patients were skipped.
            //Leave the raw file unaltered and where it is, so it can be processed again.
            {
            }
            Cursor = Cursors.Default;
            string msg = Lan.g(this, "Done.");

            if (createdPatsCount > 0)
            {
                msg += "\r\n" + Lan.g(this, "Number of patients created:") + " " + createdPatsCount;
            }
            if (updatedPatsCount > 0)
            {
                msg += "\r\n" + Lan.g(this, "Number of patients updated:") + " " + updatedPatsCount;
            }
            if (skippedPatsCount > 0)
            {
                msg += "\r\n" + Lan.g(this, "Number of patients skipped:") + " " + skippedPatsCount;
                msg += sbErrorMessages.ToString();
            }
            if (createdCarrierCount > 0)
            {
                msg += "\r\n" + Lan.g(this, "Number of carriers created:") + " " + createdCarrierCount;
                msg += sbErrorMessages.ToString();
            }
            if (createdPlanCount > 0)
            {
                msg += "\r\n" + Lan.g(this, "Number of plans created:") + " " + createdPlanCount;
                msg += sbErrorMessages.ToString();
            }
            if (droppedPlanCount > 0)
            {
                msg += "\r\n" + Lan.g(this, "Number of plans dropped:") + " " + droppedPlanCount;
                msg += sbErrorMessages.ToString();
            }
            if (updatedPlanCount > 0)
            {
                msg += "\r\n" + Lan.g(this, "Number of plans updated:") + " " + updatedPlanCount;
                msg += sbErrorMessages.ToString();
            }
            MsgBoxCopyPaste msgBox = new MsgBoxCopyPaste(msg);

            msgBox.ShowDialog();
        }
        ///<summary>The healthCoverage variable can be null.</summary>
        private void FillGridRow(UI.GridRow row, Hx834_Member member, Hx834_HealthCoverage healthCoverage)
        {
            row.Cells.Clear();
            if (healthCoverage == null)
            {
                row.Tag = member;
            }
            else
            {
                row.Tag = healthCoverage;
                member  = healthCoverage.Member;
            }
            row.Cells.Add(member.Pat.GetNameLF());            //Name
            if (member.Pat.Birthdate.Year > 1880)
            {
                row.Cells.Add(member.Pat.Birthdate.ToShortDateString());                //Birthdate
            }
            else
            {
                row.Cells.Add("");                //Birthdate
            }
            row.Cells.Add(member.Pat.SSN);        //SSN
            List <Patient> listPatientMatches = Patients.GetPatientsByNameAndBirthday(member.Pat, _listPatients);

            if (member.Pat.PatNum == 0 && listPatientMatches.Count == 1)
            {
                member.Pat.PatNum = listPatientMatches[0].PatNum;
            }
            if (member.Pat.PatNum == 0 && listPatientMatches.Count == 0)
            {
                row.Cells.Add("");                //PatNum
            }
            else if (member.Pat.PatNum == 0 && listPatientMatches.Count > 1)
            {
                row.Cells.Add("Multiple");                   //PatNum
            }
            else                                             //Either the patient was matched perfectly or the user chose the correct patient already.
            {
                row.Cells.Add(member.Pat.PatNum.ToString()); //PatNum
            }
            if (healthCoverage != null && healthCoverage.DateEffective.Year > 1880)
            {
                row.Cells.Add(healthCoverage.DateEffective.ToShortDateString());                //Date Begin
            }
            else
            {
                row.Cells.Add("");                //Date Begin
            }
            if (healthCoverage != null && healthCoverage.DateTerm.Year > 1880)
            {
                row.Cells.Add(healthCoverage.DateTerm.ToShortDateString());                //Date Term
            }
            else
            {
                row.Cells.Add("");                      //Date Term
            }
            row.Cells.Add(member.PlanRelat.ToString()); //Relation
            row.Cells.Add(member.SubscriberId);         //SubscriberID
            row.Cells.Add(member.GroupNum);             //GroupNum
            row.Cells.Add(member.Tran.Payer.Name);      //Payer
        }
Esempio n. 5
0
 private InsSub InsertOrUpdateInsSub(InsSub insSub, InsPlan insPlan, Hx834_Member member, Hx834_HealthCoverage healthCoverage, Carrier carrier)
 {
     if (insSub == null)
     {
         insSub         = new InsSub();
         insSub.PlanNum = insPlan.PlanNum;
         //According to section 1.4.3 of the 834 standard, subscribers must be sent in the 834 before dependents.
         //This requirement facilitates easier linking of dependents to their subscribers.
         //Since we were not able to locate a subscriber within the family above, we can safely assume that the insurance plan in the 834
         //is for the subscriber.  Thus we can set the Subscriber PatNum to the same PatNum as the patient.
         insSub.Subscriber    = member.Pat.PatNum;
         insSub.SubscriberID  = member.SubscriberId;
         insSub.ReleaseInfo   = member.IsReleaseInfo;
         insSub.AssignBen     = true;
         insSub.DateEffective = healthCoverage.DateEffective;
         insSub.DateTerm      = healthCoverage.DateTerm;
         InsSubs.Insert(insSub);
         SecurityLogs.MakeLogEntry(Permissions.InsPlanCreateSub, insSub.Subscriber,
                                   "Insurance subscriber created for carrier '" + carrier.CarrierName + "' and groupnum "
                                   + "'" + insPlan.GroupNum + "' and subscriber ID '" + insSub.SubscriberID + "' "
                                   + "from Import Ins Plans 834.", insPlan.PlanNum, LogSources.InsPlanImport834, DateTime.MinValue);
     }
     else
     {
         InsSub insSubOld = insSub.Copy();
         insSub.DateEffective = healthCoverage.DateEffective;
         insSub.DateTerm      = healthCoverage.DateTerm;
         insSub.ReleaseInfo   = member.IsReleaseInfo;
         if (OpenDentBusiness.Crud.InsSubCrud.UpdateComparison(insSub, insSubOld))
         {
             InsSubs.Update(insSub);
             SecurityLogs.MakeLogEntry(Permissions.InsPlanEditSub, insSub.Subscriber,
                                       "Insurance subscriber edited for carrier '" + carrier.CarrierName + "' and groupnum "
                                       + "'" + insPlan.GroupNum + "' and subscriber ID '" + insSub.SubscriberID + "' "
                                       + "from Import Ins Plans 834.", insPlan.PlanNum, LogSources.InsPlanImport834, insSubOld.SecDateTEdit);
         }
     }
     return(insSub);
 }