예제 #1
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();
        }