Exemple #1
0
        private void butMovePats_Click(object sender, EventArgs e)
        {
            if (gridMain.SelectedIndices.Length < 1)
            {
                MsgBox.Show(this, "You must select at least one clinic to move patients from.");
                return;
            }
            if (_clinicNumTo == -1)
            {
                MsgBox.Show(this, "You must pick a 'To' clinic in the box above to move patients to.");
                return;
            }
            Dictionary <long, Clinic> dictClinicsFrom = gridMain.SelectedTags <Clinic>().ToDictionary(x => x.ClinicNum);
            Clinic clinicTo = gridMain.GetTags <Clinic>().FirstOrDefault(x => x.ClinicNum == _clinicNumTo);

            if (clinicTo == null)
            {
                MsgBox.Show(this, "The clinic could not be found.");
                return;
            }
            if (dictClinicsFrom.ContainsKey(clinicTo.ClinicNum))
            {
                MsgBox.Show(this, "The 'To' clinic should not also be one of the 'From' clinics.");
                return;
            }
            Dictionary <long, int> dictClinFromCounts = Clinics.GetClinicalPatientCount(true)
                                                        .Where(x => dictClinicsFrom.ContainsKey(x.Key)).ToDictionary(x => x.Key, x => x.Value);

            if (dictClinFromCounts.Sum(x => x.Value) == 0)
            {
                MsgBox.Show(this, "There are no patients assigned to the selected clinics.");
                return;
            }
            string msg = Lan.g(this, "This will move all patients to") + " " + clinicTo.Abbr + " " + Lan.g(this, "from the following clinics") + ":\r\n"
                         + string.Join("\r\n", dictClinFromCounts.Select(x => dictClinicsFrom[x.Key].Abbr)) + "\r\n" + Lan.g(this, "Continue?");

            if (MessageBox.Show(msg, "", MessageBoxButtons.YesNo) != DialogResult.Yes)
            {
                return;
            }
            ODProgress.ShowAction(() => {
                int patsMoved             = 0;
                List <Action> listActions = dictClinFromCounts.Select(x => new Action(() => {
                    Patients.ChangeClinicsForAll(x.Key, clinicTo.ClinicNum);                           //update all clinicNums to new clinic
                    Clinic clinicCur;
                    SecurityLogs.MakeLogEntry(Permissions.PatientEdit, 0, "Clinic changed for " + x.Value + " patients from "
                                              + (dictClinicsFrom.TryGetValue(x.Key, out clinicCur)?clinicCur.Abbr:"") + " to " + clinicTo.Abbr + ".");
                    patsMoved += x.Value;
                    ClinicEvent.Fire(ODEventType.Clinic, Lan.g(this, "Moved patients") + ": " + patsMoved + " " + Lan.g(this, "out of") + " "
                                     + dictClinFromCounts.Sum(y => y.Value));
                })).ToList();
                ODThread.RunParallel(listActions, TimeSpan.FromMinutes(2));
            },
                                  startingMessage: Lan.g(this, "Moving patients") + "...",
                                  eventType: typeof(ClinicEvent),
                                  odEventType: ODEventType.Clinic);
            _dictClinicalCounts = Clinics.GetClinicalPatientCount();
            FillGrid();
            MsgBox.Show(this, "Done");
        }
 ///<summary>Returns false if the backup, repair, or the optimze failed.
 ///Set isSilent to true to suppress the failure message boxes.  However, progress windows will always be shown.</summary>
 public static bool BackupRepairAndOptimize(bool isSilent, BackupLocation backupLocation, bool isSecurityLogged = true)
 {
     if (!MakeABackup(isSilent, backupLocation, isSecurityLogged))
     {
         return(false);
     }
     try {
         ODProgress.ShowAction(() => DatabaseMaintenances.RepairAndOptimize(),
                               eventType: typeof(MiscDataEvent),
                               odEventType: ODEventType.MiscData);
     }
     catch (Exception ex) {           //MiscData.MakeABackup() could have thrown an exception.
         //Show the user that something what went wrong when not in silent mode.
         if (!isSilent)
         {
             if (ex.Message != "")
             {
                 MessageBox.Show(ex.Message);
             }
             MsgBox.Show("FormDatabaseMaintenance", "Optimize and Repair failed.");
         }
         return(false);
     }
     return(true);
 }
        ///<summary>Using shown so we can properly display a progress bar on the initial fillgrid.</summary>
        private void FormFamilyBalancer_Shown(object sender, EventArgs e)
        {
            Action actionCloseProgress = ODProgress.Show(ODEventType.Billing, startingMessage: "Loading first batch.  Please wait...");

            FillNextBatch();
            actionCloseProgress();
        }
        private void butHideUnused_Click(object sender, EventArgs e)
        {
            if (!MsgBox.Show(this, MsgBoxButtons.OKCancel, "Hide fee schedules that are not in use by insurance plans, patients, or providers?\r\n"
                             + "A backup of the database will be made first."))
            {
                return;
            }
            bool   hasChanged     = FeeScheds.Sync(_listFeeScheds, _listFeeSchedsOld);
            Action actionProgress = ODProgress.Show(ODEventType.HideUnusedFeeSchedules, startingMessage: Lans.g(this, "Backing up database..."));

            try {
                MiscData.MakeABackup();
            }
            catch (Exception ex) {
                actionProgress?.Invoke();
                FriendlyException.Show(Lans.g(this, "Unable to make a backup. No fee schedules have been altered."), ex);
                return;
            }
            ODEvent.Fire(ODEventType.HideUnusedFeeSchedules, Lans.g(this, "Hiding unused fee schedules..."));
            long countChanged = FeeScheds.HideUnusedScheds();

            if (hasChanged || countChanged > 0)
            {
                DataValid.SetInvalid(InvalidType.FeeScheds);
            }
            actionProgress?.Invoke();
            MessageBox.Show(countChanged.ToString() + " " + Lans.g(this, "unused fee schedules hidden."));
            _listFeeScheds    = FeeScheds.GetDeepCopy(_isSelectionMode);
            _listFeeSchedsOld = _listFeeScheds.Select(x => x.Copy()).ToList();
            FillGrid();
        }
        private void FillGrid()
        {
            ODProgress.ShowAction(            //Show progress window while filling the grid.
                () => {
                gridMain.BeginUpdate();
                gridMain.ListGridColumns.Clear();
                GridColumn col = new GridColumn(Lan.g(this, "Patient"), 140);
                gridMain.ListGridColumns.Add(col);
                col = new GridColumn(Lan.g(this, "Date"), 65);
                gridMain.ListGridColumns.Add(col);
                col = new GridColumn(Lan.g(this, "Status"), 110);
                gridMain.ListGridColumns.Add(col);
                col = new GridColumn(Lan.g(this, "Prov"), 50);
                gridMain.ListGridColumns.Add(col);
                col = new GridColumn(Lan.g(this, "Procedures"), 150);
                gridMain.ListGridColumns.Add(col);
                col = new GridColumn(Lan.g(this, "Notes"), 200);
                gridMain.ListGridColumns.Add(col);
                gridMain.ListGridRows.Clear();
                GridRow row;
                Dictionary <long, string> dictPatNames = Patients.GetLimForPats(_listPlannedAppts.Select(x => x.PatNum).ToList())
                                                         .ToDictionary(x => x.PatNum, x => x.GetNameLF());
                foreach (Appointment apt in _listPlannedAppts)
                {
                    row            = new GridRow();
                    string patName = Lan.g(this, "UNKNOWN");
                    dictPatNames.TryGetValue(apt.PatNum, out patName);
                    row.Cells.Add(patName);
                    if (apt.AptDateTime.Year < 1880)
                    {
                        row.Cells.Add("");
                    }
                    else
                    {
                        row.Cells.Add(apt.AptDateTime.ToShortDateString());
                    }
                    row.Cells.Add(Defs.GetName(DefCat.RecallUnschedStatus, apt.UnschedStatus));
                    if (apt.IsHygiene)
                    {
                        Provider provHyg = Providers.GetFirstOrDefault(x => x.ProvNum == apt.ProvHyg);
                        row.Cells.Add(provHyg == null?Lan.g(this, "INVALID"):provHyg.Abbr);
                    }
                    else
                    {
                        Provider prov = Providers.GetFirstOrDefault(x => x.ProvNum == apt.ProvNum);
                        row.Cells.Add(prov == null?Lan.g(this, "INVALID"):prov.Abbr);
                    }
                    row.Cells.Add(apt.ProcDescript);
                    row.Cells.Add(apt.Note);

                    gridMain.ListGridRows.Add(row);
                }
                gridMain.EndUpdate();
            },
                startingMessage: Lans.g(this, "Filling the Planned Appointments Grid..."),
                eventType: typeof(PlannedTrackerEvent),
                odEventType: ODEventType.PlannedTracker
                );
        }
        private void butGetNextBatch_Click(object sender, EventArgs e)
        {
            Action actionCloseProgress = ODProgress.Show(ODEventType.Billing, startingMessage: "Retrieving family information.  Please wait...");

            ODEvent.Fire(ODEventType.Billing, Lan.g(this, "Filling the grid.  This may take awhile..."));
            FillNextBatch();
            actionCloseProgress();
        }
 private void FillGrid()
 {
     ODProgress.ShowAction(
         () => {
         RefreshReport();
         gridMain.BeginUpdate();
         if (gridMain.ListGridColumns.Count == 0)
         {
             gridMain.ListGridColumns.Add(new GridColumn(Lan.g(this, "Patient"), _colWidthPatName, GridSortingStrategy.StringCompare));
             gridMain.ListGridColumns.Add(new GridColumn(Lan.g(this, "Date"), _colWidthProcDate, HorizontalAlignment.Center, GridSortingStrategy.DateParse));
             gridMain.ListGridColumns.Add(new GridColumn(Lan.g(this, "Code"), _colWidthProcCode, GridSortingStrategy.StringCompare));
             gridMain.ListGridColumns.Add(new GridColumn(Lan.g(this, "Tth"), _colWidthProcTth, GridSortingStrategy.StringCompare));
             gridMain.ListGridColumns.Add(new GridColumn(Lan.g(this, "Prov"), _colWidthProv, GridSortingStrategy.StringCompare));
             gridMain.ListGridColumns.Add(new GridColumn(Lan.g(this, "Fee"), _colWidthFee, HorizontalAlignment.Right, GridSortingStrategy.AmountParse));
             gridMain.ListGridColumns.Add(new GridColumn(Lan.g(this, "Ins Paid"), _colWidthInsPay, HorizontalAlignment.Right, GridSortingStrategy.AmountParse));
             gridMain.ListGridColumns.Add(new GridColumn(Lan.g(this, "Write-off"), _colWidthWO, HorizontalAlignment.Right, GridSortingStrategy.AmountParse));
             gridMain.ListGridColumns.Add(new GridColumn(Lan.g(this, "Pt Paid"), _colWidthPtPaid, HorizontalAlignment.Right, GridSortingStrategy.AmountParse));
             gridMain.ListGridColumns.Add(new GridColumn(Lan.g(this, "Adjust"), _colWidthAdj, HorizontalAlignment.Right, GridSortingStrategy.AmountParse));
             gridMain.ListGridColumns.Add(new GridColumn(Lan.g(this, "Overpayment"), _colWidthOverpay, HorizontalAlignment.Right, GridSortingStrategy.AmountParse));
         }
         gridMain.ListGridRows.Clear();
         GridRow row;
         for (int i = 0; i < _myReport.ReportObjects.Count; i++)
         {
             if (_myReport.ReportObjects[i].ObjectType != ReportObjectType.QueryObject)
             {
                 continue;
             }
             QueryObject queryObj = (QueryObject)_myReport.ReportObjects[i];
             for (int j = 0; j < queryObj.ReportTable.Rows.Count; j++)
             {
                 DataRow rowCur = queryObj.ReportTable.Rows[j];
                 row            = new GridRow();
                 row.Cells.Add(rowCur["patientName"].ToString());
                 row.Cells.Add(PIn.Date(rowCur["ProcDate"].ToString()).ToShortDateString());
                 row.Cells.Add(PIn.String(rowCur["ProcCode"].ToString()));
                 row.Cells.Add(PIn.String(rowCur["ToothNum"].ToString()));
                 row.Cells.Add(PIn.String(rowCur["Abbr"].ToString()));
                 row.Cells.Add(PIn.Double(rowCur["fee"].ToString()).ToString("c"));
                 row.Cells.Add(PIn.Double(rowCur["insPaid"].ToString()).ToString("c"));
                 row.Cells.Add(PIn.Double(rowCur["wo"].ToString()).ToString("c"));
                 row.Cells.Add(PIn.Double(rowCur["ptPaid"].ToString()).ToString("c"));
                 row.Cells.Add(PIn.Double(rowCur["adjAmt"].ToString()).ToString("c"));
                 row.Cells.Add(PIn.Double(rowCur["overpay"].ToString()).ToString("c"));
                 row.Tag = rowCur;
                 gridMain.ListGridRows.Add(row);
             }
         }
         gridMain.EndUpdate();
     },
         startingMessage: "Refreshing Grid...",
         actionException: e => this.Invoke(() => {
         FriendlyException.Show(Lan.g(this, "Error filling the Procedures Overpaid grid."), e);
     })
         );
 }
 private void FormClaimAttachment_Shown(object sender, EventArgs e)
 {
     FillGrid();
     ODProgress.ShowAction(() => { ValidateClaimHelper(); }, "Communicating with DentalXChange...");
     //Check for if the attachmentID is already in use. If so inform the user they need to redo their attachments.
     if (textClaimStatus.Text.ToUpper().Contains("ATTACHMENT ID HAS BEEN ASSOCIATED TO A DIFFERENT CLAIM") ||
         textClaimStatus.Text.ToUpper().Contains("HAS ALREADY BEEN DELIVERED TO THE PAYER"))
     {
         MessageBox.Show("The attachment ID is associated to another claim. Please redo your attachments.");
         ClearAttachmentID();
         ODProgress.ShowAction(() => { ValidateClaimHelper(); }, "Re-validating the claim...");
     }
 }
Exemple #9
0
        ///<summary>Runs the workerDelegate on a separate thread and displays a progress window while the thread is running.</summary>
        public static void ShowProgressForThread(ODThread.WorkerDelegate workerDelegate, Control parent, string startingMessage = "Please Wait...",
                                                 ProgBarStyle progStyle = ProgBarStyle.Blocks, string threadName = "ODProgressThread", ODThread.ExceptionDelegate exceptionHandler = null)
        {
            ODProgress prog   = new ODProgress(Lan.g(parent, startingMessage), progStyle);
            ODThread   thread = new ODThread(workerDelegate);

            if (exceptionHandler != null)
            {
                thread.AddExceptionHandler(exceptionHandler);
            }
            thread.Name        = threadName;
            thread.ProgressLog = prog;
            thread.Start(true);
            prog.ShowDialog(parent);
        }
Exemple #10
0
 private void butArchive_Click(object sender, EventArgs e)
 {
     #region Validation
     if (checkArchiveDoBackupFirst.Checked)              //We only need to validate the backup settings if the user wants to make a backup first
     {
         if (!MsgBox.Show(MsgBoxButtons.YesNo, "To make a backup of the database, ensure no other machines are currently using OpenDental. Proceed?"))
         {
             return;
         }
         //Validation
         if (string.IsNullOrWhiteSpace(textArchiveServerName.Text))
         {
             MsgBox.Show(this, "Please specify a Server Name.");
             return;
         }
         if (string.IsNullOrWhiteSpace(textArchiveUser.Text))
         {
             MsgBox.Show(this, "Please enter a User.");
             return;
         }
         if (string.IsNullOrWhiteSpace(PrefC.GetString(PrefName.ArchiveKey)))                 //If archive key isn't set, generate a new one.
         {
             string archiveKey = MiscUtils.CreateRandomAlphaNumericString(10);
             Prefs.UpdateString(PrefName.ArchiveKey, archiveKey);
         }
     }
     #endregion
     //Create an ODProgress
     ODProgress.ShowAction(() => {
         //Make a backup if needed
         if (checkArchiveDoBackupFirst.Checked)
         {
             try {
                 MiscData.MakeABackup(textArchiveServerName.Text, textArchiveUser.Text, textArchivePass.Text, doVerify: true);
             }
             catch (Exception ex) {
                 FriendlyException.Show("An error occurred backing up the old database. Old data was not removed from the database. " +
                                        "Ensure no other machines are currently using OpenDental and try again.", ex);
                 return;
             }
         }
         //Delete the unnecessary data
         SecurityLogs.DeleteBeforeDateInclusive(dateTimeArchive.Value);
         SecurityLogs.MakeLogEntry(Permissions.Backup, 0, $"SecurityLog and SecurityLogHashes on/before {dateTimeArchive.Value} deleted.");
     },
                           eventType: typeof(MiscDataEvent),
                           odEventType: ODEventType.MiscData);
 }
Exemple #11
0
        ///<summary>This is a wrapper method for MiscData.MakeABackup() that will show a progress window so that the user can see progress.
        ///Set isSilent to true to suppress the failure message boxes.  However, the progress window will always be shown.
        ///Returns false if making a backup failed.</summary>
        public static bool MakeABackup(bool isSilent, BackupLocation backupLocation, bool isSecurityLogged = true)
        {
            if (DataConnection.DBtype == DatabaseType.Oracle)
            {
                return(false);               //Because MiscData.MakeABackup() is not yet Oracle compatible.
            }
#if DEBUG
            switch (MessageBox.Show("Would you like to make a backup of the DB?", "DEBUG ONLY", MessageBoxButtons.YesNoCancel))
            {
            case DialogResult.Cancel:
                return(false);

            case DialogResult.No:
                return(true);

            case DialogResult.Yes:
            default:
                //do nothing, make backup like usual.
                break;
            }
#endif
            //Create a thread that will show a window and then stay open until the closing action is called.
            try {
                ODProgress.ShowAction(() => MiscData.MakeABackup(),
                                      eventType: typeof(MiscDataEvent),
                                      odEventType: ODEventType.MiscData);
            }
            catch (Exception ex) {           //MiscData.MakeABackup() could have thrown an exception.
                //Show the user that something what went wrong when not in silent mode.
                if (!isSilent)
                {
                    if (ex.Message != "")
                    {
                        MessageBox.Show(ex.Message);
                    }
                    //Reusing translation in ClassConvertDatabase, since it is most likely the only place a translation would have been performed previously.
                    MsgBox.Show("ClassConvertDatabase", "Backup failed. Your database has not been altered.");
                }
                return(false);
            }
            if (isSecurityLogged && PrefC.GetStringNoCache(PrefName.UpdateStreamLinePassword) != "abracadabra")
            {
                SecurityLogs.MakeLogEntryNoCache(Permissions.Backup, 0, Lan.g("Backups", "A backup was created when running the") + " " + backupLocation.ToString());
            }
            return(true);
        }
Exemple #12
0
        private bool RunAgingEnterprise(DateTime dateCalc)
        {
            DateTime dateLastAging = PrefC.GetDate(PrefName.DateLastAging);

            if (dateLastAging.Date == dateCalc.Date)
            {
                if (MessageBox.Show(this, Lan.g(this, "Aging has already been calculated for") + " " + dateCalc.ToShortDateString() + " "
                                    + Lan.g(this, "and does not normally need to run more than once per day.\r\n\r\nRun anyway?"), "", MessageBoxButtons.YesNo) != DialogResult.Yes)
                {
                    return(false);
                }
            }
            //Refresh prefs because AgingBeginDateTime is very time sensitive
            Prefs.RefreshCache();
            DateTime dateTAgingBeganPref = PrefC.GetDateT(PrefName.AgingBeginDateTime);

            if (dateTAgingBeganPref > DateTime.MinValue)
            {
                MessageBox.Show(this, Lan.g(this, "You cannot run aging until it has finished the current calculations which began on") + " "
                                + dateTAgingBeganPref.ToString() + ".\r\n" + Lans.g(this, "If you believe the current aging process has finished, a user with SecurityAdmin permission "
                                                                                    + "can manually clear the date and time by going to Setup | Miscellaneous and pressing the 'Clear' button."));
                return(false);
            }
            SecurityLogs.MakeLogEntry(Permissions.AgingRan, 0, "Aging Ran - Aging Form");
            Prefs.UpdateString(PrefName.AgingBeginDateTime, POut.DateT(MiscData.GetNowDateTime(), false)); //get lock on pref to block others
            Signalods.SetInvalid(InvalidType.Prefs);                                                       //signal a cache refresh so other computers will have the updated pref as quickly as possible
            Cursor = Cursors.WaitCursor;
            bool result = true;

            ODProgress.ShowAction(
                () => {
                Ledgers.ComputeAging(0, dateCalc);
                Prefs.UpdateString(PrefName.DateLastAging, POut.Date(dateCalc, false));
            },
                startingMessage: Lan.g(this, "Calculating enterprise aging for all patients as of") + " " + dateCalc.ToShortDateString() + "...",
                actionException: ex => {
                Ledgers.AgingExceptionHandler(ex, this);
                result = false;
            }
                );
            Cursor = Cursors.Default;
            Prefs.UpdateString(PrefName.AgingBeginDateTime, "");           //clear lock on pref whether aging was successful or not
            Signalods.SetInvalid(InvalidType.Prefs);
            return(result);
        }
Exemple #13
0
        private void butOK_Click(object sender, System.EventArgs e)
        {
            if (textDateCalc.errorProvider1.GetError(textDateCalc) != "")
            {
                MsgBox.Show(this, "Please fix data entry errors first.");
                return;
            }
            DateTime dateCalc = PIn.Date(textDateCalc.Text);

            if (PrefC.GetBool(PrefName.AgingIsEnterprise))
            {
                //if this is true, dateCalc has to be DateTime.Today and aging calculated daily not monthly.
                if (!RunAgingEnterprise(dateCalc))
                {
                    //Errors displayed from RunAgingEnterprise
                    return;
                }
            }
            else
            {
                SecurityLogs.MakeLogEntry(Permissions.AgingRan, 0, "Aging Ran - Aging Form");
                Cursor = Cursors.WaitCursor;
                bool result = true;
                ODProgress.ShowAction(() => Ledgers.ComputeAging(0, dateCalc),
                                      startingMessage: Lan.g(this, "Calculating aging for all patients as of") + " " + dateCalc.ToShortDateString() + "...",
                                      actionException: ex => {
                    Ledgers.AgingExceptionHandler(ex, this);
                    result = false;
                }
                                      );
                Cursor = Cursors.Default;
                if (!result)
                {
                    DialogResult = DialogResult.Cancel;
                    return;
                }
                if (Prefs.UpdateString(PrefName.DateLastAging, POut.Date(dateCalc, false)))
                {
                    DataValid.SetInvalid(InvalidType.Prefs);
                }
            }
            MsgBox.Show(this, "Aging Complete");
            DialogResult = DialogResult.OK;
        }
        private bool SyncPhoneNums()
        {
            string syncError = null;

            Cursor = Cursors.WaitCursor;
            ODProgress.ShowAction(
                () => PhoneNumbers.SyncAllPats(),
                startingMessage: Lan.g(this, "Syncing all patient phone numbers to the phonenumber table") + "...",
                actionException: ex => syncError = Lan.g(this, "The patient phone number sync failed with the message") + ":\r\n" + ex.Message + "\r\n" + Lan.g(this, "Please try again.")
                );
            Cursor = Cursors.Default;
            if (!string.IsNullOrEmpty(syncError))
            {
                MessageBox.Show(this, syncError);
                return(false);
            }
            _usePhonenumTable = YN.Yes;          //so it won't sync again if you clicked the button
            return(true);
        }
Exemple #15
0
        private void butSynch_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            GC.Collect();            //free up resources since this could take a lot of memory
            DataValid.SetInvalid(InvalidType.RecallTypes);
            Action actionCloseRecallSyncProgress = ODProgress.Show(ODEventType.RecallSync, typeof(RecallSyncEvent), Lan.g(this, "Running Prep Queries") + "...", false, true);
            bool   isSyncCompleted = Recalls.SynchAllPatients();

            actionCloseRecallSyncProgress?.Invoke();
            GC.Collect();            //clean up resources, force the garbage collector to collect since resources may remain tied-up
            Cursor = Cursors.Default;
            if (isSyncCompleted)
            {
                changed = false;
                MsgBox.Show(this, "Done.");
            }
            else
            {
                MsgBox.Show(this, "Synch is currently running from a different workstation.");
            }
        }
Exemple #16
0
 private void FormRecallTypes_FormClosing(object sender, FormClosingEventArgs e)
 {
     if (changed)
     {
         DataValid.SetInvalid(InvalidType.RecallTypes);
         if (MessageBox.Show(Lan.g(this, "Recalls for all patients should be synchronized.  Synchronize now?"), "", MessageBoxButtons.YesNo)
             == DialogResult.Yes)
         {
             Cursor = Cursors.WaitCursor;
             GC.Collect();                    //free up resources since this could take a lot of memory
             Action actionCloseRecallSyncProgress = ODProgress.Show(ODEventType.RecallSync, typeof(RecallSyncEvent), Lan.g(this, "Running Prep Queries") + "...");
             bool   isSyncSuccessful = Recalls.SynchAllPatients();
             actionCloseRecallSyncProgress?.Invoke();
             GC.Collect();                    //clean up resources, force the garbage collector to collect since resources may remain tied-up
             Cursor = Cursors.Default;
             if (!isSyncSuccessful)
             {
                 MsgBox.Show(this, "Synch is currently running from a different workstation.  Recalls should be synchronized again later.");
             }
         }
     }
 }
        private void FormEServicesSetup_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (DialogResult == DialogResult.Abort || !Security.IsAuthorized(Permissions.EServicesSetup, true))
            {
                return;
            }
            //Anything they could have modified should have been disabled on load anyways.
            if (!SaveForm())              //Something failed. Ask the user if they are ok with exiting and not saving.
            {
                if (!MsgBox.Show(this, MsgBoxButtons.OKCancel, "Validation failed and no changes were saved. Would you like to close without saving?"))
                {
                    //User wants to keep the form open.
                    e.Cancel = true;
                }
            }
            //Call this a second time so we can log if any important changes were made to this form.
            //_signupOut gets filled on load and should not be null at this point
            Action actionCloseProgress = ODProgress.Show(ODEventType.EServices, typeof(EServicesEvent), "Saving eServices...");

            WebServiceMainHQProxy.GetEServiceSetupFull(GetUserSignupPortalPermissions(), oldSignupOut: _signupOut);
            actionCloseProgress?.Invoke();
        }
Exemple #18
0
        private void FillGridMain()
        {
            string[]      searchTokens  = textSearch.Text.ToLower().Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
            long[]        userNums      = new long[0];
            JobCategory[] jobCats       = new JobCategory[0];
            JobPhase[]    jobPhases     = new JobPhase[0];
            long[]        jobPriorities = new long[0];
            if (listBoxUsers.SelectedIndices.Count > 0 && !listBoxUsers.SelectedIndices.Contains(0))
            {
                userNums = listBoxUsers.SelectedIndices.Cast <int>().Select(x => _listUsers[x - 1].UserNum).ToArray();
            }
            if (listBoxCategory.SelectedIndices.Count > 0 && !listBoxCategory.SelectedIndices.Contains(0))
            {
                jobCats = listBoxCategory.SelectedIndices.Cast <int>().Select(x => (JobCategory)(x - 1)).ToArray();
            }
            if (listBoxPhases.SelectedIndices.Count > 0 && !listBoxPhases.SelectedIndices.Contains(0))
            {
                jobPhases = listBoxPhases.SelectedIndices.Cast <int>().Select(x => (JobPhase)(x - 1)).ToArray();
            }
            if (listBoxPriorities.SelectedIndices.Count > 0 && !listBoxPriorities.SelectedIndices.Contains(0))
            {
                jobPriorities = listBoxPriorities.GetListSelected <Def>().Select(x => x.DefNum).ToArray();
            }
            Action actionCloseProgress = ODProgress.Show(ODEventType.Job, typeof(JobEvent), "Getting job data...");

            #region Get Missing Data
            //This entire section will go out to the database and get any data that is unknown based on some of the filters.
            //The other filters will be applied later via the cached lists.
            try {
                List <Job> listJobs = Jobs.GetForSearch(dateFrom.Value, dateTo.Value, jobPhases.ToList(), jobPriorities.ToList(), _listJobsAll.Select(x => x.JobNum).ToList());
                Jobs.FillInMemoryLists(listJobs, true);
                _listJobsAll.AddRange(listJobs);
            }
            catch (OutOfMemoryException oome) {
                actionCloseProgress();
                oome.DoNothing();
                MsgBox.Show(this, "Not enough memory to complete the search.  Please refine search filters.");
                return;
            }
            //Only get the feature request entries that we care about.
            JobEvent.Fire(ODEventType.Job, "Getting feature request data...");
            List <long> listFeatureRequestNums = _listJobsAll.SelectMany(x => x.ListJobLinks)
                                                 .Where(x => x.LinkType == JobLinkType.Request)
                                                 .Select(x => x.FKey)
                                                 .Distinct()
                                                 .ToList();
            //Don't download any feature requests that we already know about.
            listFeatureRequestNums.RemoveAll(x => x.In(_listFeatureRequestsAll.Select(y => y.FeatReqNum)));
            if (!listFeatureRequestNums.IsNullOrEmpty())
            {
                _listFeatureRequestsAll.AddRange(FeatureRequests.GetAll(listFeatureRequestNums));
            }
            //Only get the bug entries that we care about.
            JobEvent.Fire(ODEventType.Job, "Getting bug data...");
            List <long> listBugIds = _listJobsAll.SelectMany(x => x.ListJobLinks)
                                     .Where(x => x.LinkType == JobLinkType.Bug)
                                     .Select(x => x.FKey)
                                     .Distinct()
                                     .ToList();
            //Don't download any bugs that we already know about.
            listBugIds.RemoveAll(x => x.In(_listBugsAll.Select(y => y.BugId)));
            if (!listBugIds.IsNullOrEmpty())
            {
                _listBugsAll.AddRange(Bugs.GetMany(listBugIds));
            }
            #endregion
            JobEvent.Fire(ODEventType.Job, "Filling grid...");
            gridMain.BeginUpdate();
            gridMain.ListGridColumns.Clear();
            gridMain.ListGridColumns.Add(new GridColumn("Job\r\nNum", 50, GridSortingStrategy.AmountParse));
            gridMain.ListGridColumns.Add(new GridColumn("Priority", 50, HorizontalAlignment.Center));
            gridMain.ListGridColumns.Add(new GridColumn("Phase", 85));
            gridMain.ListGridColumns.Add(new GridColumn("Category", 80));
            gridMain.ListGridColumns.Add(new GridColumn("Job Title", -1));
            gridMain.ListGridColumns.Add(new GridColumn("Version", 80));
            gridMain.ListGridColumns.Add(new GridColumn("Est. Version", 80));
            gridMain.ListGridColumns.Add(new GridColumn("Expert", 75));
            gridMain.ListGridColumns.Add(new GridColumn("Engineer", 75));
            gridMain.ListGridColumns.Add(new GridColumn("Est.\r\nHours", 60, GridSortingStrategy.AmountParse));
            gridMain.ListGridColumns.Add(new GridColumn("Act.\r\nHours", 60, GridSortingStrategy.AmountParse));
            gridMain.ListGridColumns.Add(new GridColumn("Job\r\nMatch", 45, HorizontalAlignment.Center));
            gridMain.ListGridColumns.Add(new GridColumn("Bug\r\nMatch", 45, HorizontalAlignment.Center));
            gridMain.ListGridColumns.Add(new GridColumn("FR\r\nMatch", 45, HorizontalAlignment.Center));
            gridMain.ListGridRows.Clear();
            _listJobsFiltered = new List <Job>();
            foreach (Job jobCur in _listJobsAll)
            {
                if (jobCats.Length > 0 && !jobCats.Contains(jobCur.Category))
                {
                    continue;
                }
                if (jobPhases.Length > 0 && !jobPhases.Contains(jobCur.PhaseCur))
                {
                    continue;
                }
                if (jobPriorities.Length > 0 && !jobPriorities.Contains(jobCur.Priority))
                {
                    continue;
                }
                if (userNums.Length > 0 && !userNums.All(x => Jobs.GetUserNums(jobCur).Contains(x)))
                {
                    continue;
                }
                if (!jobCur.DateTimeEntry.Between(dateFrom.Value, dateTo.Value))
                {
                    continue;
                }
                bool isJobMatch        = false;
                bool isBugMatch        = false;
                bool isFeatureReqMatch = false;
                if (searchTokens.Length > 0)
                {
                    bool       addRow   = false;
                    List <Bug> listBugs = jobCur.ListJobLinks.FindAll(x => x.LinkType == JobLinkType.Bug)
                                          .Select(x => _listBugsAll.FirstOrDefault(y => x.FKey == y.BugId))
                                          .Where(x => x != null)
                                          .ToList();
                    List <FeatureRequest> listFeatures = jobCur.ListJobLinks.FindAll(x => x.LinkType == JobLinkType.Request)
                                                         .Select(x => _listFeatureRequestsAll.FirstOrDefault(y => x.FKey == y.FeatReqNum))
                                                         .Where(x => x != null)
                                                         .ToList();
                    foreach (string token in searchTokens.Distinct())
                    {
                        bool isFound = false;
                        //JOB MATCHES
                        if (jobCur.Title.ToLower().Contains(token) ||
                            jobCur.Implementation.ToLower().Contains(token) ||
                            jobCur.Requirements.ToLower().Contains(token) ||
                            jobCur.Documentation.ToLower().Contains(token) ||
                            jobCur.JobNum.ToString().Contains(token))
                        {
                            isFound    = true;
                            isJobMatch = true;
                        }
                        //BUG MATCHES
                        if (!isFound || !isBugMatch)
                        {
                            if (listBugs.Any(x => x.Description.ToLower().Contains(token) || x.Discussion.ToLower().Contains(token)))
                            {
                                isFound    = true;
                                isBugMatch = true;
                            }
                        }
                        //FEATURE REQUEST MATCHES
                        if (!isFound || !isFeatureReqMatch)
                        {
                            if (listFeatures.Any(x => x.Description.Contains(token) || x.FeatReqNum.ToString().ToLower().Contains(token)))
                            {
                                isFound           = true;
                                isFeatureReqMatch = true;
                            }
                        }
                        addRow = isFound;
                        if (!isFound)
                        {
                            break;                            //stop looking for additional tokens, we didn't find this one.
                        }
                    }
                    if (!addRow)
                    {
                        continue;                        //we did not find one of the search terms.
                    }
                }
                _listJobsFiltered.Add(jobCur);
                Def     jobPriority = _listJobPriorities.FirstOrDefault(y => y.DefNum == jobCur.Priority);
                GridRow row         = new GridRow();
                row.Cells.Add(jobCur.JobNum.ToString());
                row.Cells.Add(new GridCell(jobPriority.ItemName)
                {
                    ColorBackG = jobPriority.ItemColor,
                    ColorText  = (jobCur.Priority == _listJobPriorities.FirstOrDefault(y => y.ItemValue.Contains("Urgent")).DefNum) ? Color.White : Color.Black,
                });
                row.Cells.Add(jobCur.PhaseCur.ToString());
                row.Cells.Add(jobCur.Category.ToString());
                row.Cells.Add(jobCur.Title);
                row.Cells.Add(jobCur.JobVersion.ToString());
                row.Cells.Add(jobCur.ProposedVersion.ToString());
                row.Cells.Add(Userods.GetName(jobCur.UserNumExpert));
                row.Cells.Add(Userods.GetName(jobCur.UserNumEngineer));
                row.Cells.Add(jobCur.HoursEstimate.ToString());
                row.Cells.Add(jobCur.HoursActual.ToString());
                row.Cells.Add(isJobMatch ? "X" : "");
                row.Cells.Add(isBugMatch ? "X" : "");
                row.Cells.Add(new GridCell(isFeatureReqMatch ? "X" : "")
                {
                    ColorBackG = _listFeatureRequestsAll.Count == 0 ? Control.DefaultBackColor : Color.Empty
                });
                row.Tag = jobCur;
                gridMain.ListGridRows.Add(row);
            }
            gridMain.EndUpdate();
            actionCloseProgress();
        }
        ///<summary>Return false to indicate exit app.  Only called when program first starts up at the beginning of FormOpenDental.PrefsStartup.</summary>
        public bool Convert(string fromVersion, string toVersion, bool isSilent, Form currentForm, bool useDynamicMode)
        {
            FromVersion = new Version(fromVersion);
            ToVersion   = new Version(toVersion);
            if (FromVersion >= new Version("3.4.0") && PrefC.GetBool(PrefName.CorruptedDatabase))
            {
                FormOpenDental.ExitCode = 201;              //Database was corrupted due to an update failure
                if (!isSilent)
                {
                    MsgBox.Show(this, "Your database is corrupted because an update failed.  Please contact us.  This database is unusable and you will need to restore from a backup.");
                }
                return(false);               //shuts program down.
            }
            //There was a 19.3.0 convert method released in the 19.2.3 version.
            //We have to treat 19.3.0 as 19.2.3 so newer convert methods will run.
            if (!ODBuild.IsDebug() && FromVersion.ToString() == "19.3.0.0")
            {
                FromVersion = new Version("19.2.3.0");
                ODException.SwallowAnyException(() => Prefs.UpdateString(PrefName.DataBaseVersion, "19.2.3.0"));
            }
            if (FromVersion == ToVersion)
            {
                return(true);                         //no conversion necessary
            }
            if (FromVersion.CompareTo(ToVersion) > 0) //"Cannot convert database to an older version."
            //no longer necessary to catch it here.  It will be handled soon enough in CheckProgramVersion
            {
                return(true);
            }
            if (FromVersion < new Version("2.8.0"))
            {
                FormOpenDental.ExitCode = 130;              //Database must be upgraded to 2.8 to continue
                if (!isSilent)
                {
                    MsgBox.Show(this, "This database is too old to easily convert in one step. Please upgrade to 2.1 if necessary, then to 2.8.  Then you will be able to upgrade to this version. We apologize for the inconvenience.");
                }
                return(false);
            }
            if (FromVersion < new Version("6.6.2"))
            {
                FormOpenDental.ExitCode = 131;              //Database must be upgraded to 11.1 to continue
                if (!isSilent)
                {
                    MsgBox.Show(this, "This database is too old to easily convert in one step. Please upgrade to 11.1 first.  Then you will be able to upgrade to this version. We apologize for the inconvenience.");
                }
                return(false);
            }
            if (FromVersion < new Version("3.0.1"))
            {
                if (!isSilent)
                {
                    MsgBox.Show(this, "This is an old database.  The conversion must be done using MySQL 4.1 (not MySQL 5.0) or it will fail.");
                }
            }
            if (FromVersion.ToString() == "2.9.0.0" || FromVersion.ToString() == "3.0.0.0" || FromVersion.ToString() == "4.7.0.0")
            {
                FormOpenDental.ExitCode = 190;              //Cannot convert this database version which was only for development purposes
                if (!isSilent)
                {
                    MsgBox.Show(this, "Cannot convert this database version which was only for development purposes.");
                }
                return(false);
            }
            if (FromVersion > new Version("4.7.0") && FromVersion.Build == 0)
            {
                FormOpenDental.ExitCode = 190;              //Cannot convert this database version which was only for development purposes
                if (!isSilent)
                {
                    MsgBox.Show(this, "Cannot convert this database version which was only for development purposes.");
                }
                return(false);
            }
            if (FromVersion >= ConvertDatabases.LatestVersion)
            {
                return(true);               //no conversion necessary
            }
            //Trial users should never be able to update a database.
            if (ODBuild.IsTrial() && PrefC.GetString(PrefName.RegistrationKey) != "") //Allow databases with no reg key to update.  Needed by our conversion department.
            {
                FormOpenDental.ExitCode = 191;                                        //Trial versions cannot connect to live databases
                if (!isSilent)
                {
                    MsgBox.Show(this, "Trial versions cannot connect to live databases.  Please run the Setup.exe in the AtoZ folder to reinstall your original version.");
                }
                return(false);
            }
            string webServiceServerName = PrefC.GetString(PrefName.WebServiceServerName);

            //If the WebServiceServerName name is not set and they are using dynamic mode, continue on to download the binaries in CheckProgramVersion.
            //Or, if they do have the WebServiceServerName set and this is not the computer, continue on to CheckProgramVersion.
            if ((webServiceServerName == "" && useDynamicMode) ||
                (webServiceServerName != "" && !ODEnvironment.IdIsThisComputer(webServiceServerName.ToLower())))
            {
                if (isSilent)
                {
                    FormOpenDental.ExitCode = 141;   //Updates are only allowed from a designated web server
                    return(false);                   //if you are in debug mode and you really need to update the DB, you can manually clear the WebServiceServerName preference.
                }
                //This will be handled in CheckProgramVersion, giving the user option to downgrade or exit program.
                return(true);
            }
            //At this point, the current instance of the program has the ability to execute an upgrade.
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                FormOpenDental.ExitCode = 140;              //Web client cannot convert database
                if (!isSilent)
                {
                    MsgBox.Show(this, "Web client cannot convert database.  Must be using a direct connection.");
                }
                return(false);
            }
            if (ReplicationServers.ServerIsBlocked())
            {
                FormOpenDental.ExitCode = 150;              //Replication server is blocked from performing updates
                if (!isSilent)
                {
                    MsgBox.Show(this, "This replication server is blocked from performing updates.");
                }
                return(false);
            }
            //If MyISAM and InnoDb mix, then try to fix
            string namesInnodb = "";

            if (DataConnection.DBtype == DatabaseType.MySql)           //not for Oracle
            {
                namesInnodb = InnoDb.GetInnodbTableNames();            //Or possibly some other format.
                int numMyisam = DatabaseMaintenances.GetMyisamTableCount();
                if (namesInnodb != "" && numMyisam > 0)
                {
                    if (!isSilent)
                    {
                        MessageBox.Show(Lan.g(this, "A mixture of database tables in InnoDB and MyISAM format were found.  A database backup will now be made, and then the following InnoDB tables will be converted to MyISAM format: ") + namesInnodb);
                    }
                    if (!Shared.MakeABackup(isSilent, BackupLocation.ConvertScript, false))
                    {
                        Cursor.Current          = Cursors.Default;
                        FormOpenDental.ExitCode = 101;                      //Database Backup failed
                        return(false);
                    }
                    if (!DatabaseMaintenances.ConvertTablesToMyisam())
                    {
                        FormOpenDental.ExitCode = 102;                      //Failed to convert InnoDB tables to MyISAM format
                        if (!isSilent)
                        {
                            MessageBox.Show(Lan.g(this, "Failed to convert InnoDB tables to MyISAM format. Please contact support."));
                        }
                        return(false);
                    }
                    if (!isSilent)
                    {
                        MessageBox.Show(Lan.g(this, "All tables converted to MyISAM format successfully."));
                    }
                    namesInnodb = "";
                }
                if (namesInnodb == "" && numMyisam > 0)             //if all tables are myisam
                //but default storage engine is innodb, then kick them out.
                {
                    if (DatabaseMaintenances.GetStorageEngineDefaultName().ToUpper() != "MYISAM") //Probably InnoDB but could be another format.
                    {
                        FormOpenDental.ExitCode = 103;                                            //Default database .ini setting is innoDB
                        if (!isSilent)
                        {
                            MessageBox.Show(Lan.g(this, "The database tables are in MyISAM format, but the default database engine format is InnoDB. You must change the default storage engine within the my.ini (or my.cnf) file on the database server and restart MySQL in order to fix this problem. Exiting."));
                        }
                        return(false);
                    }
                }
            }
            if (ODBuild.IsDebug())
            {
                if (!isSilent && MessageBox.Show("You are in Debug mode.  Your database can now be converted" + "\r"
                                                 + "from version" + " " + FromVersion.ToString() + "\r"
                                                 + "to version" + " " + ToVersion.ToString() + "\r"
                                                 + "You can click Cancel to skip conversion and attempt to run the newer code against the older database."
                                                 , "", MessageBoxButtons.OKCancel) != DialogResult.OK)
                {
                    return(true);                   //If user clicks cancel, then do nothing
                }
            }
            else              //release
            {
                if (!isSilent && MessageBox.Show(Lan.g(this, "Your database will now be converted") + "\r"
                                                 + Lan.g(this, "from version") + " " + FromVersion.ToString() + "\r"
                                                 + Lan.g(this, "to version") + " " + ToVersion.ToString() + "\r"
                                                 + Lan.g(this, "The conversion works best if you are on the server.  Depending on the speed of your computer, it can be as fast as a "
                                                         + "few seconds, or it can take as long as 10 minutes.")
                                                 + (namesInnodb != "" ? "\r" + Lan.g(this, "The backup tables will be MyISAM format instead of InnoDB.") : "")
                                                 , "", MessageBoxButtons.OKCancel) != DialogResult.OK)
                {
                    return(false);                   //If user clicks cancel, then close the program
                }
            }
            Cursor.Current = Cursors.WaitCursor;
#if !DEBUG
            if (!isSilent)
            {
                if (DataConnection.DBtype != DatabaseType.MySql &&
                    !MsgBox.Show(this, true, "If you have not made a backup, please Cancel and backup before continuing.  Continue?"))
                {
                    return(false);
                }
            }
            if (DataConnection.DBtype == DatabaseType.MySql)
            {
                if (!Shared.MakeABackup(isSilent, BackupLocation.ConvertScript, false))
                {
                    Cursor.Current          = Cursors.Default;
                    FormOpenDental.ExitCode = 101;                  //Database Backup failed
                    return(false);
                }
            }
            //We've been getting an increasing number of phone calls with databases that have duplicate preferences which is impossible
            //unless a user has gotten this far and another computer in the office is in the middle of an update as well.
            //The issue is most likely due to the blocking messageboxes above which wait indefinitely for user input right before upgrading the database.
            //This means that the cache for this computer could be stale and we need to manually refresh our cache to double check
            //that the database isn't flagged as corrupt, an update isn't in progress, or that the database version hasn't changed (someone successfully updated already).
            Prefs.RefreshCache();
            //Now check the preferences that should stop this computer from executing an update.
            if (PrefC.GetBool(PrefName.CorruptedDatabase) ||
                (PrefC.GetString(PrefName.UpdateInProgressOnComputerName) != "" && PrefC.GetString(PrefName.UpdateInProgressOnComputerName) != Environment.MachineName))
            {
                //At this point, the pref "corrupted database" being true means that a computer is in the middle of running the upgrade script.
                //There will be another corrupted database check on start up which will take care of the scenario where this is truly a corrupted database.
                //Also, we need to make sure that the update in progress preference is set to this computer because we JUST set it to that value before entering this method.
                //If it has changed, we absolutely know without a doubt that another computer is trying to update at the same time.
                FormOpenDental.ExitCode = 142;              //Update is already in progress from another computer
                if (!isSilent)
                {
                    MsgBox.Show(this, "An update is already in progress from another computer.");
                }
                return(false);
            }
            //Double check that the database version has not changed.  This check is here just in case another computer has successfully updated the database already.
            Version versionDatabase = new Version(PrefC.GetString(PrefName.DataBaseVersion));
            if (FromVersion != versionDatabase)
            {
                FormOpenDental.ExitCode = 143;              //Database has already been updated from another computer
                if (!isSilent)
                {
                    MsgBox.Show(this, "The database has already been updated from another computer.");
                }
                return(false);
            }
            try {
#endif
            if (FromVersion < new Version("7.5.17"))                     //Insurance Plan schema conversion
            {
                if (isSilent)
                {
                    FormOpenDental.ExitCode = 139;                          //Update must be done manually to fix Insurance Plan Schema
                    Application.Exit();
                    return(false);
                }
                Cursor.Current = Cursors.Default;
                YN InsPlanConverstion_7_5_17_AutoMergeYN = YN.Unknown;
                if (FromVersion < new Version("7.5.1"))
                {
                    FormInsPlanConvert_7_5_17 form = new FormInsPlanConvert_7_5_17();
                    if (PrefC.GetBoolSilent(PrefName.InsurancePlansShared, true))
                    {
                        form.InsPlanConverstion_7_5_17_AutoMergeYN = YN.Yes;
                    }
                    else
                    {
                        form.InsPlanConverstion_7_5_17_AutoMergeYN = YN.No;
                    }
                    form.ShowDialog();
                    if (form.DialogResult == DialogResult.Cancel)
                    {
                        MessageBox.Show("Your database has not been altered.");
                        return(false);
                    }
                    InsPlanConverstion_7_5_17_AutoMergeYN = form.InsPlanConverstion_7_5_17_AutoMergeYN;
                }
                ConvertDatabases.Set_7_5_17_AutoMerge(InsPlanConverstion_7_5_17_AutoMergeYN);                        //does nothing if this pref is already present for some reason.
                Cursor.Current = Cursors.WaitCursor;
            }
            if (!isSilent && FromVersion > new Version("16.3.0") && FromVersion < new Version("16.3.29") && ApptReminderRules.UsesApptReminders())
            {
                //16.3.29 is more strict about reminder rule setup. Prompt the user and allow them to exit the update if desired.
                //Get all currently enabled reminder rules.
                List <bool> listReminderFlags = ApptReminderRules.Get_16_3_29_ConversionFlags();
                if (listReminderFlags?[0] ?? false)                        //2 reminders scheduled for same day of appointment. 1 will be converted to future day reminder.
                {
                    MsgBox.Show(this, "You have multiple appointment reminders set to send on the same day of the appointment. One of these will be converted to send 1 day prior to the appointment.  Please review automated reminder rule setup after update has finished.");
                }
                if (listReminderFlags?[1] ?? false)                        //2 reminders scheduled for future day of appointment. 1 will be converted to same day reminder.
                {
                    MsgBox.Show(this, "You have multiple appointment reminders set to send 1 or more days prior to the day of the appointment. One of these will be converted to send 1 hour prior to the appointment.  Please review automated reminder rule setup after update has finished.");
                }
            }
            if (FromVersion >= new Version("17.3.1") && FromVersion < new Version("17.3.23") && DataConnection.DBtype == DatabaseType.MySql &&
                (Tasks.HasAnyLongDescripts() || TaskNotes.HasAnyLongNotes() || Commlogs.HasAnyLongNotes()))
            {
                if (isSilent)
                {
                    FormOpenDental.ExitCode = 138;                          //Update must be done manually in order to get data loss notification(s).
                    Application.Exit();
                    return(false);
                }
                if (!MsgBox.Show(this, true, "Data will be lost during this update."
                                 + "\r\nContact support in order to retrieve the data from a backup after the update."
                                 + "\r\n\r\nContinue?"))
                {
                    MessageBox.Show("Your database has not been altered.");
                    return(false);
                }
            }
            if (FromVersion >= new Version("3.4.0"))
            {
                Prefs.UpdateBool(PrefName.CorruptedDatabase, true);
            }
            ConvertDatabases.FromVersion = FromVersion;
#if !DEBUG
            //Typically the UpdateInProgressOnComputerName preference will have already been set within FormUpdate.
            //However, the user could have cancelled out of FormUpdate after successfully downloading the Setup.exe
            //OR the Setup.exe could have been manually sent to our customer (during troubleshooting with HQ).
            //For those scenarios, the preference will be empty at this point and we need to let other computers know that an update going to start.
            //Updating the string (again) here will guarantee that all computers know an update is in fact in progress from this machine.
            Prefs.UpdateString(PrefName.UpdateInProgressOnComputerName, Environment.MachineName);
#endif
            //Show a progress window that will indecate to the user that there is an active update in progress. Currently okay to show during isSilent.
            ODProgress.ShowAction(() => ConvertDatabases.InvokeConvertMethods(),
                                  hasMinimize: false,
                                  odEventType: ODEventType.ConvertDatabases);
            Cursor.Current = Cursors.Default;
            if (FromVersion >= new Version("3.4.0"))
            {
                //CacheL.Refresh(InvalidType.Prefs);//or it won't know it has to update in the next line.
                Prefs.UpdateBool(PrefName.CorruptedDatabase, false, true);                      //more forceful refresh in order to properly change flag
            }
            Cache.Refresh(InvalidType.Prefs);
            if (!isSilent)
            {
                MsgBox.Show(this, "Database update successful");
            }
            return(true);

#if !DEBUG
        }

        catch (System.IO.FileNotFoundException e) {
            FormOpenDental.ExitCode = 160;                  //File not found exception
            if (!isSilent)
            {
                MessageBox.Show(e.FileName + " " + Lan.g(this, "could not be found. Your database has not been altered and is still usable if you uninstall this version, then reinstall the previous version."));
            }
            if (FromVersion >= new Version("3.4.0"))
            {
                Prefs.UpdateBool(PrefName.CorruptedDatabase, false);
            }
            return(false);
        }
        catch (System.IO.DirectoryNotFoundException) {
            FormOpenDental.ExitCode = 160;                  //ConversionFiles folder could not be found
            if (!isSilent)
            {
                MessageBox.Show(Lan.g(this, "ConversionFiles folder could not be found. Your database has not been altered and is still usable if you uninstall this version, then reinstall the previous version."));
            }
            if (FromVersion >= new Version("3.4.0"))
            {
                Prefs.UpdateBool(PrefName.CorruptedDatabase, false);
            }
            return(false);
        }
        catch (Exception ex) {
            FormOpenDental.ExitCode = 201;                  //Database was corrupted due to an update failure
            if (!isSilent)
            {
                MessageBox.Show(ex.Message + "\r\n\r\n"
                                + Lan.g(this, "Conversion unsuccessful. Your database is now corrupted and you cannot use it.  Please contact us."));
            }
            //Then, application will exit, and database will remain tagged as corrupted.
            return(false);
        }
#endif
        }
Exemple #20
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;
        }
        private void FillSubGrid(bool isRefreshNeeded = false, string grouping95 = "")
        {
            List <string> listSelectedVersions = listVersionsFilter.SelectedItems.OfType <string>().ToList();

            if (listSelectedVersions.Contains("All"))
            {
                listSelectedVersions.Clear();
            }
            if (isRefreshNeeded && listSelectedVersions.IsNullOrEmpty())
            {
                if (!MsgBox.Show(MsgBoxButtons.YesNo, "All bug submissions are going to be downloaded...\r\nAre you sure about this?"))
                {
                    return;
                }
            }
            Action loadingProgress = null;

            Cursor = Cursors.WaitCursor;
            #region gridSubs columns
            gridSubs.BeginUpdate();
            gridSubs.ListGridColumns.Clear();
            gridSubs.ListGridColumns.Add(new GridColumn("Submitter", 140));
            gridSubs.ListGridColumns.Add(new GridColumn("Vers.", 55, GridSortingStrategy.VersionNumber));
            if (comboGrouping.SelectedIndex == 0)           //Group by 'None'
            {
                gridSubs.ListGridColumns.Add(new GridColumn("DateTime", 75, GridSortingStrategy.DateParse));
            }
            else
            {
                gridSubs.ListGridColumns.Add(new GridColumn("#", 30, HorizontalAlignment.Right, GridSortingStrategy.AmountParse));
            }
            gridSubs.ListGridColumns.Add(new GridColumn("Flag", 50, HorizontalAlignment.Center));
            gridSubs.ListGridColumns.Add(new GridColumn("Msg Text", 0));
            gridSubs.AllowSortingByColumn = true;
            gridSubs.ListGridRows.Clear();
            #endregion
            bugSubmissionControl.ClearCustomerInfo();
            bugSubmissionControl.SetTextDevNoteEnabled(false);
            if (isRefreshNeeded)
            {
                loadingProgress = ODProgress.Show(ODEventType.BugSubmission, typeof(BugSubmissionEvent), Lan.g(this, "Refreshing Data") + "...");
                #region Refresh Logic
                if (_viewMode.In(FormBugSubmissionMode.ViewOnly, FormBugSubmissionMode.ValidationMode))
                {
                    _listAllSubs = ListViewedSubs;
                }
                else
                {
                    BugSubmissionEvent.Fire(ODEventType.BugSubmission, Lan.g(this, "Refreshing Data: Bugs"));
                    _listAllSubs = BugSubmissions.GetAllInRange(dateRangePicker.GetDateTimeFrom(), dateRangePicker.GetDateTimeTo(), listSelectedVersions);
                }
                try {
                    BugSubmissionEvent.Fire(ODEventType.BugSubmission, Lan.g(this, "Refreshing Data: Patients"));
                    _dictPatients = RegistrationKeys.GetPatientsByKeys(_listAllSubs.Select(x => x.RegKey).ToList());
                }
                catch (Exception e) {
                    e.DoNothing();
                    _dictPatients = new Dictionary <string, Patient>();
                }
                BugSubmissionEvent.Fire(ODEventType.BugSubmission, Lan.g(this, "Refreshing Data: JobLinks"));
                _listJobLinks = JobLinks.GetManyForType(JobLinkType.Bug, _listAllSubs.Select(x => x.BugId).Where(x => x != 0).Distinct().ToList());
                #endregion
            }
            #region Filter Logic
            BugSubmissionEvent.Fire(ODEventType.BugSubmission, "Filtering Data");
            List <BugSubmission> listFilteredSubs    = null;
            List <string>        listSelectedRegKeys = comboRegKeys.ListSelectedItems.Select(x => (string)x).ToList();
            if (listSelectedRegKeys.Contains("All"))
            {
                listSelectedRegKeys.Clear();
            }
            List <string> listStackFilters = textStackFilter.Text.Split(',')
                                             .Where(x => !string.IsNullOrWhiteSpace(x))
                                             .Select(x => x.ToLower()).ToList();
            List <string> listPatNumFilters = textPatNums.Text.Split(',')
                                              .Where(x => !string.IsNullOrWhiteSpace(x))
                                              .Select(x => x.ToLower()).ToList();
            _listAllSubs.ForEach(x => x.TagCustom = null);
            List <string> listCategoryFilters = textCategoryFilters.Text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            string        msgText             = textMsgText.Text;
            string        devNoteFilter       = textDevNoteFilter.Text;
            DateTime      dateTimeFrom        = dateRangePicker.GetDateTimeFrom();
            DateTime      dateTimeTo          = dateRangePicker.GetDateTimeTo();
            //Filter the list of all bug submissions and then order it by program version and submission date time so that the grouping is predictable.
            listFilteredSubs = _listAllSubs.Where(x =>
                                                  PassesFilterValidation(x, listCategoryFilters, listSelectedRegKeys, listStackFilters, listPatNumFilters, listSelectedVersions, grouping95,
                                                                         msgText, devNoteFilter, dateTimeFrom, dateTimeTo)
                                                  )
                               .OrderByDescending(x => new Version(x.ProgramVersion))
                               .ThenByDescending(x => x.SubmissionDateTime)
                               .ToList();
            if (isRefreshNeeded)
            {
                FillPatNameFilter(_listAllSubs);
            }
            #endregion
            #region Grouping Logic
            List <BugSubmission> listGridSubmissions = new List <BugSubmission>();
            BugSubmissionEvent.Fire(ODEventType.BugSubmission, "Grouping Data");
            switch (comboGrouping.SelectedIndex)
            {
            case 0:
                #region None
                foreach (BugSubmission bugSubmission in listFilteredSubs)
                {
                    AddGroupedSubsToGridSubs(listGridSubmissions, new List <BugSubmission>()
                    {
                        bugSubmission
                    });
                }
                listShowHideOptions.SetSelected(3, false);                       //Deselect 'None'
                _minGroupingCount = -1;
                butAddJob.Enabled = true;
                #endregion
                break;

            case 1:
                #region RegKey/Ver/Stack
                listFilteredSubs.GroupBy(x => new {
                    x.BugId,
                    x.RegKey,
                    x.ProgramVersion,
                    x.ExceptionMessageText,
                    x.ExceptionStackTrace
                })
                .ToDictionary(x => x.Key, x => x.ToList())
                .ForEach(x => AddGroupedSubsToGridSubs(listGridSubmissions, x.Value));
                butAddJob.Enabled = true;
                #endregion
                break;

            case 2:
                #region StackTrace
                listFilteredSubs.GroupBy(x => new {
                    x.BugId,
                    x.ExceptionMessageText,
                    x.ExceptionStackTrace
                })
                .ToDictionary(x => x.Key, x => x.ToList())
                .ForEach(x => AddGroupedSubsToGridSubs(listGridSubmissions, x.Value));
                butAddJob.Enabled = true;
                #endregion
                break;

            case 3:
                #region 95%
                //At this point all bugSubmissions in listFilteredSubs is at least a 95% match. Group them all together in a single row.
                AddGroupedSubsToGridSubs(listGridSubmissions, listFilteredSubs);
                butAddJob.Enabled = true;
                #endregion
                break;

            case 4:
                #region StackSig
                listFilteredSubs.GroupBy(x => new {
                    x.BugId,
                    x.ExceptionMessageText,
                    x.OdStackSignature
                })
                .ToDictionary(x => x.Key, x => x.ToList())
                .ForEach(x => AddGroupedSubsToGridSubs(listGridSubmissions, x.Value));
                butAddJob.Enabled = false;                      //Can not add jobs in this mode.
                #endregion
                break;

            case 5:
                #region StackSimple
                listFilteredSubs.GroupBy(x => new {
                    x.BugId,
                    x.ExceptionMessageText,
                    x.SimplifiedStackTrace
                })
                .ToDictionary(x => x.Key, x => x.ToList())
                .ForEach(x => AddGroupedSubsToGridSubs(listGridSubmissions, x.Value));
                butAddJob.Enabled = false;                      //Can not add jobs in this mode.
                #endregion
                break;

            case 6:
                #region Hash
                listFilteredSubs.GroupBy(x => new {
                    x.BugId,
                    x.BugSubmissionHashNum
                })
                .ToDictionary(x => x.Key, x => x.ToList())
                .ForEach(x => AddGroupedSubsToGridSubs(listGridSubmissions, x.Value));
                butAddJob.Enabled = false;                      //Can not add jobs in this mode.
                #endregion
                break;
            }
            if (_minGroupingCount > 0)
            {
                listGridSubmissions.RemoveAll(x => (x.TagCustom as List <BugSubmission>).Count < _minGroupingCount);
            }
            #endregion
            #region Sorting Logic
            BugSubmissionEvent.Fire(ODEventType.BugSubmission, "Sorting Data");
            switch (comboSortBy.SelectedIndex)
            {
            case 0:
                listGridSubmissions = listGridSubmissions.OrderByDescending(x => new Version(x.ProgramVersion))
                                      .ThenByDescending(x => GetGroupCount(x))
                                      .ThenByDescending(x => x.SubmissionDateTime).ToList();
                break;
            }
            #endregion
            #region Fill gridSubs
            BugSubmissionEvent.Fire(ODEventType.BugSubmission, "Filling Grid");
            foreach (BugSubmission sub in listGridSubmissions)
            {
                gridSubs.ListGridRows.Add(GetODGridRowForSub(sub));
            }
            gridSubs.EndUpdate();
            #endregion
            loadingProgress?.Invoke();
            Cursor = Cursors.Default;
        }
        private void RefreshReport()
        {
            bool      hasValidationPassed = ValidateFields();
            DataTable tableOverpaidProcs  = new DataTable();

            if (hasValidationPassed)
            {
                ODProgress.ShowAction(
                    () => {
                    tableOverpaidProcs = RpProcOverpaid.GetOverPaidProcs(_patNum, _listSelectedProvNums, comboBoxMultiClinics.ListSelectedClinicNums,
                                                                         _myReportDateFrom, _myReportDateTo);
                },
                    startingMessage: "Refreshing the Grid Data...",
                    actionException: e => this.Invoke(() => {
                    FriendlyException.Show(Lan.g(this, "Error filling the Procedures Overpaid grid."), e);
                })
                    );
            }
            string subTitleProviders = Lan.g(this, "All Providers");

            if (_listSelectedProvNums.Count > 0)
            {
                subTitleProviders = Lan.g(this, "For Providers:") + " " + string.Join(",", _listSelectedProvNums.Select(x => Providers.GetFormalName(x)));
            }
            string subtitleClinics = comboBoxMultiClinics.GetStringSelectedClinics();

            //This report will never show progress for printing.  This is because the report is being rebuilt whenever the grid is refreshed.
            _myReport            = new ReportComplex(true, false, false);
            _myReport.ReportName = Lan.g(this, "Overpaid Procedures");
            _myReport.AddTitle("Title", Lan.g(this, "Overpaid Procedures"));
            _myReport.AddSubTitle("Practice Name", PrefC.GetString(PrefName.PracticeTitle));
            if (_myReportDateFrom == _myReportDateTo)
            {
                _myReport.AddSubTitle("Report Dates", _myReportDateFrom.ToShortDateString());
            }
            else
            {
                _myReport.AddSubTitle("Report Dates", _myReportDateFrom.ToShortDateString() + " - " + _myReportDateTo.ToShortDateString());
            }
            if (_patNum > 0)
            {
                _myReport.AddSubTitle("Patient", Patients.GetLim(_patNum).GetNameFL());
            }
            _myReport.AddSubTitle("Providers", subTitleProviders);
            if (PrefC.HasClinicsEnabled)
            {
                _myReport.AddSubTitle("Clinics", subtitleClinics);
            }
            QueryObject query = _myReport.AddQuery(tableOverpaidProcs, DateTimeOD.Today.ToShortDateString());

            query.AddColumn("Patient Name", _colWidthPatName, FieldValueType.String);
            query.AddColumn("Date", _colWidthProcDate, FieldValueType.Date);
            query.GetColumnDetail("Date").StringFormat = "d";
            query.AddColumn("Code", _colWidthProcCode, FieldValueType.String);
            query.AddColumn("Tth", _colWidthProcTth, FieldValueType.String);
            query.AddColumn("Prov", _colWidthProv, FieldValueType.String);
            query.AddColumn("Fee", _colWidthFee, FieldValueType.Number);
            query.AddColumn("Ins Paid", _colWidthInsPay, FieldValueType.Number);
            query.AddColumn("Write-off", _colWidthWO, FieldValueType.Number);
            query.AddColumn("Pt Paid", _colWidthPtPaid, FieldValueType.Number);
            query.AddColumn("Adjust", _colWidthAdj, FieldValueType.Number);
            query.AddColumn("Overpayment", _colWidthOverpay, FieldValueType.Number);
            _myReport.AddPageNum();
            _myReport.SubmitQueries(false);
        }
Exemple #23
0
        ///<summary>Sends a request to HQ to update the Short Code Opt In status of this patient.  Can be sent silently without any feedback in the UI.
        ///</summary>
        private static bool TrySendToHq(string wirelessPhone, YN optIn, long patNum, long clinicNum, bool isSilent = false)
        {
            List <PayloadItem> listPayloadItems = new List <PayloadItem>()
            {
                new PayloadItem(wirelessPhone, "PhonePat"),
                new PayloadItem((int)optIn, "ShortCodeOptInInt"),
                new PayloadItem(patNum, "PatNum"),
                new PayloadItem(clinicNum, "ClinicNum"),
                new PayloadItem(false, "IsWebSchedNewPat"),
                new PayloadItem(isSilent, "IsSilentUpdate"),
            };
            string result = "";

            if (isSilent)
            {
                ODThread threadSilent = new ODThread((o) => WebServiceMainHQProxy.GetWebServiceMainHQInstance()
                                                     .SetSmsPatientPhoneOptIn(PayloadHelper.CreatePayload(listPayloadItems, eServiceCode.IntegratedTexting)));
                threadSilent.AddExceptionHandler((ex) => ex.DoNothing());
                threadSilent.Name = "ShortCodeOptIn";
                threadSilent.Start();
                return(true);
            }
            ODProgress.ShowAction(() => {
                result = WebServiceMainHQProxy.GetWebServiceMainHQInstance()
                         .SetSmsPatientPhoneOptIn(PayloadHelper.CreatePayload(listPayloadItems, eServiceCode.IntegratedTexting));
            });
            XmlDocument doc = new XmlDocument();

            doc.LoadXml(result);
            XmlNode node = doc.SelectSingleNode("//ListSmsToMobiles");

            if (node is null)
            {
                node = doc.SelectSingleNode("//Error");
                if (!(node is null))
                {
                    MessageBox.Show(Lan.g("ShortCodes", "An error occurred: ") + node.InnerText);
                }
                return(false);
            }
            List <SmsToMobile> listSmsToMobiles;

            using (XmlReader reader = XmlReader.Create(new System.IO.StringReader(node.InnerXml))) {
                System.Xml.Serialization.XmlSerializer xmlListSmsToMobileSerializer = new System.Xml.Serialization.XmlSerializer(typeof(List <SmsToMobile>));
                listSmsToMobiles = (List <SmsToMobile>)xmlListSmsToMobileSerializer.Deserialize(reader);
            }
            if (listSmsToMobiles == null)            //List should always be there even if it's empty.
            {
                MessageBox.Show(Lan.g("ShortCodes", "An error occurred: ") + node.InnerText);
                return(false);
            }
            //Should only be 0 or 1.
            if (listSmsToMobiles.Count > 0)
            {
                listSmsToMobiles.ForEach(x => x.DateTimeSent = DateTime.Now);
                SmsToMobiles.InsertMany(listSmsToMobiles);
                string message = $"{wirelessPhone} will shortly receive the following message{(listSmsToMobiles.Count>1 ? "s" : "")}:\n"
                                 + string.Join("\n", listSmsToMobiles.Select((x, i) => $"{i+1}) {x.MsgText}"));
                MessageBox.Show(message, "Appointment Texts");
            }
            //Local OptIn status for this patient will be updated by a Transmission from HQ, resulting from this call to SetSmsPatientPhoneOptIn().
            return(true);
        }
        ///<summary>Saves all images in the grid to the patient on the claim's directory in the images module. Also creates
        ///a list of ClaimAttach objects to associate to the given claim.</summary>
        private void buttonOK_Click(object sender, EventArgs e)
        {
            //The user must create an image or narrative attachment before sending.
            if (gridAttachedImages.ListGridRows.Count == 0 && textNarrative.Text.Trim().Length == 0)
            {
                MsgBox.Show(this, "An image or narrative must be specified before continuing.");
                return;
            }
            try {
                CreateAndSendAttachments();
            }
            //Creating and sending Attachments will sometimes time out when an arbirtrarily large group of attachments are being sent,
            //at which point each attachment should be sent individually.
            catch (TimeoutException ex) {
                ex.DoNothing();
                ODProgress.ShowAction(() => { BatchSendAttachments(); }, "Sending attachments timed out. Attempting to send individually. Please wait.");
            }
            catch (ODException ex) {
                //ODExceptions should already be Lans.g when throwing meaningful messages.
                //If they weren't translated, the message was from a third party and shouldn't be translated anyway.
                MessageBox.Show(ex.Message);
                return;
            }
            //Validate the claim, if it isn't valid let the user decide if they want to continue
            if (!ValidateClaimHelper())
            {
                if (!MsgBox.Show(this, MsgBoxButtons.YesNo, "There were errors validating the claim, would you like to continue?"))
                {
                    return;
                }
            }
            //Used for determining which category to save the image attachments to. 0 will save the image to the first category in the Images module.
            long imageTypeDefNum   = 0;
            Def  defClaimAttachCat = CheckImageCatDefs().FirstOrDefault();

            if (defClaimAttachCat != null)
            {
                imageTypeDefNum = defClaimAttachCat.DefNum;
            }
            else              //User does not have a Claim Attachment image category, just use the first image category available.
            {
                imageTypeDefNum = Defs.GetCatList((int)DefCat.ImageCats).FirstOrDefault(x => !x.IsHidden).DefNum;
            }
            List <ClaimAttach> listClaimAttachments = new List <ClaimAttach>();

            for (int i = 0; i < gridAttachedImages.ListGridRows.Count; i++)
            {
                ClaimConnect.ImageAttachment imageRow = ((ClaimConnect.ImageAttachment)gridAttachedImages.ListGridRows[i].Tag);
                if (PrefC.GetBool(PrefName.SaveDXCAttachments))
                {
                    Bitmap   imageBitmap = new Bitmap(imageRow.Image);
                    Document docCur      = ImageStore.Import(imageBitmap, imageTypeDefNum, ImageType.Document, _claimPat);
                    imageRow.ImageFileNameActual = docCur.FileName;
                }
                //Create attachment objects
                listClaimAttachments.Add(CreateClaimAttachment(imageRow.ImageFileNameDisplay, imageRow.ImageFileNameActual));
            }
            //Keep a running list of attachments sent to DXC for the claim. This will show in the attachments listbox.
            _claimCur.Attachments.AddRange(listClaimAttachments);
            Claims.Update(_claimCur);
            MsgBox.Show("Attachments sent successfully!");
            DialogResult = DialogResult.OK;
        }
        ///<summary>Balances all selected accounts.</summary>
        private void butTransfer_Click(object sender, EventArgs e)
        {
            //FormIncomeTransferManage requires PaymentCreate to run.
            //This form requires SecurityAdmin and a password to open, and although rare,
            // a SecuirtyAdmin doesn't have to have PaymentCreate permission
            if (!Security.IsAuthorized(Permissions.PaymentCreate))
            {
                return;
            }
            //Make sure the user wants to run the tool.
            if (!MsgBox.Show(this, MsgBoxButtons.YesNo, "This process can take a long time and cannot be reversed.\r\n\r\nContinue?"))
            {
                return;
            }
            Action actionCloseProgress = ODProgress.Show(ODEventType.Billing);

            //Build list of families based off of selected rows.
            _logger.WriteLine("This is the summary of all transactions that took place.This can be saved for later reference if one or more"
                              + " transactions need to be undone outside of the tool.\r\n", LogLevel.Information);
            //Do income transfers if applicable.
            for (int i = _batchNum - 1; i < _listBatches.Count(); i++)     //_batchNum is 1-based, so drop i by 1 to make sure the current batch is included
            {
                string logText = "";
                if (checkAllocateCharges.Checked)
                {
                    ODEvent.Fire(ODEventType.Billing, Lan.g(this, $"Creating income transfers for batch {_batchNum}/{_listBatches.Count()} please wait..."));
                    foreach (FamilyAccount famAccountCur in _dictCurrentFamilyBatch.Select(x => x.Value))
                    {
                        //Clear the list of splits in case any are hanging around from a previous run.
                        famAccountCur.ListSplits.Clear();
                        famAccountCur.ListSplitsAssociated.Clear();
                        //Make lists of positive and negative charges.
                        List <AccountEntry> listPosCharges        = famAccountCur.Account.ListAccountCharges.Where(x => x.AmountEnd > 0).ToList();
                        List <AccountEntry> listNegCharges        = famAccountCur.Account.ListAccountCharges.Where(x => x.AmountEnd < 0).ToList();
                        List <long>         listPatNumsForCharges = listPosCharges.Select(x => x.PatNum).Distinct().ToList();
                        List <AccountEntry> listEntriesForPats    = famAccountCur.Account.ListAccountCharges.FindAll(x => x.PatNum.In(listPatNumsForCharges));
                        //This catch will save us some time if they run the tool on the same family twice.
                        if (listPosCharges.Count() == 0 || listNegCharges.Count() == 0)
                        {
                            continue;                            //No need to add to logText, CreateTransfers wouldn't return anything either.
                        }
                        Payment payCur = CreatePaymentTransferHelper(famAccountCur.Guarantor);
                        logText += CreateTransfers(listPosCharges, listNegCharges, listEntriesForPats, famAccountCur, payCur);
                        logText += CreditsToUnallocated(listNegCharges, famAccountCur, payCur);
                        //Remove any $0 splits created from CreateTransfers.
                        famAccountCur.ListSplits.RemoveAll(x => x.SplitAmt == 0);
                        foreach (PaySplit split in famAccountCur.ListSplits)
                        {
                            PaySplits.Insert(split);
                        }
                        //Go through family accounts and update FSplitNums.
                        foreach (PaySplits.PaySplitAssociated split in famAccountCur.ListSplitsAssociated)
                        {
                            //Update the FSplitNum after inserts are made.
                            if (split.PaySplitLinked != null && split.PaySplitOrig != null)
                            {
                                PaySplits.UpdateFSplitNum(split.PaySplitOrig.SplitNum, split.PaySplitLinked.SplitNum);
                            }
                        }
                    }
                }
                //Transfer balances to guarantor if applicable.
                if (checkGuarAllocate.Checked)
                {
                    ODEvent.Fire(ODEventType.Billing, Lan.g(this, $"Transferring remaining balance to guarantor for batch {_batchNum}/{_listBatches.Count()} please wait..."));
                    logText += "Balances transferred to Guarantor:\r\n";
                    logText += TransferToGuarantor();
                }
                //load up the next batch
                ODEvent.Fire(ODEventType.Billing, Lan.g(this, $"Loading next batch please wait..."));
                FillNextBatch();
                _logger.WriteLine(logText, LogLevel.Information);
            }
            actionCloseProgress();
        }
        ///<summary>Processes a PayConnect payment via a credit card terminal.</summary>
        private bool ProcessPaymentTerminal()
        {
            PosRequest posRequest = null;

            try {
                if (radioSale.Checked)
                {
                    posRequest = PosRequest.CreateSale(PIn.Decimal(textAmount.Text));
                }
                else if (radioAuthorization.Checked)
                {
                    posRequest = PosRequest.CreateAuth(PIn.Decimal(textAmount.Text));
                }
                else if (radioVoid.Checked)
                {
                    posRequest = PosRequest.CreateVoidByReference(textRefNumber.Text);
                }
                else if (radioReturn.Checked)
                {
                    if (textRefNumber.Text == "")
                    {
                        posRequest = PosRequest.CreateRefund(PIn.Decimal(textAmount.Text));
                    }
                    else
                    {
                        posRequest = PosRequest.CreateRefund(PIn.Decimal(textAmount.Text), textRefNumber.Text);
                    }
                }
                else                  //Shouldn't happen
                {
                    MsgBox.Show(this, "Please select a transaction type");
                    return(false);
                }
                posRequest.ForceDuplicate = checkForceDuplicate.Checked;
            }
            catch (Exception ex) {
                MessageBox.Show(Lan.g(this, "Error creating request:") + " " + ex.Message);
                return(false);
            }
            bool result = true;

            ODProgress.ShowAction(() => {
                _posResponse = DpsPos.ProcessCreditCard(posRequest);
            },
                                  startingMessage: Lan.g(this, "Processing payment on terminal"),
                                  actionException: ex => {
                this.Invoke(() => {
                    MessageBox.Show(Lan.g(this, "Error processing card:") + " " + ex.Message);
                    result = false;
                });
            });
            if (!result)
            {
                return(false);
            }
            if (_posResponse == null)
            {
                MessageBox.Show(Lan.g(this, "Error processing card"));
                return(false);
            }
            if (_posResponse.ResponseCode != "0")           //"0" indicates success. May need to check the AuthCode field too to determine if this was a success.
            {
                MessageBox.Show(Lan.g(this, "Error message from Pay Connect:") + "\r\n" + _posResponse.ResponseDescription);
                return(false);
            }
            PayConnectService.signatureResponse sigResponse = null;
            try {
                Cursor      = Cursors.WaitCursor;
                sigResponse = SendSignature(_posResponse.ReferenceNumber.ToString());
                Cursor      = Cursors.Default;
            }
            catch (Exception ex) {
                Cursor = Cursors.Default;
                MessageBox.Show(Lan.g(this, "Card successfully charged. Error processing signature:") + " " + ex.Message);
            }
            textCardNumber.Text = _posResponse.CardNumber;
            textAmount.Text     = _posResponse.Amount.ToString("f");
            _receiptStr         = PayConnectTerminal.BuildReceiptString(posRequest, _posResponse, sigResponse, _clinicNum);
            PrintReceipt(_receiptStr);
            return(true);
        }
        ///<summary>Makes a web call to WebServiceMainHQ to get the corresponding EServiceSetupFull information and then attempts to fill each tab.
        ///If anything goes wrong within this method a message box will show to the user and then the window will auto close via Abort.</summary>
        private void FillForm()
        {
            Action actionCloseProgress = ODProgress.Show(ODEventType.EServices, typeof(EServicesEvent), "Validating eServices...");

            try {
                if (!ODBuild.IsWeb() && MiscUtils.TryUpdateIeEmulation())
                {
                    throw new Exception("Browser emulation version updated.\r\nYou must restart this application before accessing the Signup Portal.");
                }
                //Send light version of clinics to HQ to be used by signup portal below. Get back all args needed from HQ in order to perform the operations of this window.
                SignupPortalPermission perm = GetUserSignupPortalPermissions();
                SecurityLogs.MakeLogEntry(Permissions.Setup, 0, $"User {Security.CurUser.UserName} entered EService Setup with SignupPortalPermission {perm}");
                if (_signupOut == null)                //the first time this loads _signupOut will be null, so we won't have a previous state to compare
                {
                    _signupOut = WebServiceMainHQProxy.GetEServiceSetupFull(perm);
                }
                else                   //If we are switching from the signup tab to another this will get called again and we don't want to lose the "diff"
                {
                    _signupOut = WebServiceMainHQProxy.GetEServiceSetupFull(perm, oldSignupOut: _signupOut);
                }
                //Show user any prompts that were generated by GetEServiceSetupFull().
                if (_signupOut.Prompts.Count > 0)
                {
                    MessageBox.Show(string.Join("\r\n", _signupOut.Prompts.Select(x => Lans.g(this, x))));
                }
                if (ODBuild.IsWeb())
                {
                    bool isSignupSelected = tabControl.SelectedTab == tabSignup;
                    tabControl.TabPages.Remove(tabSignup);
                    if (isSignupSelected)
                    {
                        actionCloseProgress?.Invoke();
                        this.ForceBringToFront();
                        Process.Start(_signupOut.SignupPortalUrl);
                        DialogResult = DialogResult.Abort;
                        return;
                    }
                }
                #region Fill
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - Signup"));
                FillTabSignup();
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - eConnector Service"));
                FillTabEConnector();
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - Mobile Synch (old-style)"));
                FillTabMobileSynch();
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - Mobile Web"));
                FillTabMobileWeb();
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - Patient Portal"));
                FillTabPatientPortal();
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - Web Sched Recall"));
                FillTabWebSchedRecall();
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - Web Sched New Pat Appt"));
                FillTabWebSchedNewPat();
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - Web Sched Verify"));
                FillTabWebSchedVerify();
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - Texting Services"));
                FillTabTexting();
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - eReminders & eConfirmations"));
                FillTabECR();
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - eClipboard"));
                FillTabEClipboard();
                EServicesEvent.Fire(ODEventType.EServices, Lan.g(this, "Loading tab - Miscellaneous"));
                FillTabMisc();
                #endregion
                #region Authorize editing
                //Disable certain buttons but let them continue to view.
                bool allowEdit = Security.IsAuthorized(Permissions.EServicesSetup, true);
                AuthorizeTabSignup(allowEdit);
                AuthorizeTabEConnector(allowEdit);
                AuthorizeTabMobileSynch(allowEdit);
                AuthorizeTabPatientPortal(allowEdit);
                AuthorizeTabWebSchedRecall(allowEdit);
                AuthorizeTabWebSchedNewPat(allowEdit);
                AuthorizeTabTexting(allowEdit);
                AuthorizeTabECR(allowEdit);
                AuthorizeTabEClipboard(allowEdit);
                AuthorizeTabMisc(allowEdit);
                ((Control)tabMobileSynch).Enabled = allowEdit;
                #endregion
            }
            catch (WebException we) {
                actionCloseProgress?.Invoke();
                this.ForceBringToFront();
                FriendlyException.Show(Lan.g(this, "Could not reach HQ.  Please make sure you have an internet connection and try again or call support."), we);
                //Set the dialog result to Abort so that FormClosing knows to not try and save any changes.
                DialogResult = DialogResult.Abort;
                Close();
            }
            catch (Exception e) {
                actionCloseProgress?.Invoke();
                this.ForceBringToFront();
                FriendlyException.Show(Lan.g(this, "There was a problem loading the eServices Setup window.  Please try again or call support."), e);
                //Set the dialog result to Abort so that FormClosing knows to not try and save any changes.
                DialogResult = DialogResult.Abort;
                Close();
            }
            actionCloseProgress?.Invoke();
            this.ForceBringToFront();
        }
Exemple #28
0
        private void FillGrid()
        {
            ODProgress.ShowAction(            //Show progress window while filling the grid.
                () => {
                string order = "";
                switch (comboOrder.SelectedIndex)
                {
                case 0:
                    order = "status";
                    break;

                case 1:
                    order = "alph";
                    break;

                case 2:
                    order = "date";
                    break;
                }
                long provNum = 0;
                if (comboProv.SelectedIndex != 0)
                {
                    provNum = _listProviders[comboProv.SelectedIndex - 1].ProvNum;
                }
                long siteNum = 0;
                if (!PrefC.GetBool(PrefName.EasyHidePublicHealth) && comboSite.SelectedIndex != 0)
                {
                    siteNum = _listSites[comboSite.SelectedIndex - 1].SiteNum;
                }
                bool showBrokenAppts;
                showBrokenAppts = checkBrokenAppts.Checked;
                long clinicNum  = PrefC.HasClinicsEnabled ? comboClinic.SelectedClinicNum : -1;
                _listUnschedApt = Appointments.RefreshUnsched(order, provNum, siteNum, showBrokenAppts, clinicNum,
                                                              codeRangeFilter.StartRange, codeRangeFilter.EndRange, dateRangePicker.GetDateTimeFrom(), dateRangePicker.GetDateTimeTo());
                UnscheduleListEvent.Fire(ODEventType.UnscheduledList, Lans.g(this, "Filling the Unscheduled List grid..."));
                int scrollVal = grid.ScrollValue;
                grid.BeginUpdate();
                grid.ListGridColumns.Clear();
                GridColumn col = new GridColumn(Lan.g("TableUnsched", "Patient"), 140);
                grid.ListGridColumns.Add(col);
                col = new GridColumn(Lan.g("TableUnsched", "Date"), 65);
                grid.ListGridColumns.Add(col);
                col = new GridColumn(Lan.g("TableUnsched", "AptStatus"), 90);
                grid.ListGridColumns.Add(col);
                col = new GridColumn(Lan.g("TableUnsched", "UnschedStatus"), 110);
                grid.ListGridColumns.Add(col);
                col = new GridColumn(Lan.g("TableUnsched", "Prov"), 50);
                grid.ListGridColumns.Add(col);
                col = new GridColumn(Lan.g("TableUnsched", "Procedures"), 150);
                grid.ListGridColumns.Add(col);
                col = new GridColumn(Lan.g("TableUnsched", "Notes"), 200);
                grid.ListGridColumns.Add(col);
                grid.ListGridRows.Clear();
                GridRow row;
                Dictionary <long, string> dictPatNames = Patients.GetPatientNames(_listUnschedApt.Select(x => x.PatNum).ToList());
                foreach (Appointment apt in _listUnschedApt)
                {
                    row            = new GridRow();
                    string patName = Lan.g(this, "UNKNOWN");
                    dictPatNames.TryGetValue(apt.PatNum, out patName);
                    row.Cells.Add(patName);
                    if (apt.AptDateTime.Year < 1880)
                    {
                        row.Cells.Add("");
                    }
                    else
                    {
                        row.Cells.Add(apt.AptDateTime.ToShortDateString());
                    }
                    if (apt.AptStatus == ApptStatus.Broken)
                    {
                        row.Cells.Add(Lan.g(this, "Broken"));
                    }
                    else
                    {
                        row.Cells.Add(Lan.g(this, "Unscheduled"));
                    }
                    row.Cells.Add(Defs.GetName(DefCat.RecallUnschedStatus, apt.UnschedStatus));
                    row.Cells.Add(Providers.GetAbbr(apt.ProvNum));
                    row.Cells.Add(apt.ProcDescript);
                    row.Cells.Add(apt.Note);
                    grid.ListGridRows.Add(row);
                }
                grid.EndUpdate();
                grid.ScrollValue = scrollVal;
            },
                startingMessage: Lans.g(this, "Retrieving data for the Unscheduled List grid..."),
                eventType: typeof(UnscheduleListEvent),
                odEventType: ODEventType.UnscheduledList
                );
        }
Exemple #29
0
        ///<summary>Refreshes the data and changes the UI accordingly. Called from FillGrid when dataRefresh is true.</summary>
        private void RefreshData()
        {
            List <ODThread> listThreadsRunning = ODThread.GetThreadsByGroupName("FormBackport_Refresh");

            //Quit all threads that are still running. The user may have changed the path. This way the grid will not be filled with false information.
            listThreadsRunning.ForEach(x => x.QuitAsync());
            //Store path
            _pathOnRefresh           = comboPath.Text.TrimEnd('\\');
            _ignoreListNameOnRefresh = textIgnoreList.Text;
            _currentProject          = BackportProjects.Unknown;
            _listFileChanges         = new List <ODFileChanges>();
            //Clear Rows
            gridMain.BeginUpdate();
            gridMain.ListGridRows.Clear();
            gridMain.EndUpdate();
            if (!Directory.Exists(comboPath.Text))
            {
                MessageBox.Show("The directory does not exist.");
                return;
            }
            else
            {
                if (_pathOnRefresh.Contains("OPEN DENTAL SUBVERSION"))                 //look for open dental first as its naming scheme does not match the rest.
                {
                    _currentProject = BackportProjects.OpenDental;
                }
                else
                {
                    for (int i = 0; i < Enum.GetNames(typeof(ProjectName)).Length; i++)
                    {
                        if (_pathOnRefresh.Contains(Enum.GetNames(typeof(ProjectName))[i]))
                        {
                            _currentProject = BackportProjects.ListProjects.Find(x => x.Name == ((ProjectName)i));
                            break;
                        }
                    }
                }
            }
            if (_currentProject == BackportProjects.Unknown)
            {
                MessageBox.Show("Could not find the correct project.");
                return;
            }
            //Get available versions based on folder structure.
            UpdateListVersions();
            Cursor = Cursors.AppStarting;
            //Refresh Data
            string          pathOnRefresh           = _pathOnRefresh;
            string          ignoreListNameOnRefresh = _ignoreListNameOnRefresh;
            BackportProject currentProject          = _currentProject.Copy();
            ODThread        odThread = new ODThread((o) => {
                List <ODFileChanges> listFileChanges = GetListOfFiles(pathOnRefresh, _listAvailableVersions, ignoreListNameOnRefresh, currentProject);
                this.InvokeIfNotDisposed(() => {       //If window quit, this action will not run and the thread will die.
                    if (o.HasQuit)                     //If the user refreshed the path and this was marked to quit.
                    {
                        return;
                    }
                    Cursor            = Cursors.Default;
                    _listFileChanges  = listFileChanges;
                    labelCurProj.Text = "Current Project: " + Enum.GetName(_currentProject.Name.GetType(), _currentProject.Name);
                    FillGrid();
                    _progressBarAction?.Invoke();
                    _progressBarAction = null;
                });
            });

            odThread.AddExceptionHandler(ex => {
                _progressBarAction?.Invoke();
                _progressBarAction = null;
                this.InvokeIfNotDisposed(() => {                //If there's an exception after the form is closed, swallow and do not do anything.
                    FriendlyException.Show("Error refreshing data.", ex);
                });
            });
            odThread.GroupName = "FormBackport_Refresh";
            odThread.Name      = "FormBackport_Refresh" + DateTime.Now.Millisecond;
            odThread.Start();
            if (_progressBarAction == null)
            {
                _progressBarAction = ODProgress.Show();
            }
        }
Exemple #30
0
        private void butOK_Click(object sender, EventArgs e)
        {
            if (!ValidateUserInput())
            {
                return;
            }
            FeeSched    feeSchedCur       = ((ODBoxItem <FeeSched>)comboFeeSched.SelectedItem).Tag;
            List <long> listClinicNumsNew = _listClinicsInGroup.Select(x => x.ClinicNum).ToList();

            //Initial fee sync for new groups or groups that were created without any clinics in the group, or if we just changed the Fee Schedule for the group.
            //If editing an existing fee schedule group that contains no clinic associations, treat it like a new group and set the initial fees.
            if (_feeSchedGroupCur.IsNew || _feeSchedGroupCur.ListClinicNumsAll.Count() < 1 || _feeSchedGroupCur.FeeSchedNum != feeSchedCur.FeeSchedNum)
            {
                if (MsgBox.Show(this, MsgBoxButtons.YesNo, "Would you like to set the initial group fees to a specific clinic's fees?"
                                + "  Answering no will result in the default fees for the fee schedule being used."))
                {
                    List <GridColumn> listColumnHeaders = new List <GridColumn>()
                    {
                        new GridColumn(Lan.g(this, "Abbr"), 75),
                        new GridColumn(Lan.g(this, "Description"), 200)
                    };
                    List <GridRow> listRowValues = new List <GridRow>();
                    _listClinicsInGroup.ForEach(x => {
                        GridRow row = new GridRow(x.Abbr, x.Description);
                        row.Tag     = x;
                        listRowValues.Add(row);
                    });
                    string            formTitle = Lan.g(this, "Clinic Picker");
                    string            gridTitle = Lan.g(this, "Clinics");
                    FormGridSelection form      = new FormGridSelection(listColumnHeaders, listRowValues, formTitle, gridTitle);
                    if (form.ShowDialog() != DialogResult.OK)
                    {
                        MsgBox.Show(this, "A default clinic was not selected.");
                        return;
                    }
                    long clinicNumMaster = ((Clinic)form.ListSelectedTags[0]).ClinicNum;                  //DialogResult.OK means a selection was made.
                    //This list came from _listClinicsInGroup which was used to fill the grid picker that we get clinicNumMaster from.  We need to pop the master
                    //clinic off the list while copying fee schedules or else it will be deleted before copying.
                    //Give the user an out before potentially changing a lot of data in the db.
                    if (!MsgBox.Show(this, MsgBoxButtons.YesNo, "Fees are about to be updated.  Continue?"))
                    {
                        return;
                    }
                    ODProgress.ShowAction(() => {
                        listClinicNumsNew.Remove(clinicNumMaster);
                        FeeScheds.CopyFeeSchedule(feeSchedCur, clinicNumMaster, 0, feeSchedCur, listClinicNumsNew, 0);
                        listClinicNumsNew.Add(clinicNumMaster);
                    }, Lans.g(this, "Creating Group, Please Wait..."));
                }
                else                  //Default fees.
                                      //Give the user an out before potentially changing a lot of data in the db.
                {
                    if (!MsgBox.Show(this, MsgBoxButtons.YesNo, "Fees are about to be updated.  Continue?"))
                    {
                        return;
                    }
                    ODProgress.ShowAction(() => {
                        FeeScheds.CopyFeeSchedule(feeSchedCur, 0, 0, feeSchedCur, listClinicNumsNew, 0);
                    }, Lans.g(this, "Creating Group, Please Wait..."));
                }
            }
            //Existing group, change the fees for all the new clinics in the group. Use the first clinic in the old clinic list as we already did an empty check
            //and the fees should have already been synched previously.
            else
            {
                if (listClinicNumsNew.Except(_feeSchedGroupCur.ListClinicNumsAll).Count() != 0 || _feeSchedGroupCur.ListClinicNumsAll.Except(listClinicNumsNew).Count() != 0)
                {
                    //Give the user an out before potentially changing a lot of data in the db.
                    if (!MsgBox.Show(this, MsgBoxButtons.YesNo, "Clinics added to the group will have their fees updated to match the group.  Clinics removed from" +
                                     " the group will not have their fees changed.  Continue?"))
                    {
                        return;
                    }
                    //For an existing group we can not guarantee that the ClinicNum we are using to copy fee schedules with is actually still in the group. It is ok to
                    //use a ClinicNum that used to be in the group as the fees will still be in sync at this point.
                    //Only update the fees for clinics that were just added to the group, don't attempt to update fess already in the group.
                    List <long> listClinicNumsToSync = listClinicNumsNew.Where(x => !_feeSchedGroupCur.ListClinicNumsAll.Contains(x)).ToList();
                    if (listClinicNumsToSync.Count > 0)
                    {
                        FeeScheds.CopyFeeSchedule(feeSchedCur, _feeSchedGroupCur.ListClinicNumsAll.First(), 0, feeSchedCur, listClinicNumsToSync, 0);
                    }
                }
            }
            _feeSchedGroupCur.Description       = textDescription.Text;
            _feeSchedGroupCur.FeeSchedNum       = feeSchedCur.FeeSchedNum;
            _feeSchedGroupCur.ListClinicNumsAll = listClinicNumsNew;
            DialogResult = DialogResult.OK;
        }