private void gridMain_CellDoubleClick(object sender, ODGridClickEventArgs e) { FormMedLabEdit FormLE = new FormMedLabEdit(); long patNum = 0; string[] patSpecimenIds = gridMain.Rows[e.Row].Tag.ToString().Split(','); if (patSpecimenIds.Length > 0) { patNum = PIn.Long(patSpecimenIds[0]); //if PatNum portion of the tag is an empty string, patNum will remain 0 } FormLE.PatCur = Patients.GetPat(patNum); //could be null if PatNum=0 string specimenId = ""; string specimenIdFiller = ""; if (patSpecimenIds.Length > 1) { specimenId = patSpecimenIds[1]; } if (patSpecimenIds.Length > 2) { specimenIdFiller = patSpecimenIds[2]; } FormLE.ListMedLabs = MedLabs.GetForPatAndSpecimen(patNum, specimenId, specimenIdFiller); //patNum could be 0 if this MedLab is not attached to a pat FormLE.ShowDialog(); FillGrid(); }
///<summary>This will delete all MedLab objects for the specimen referenced by _medLabCur and all MedLabResult, MedLabSpecimen, ///and MedLabFacAttach objects, as well as any documents referenced by the results. The original HL7 message will remain in the image folder, ///but this MedLab will not point to it. We won't remove the HL7 message since there may be other MedLab rows that point to it.</summary> private void butDelete_Click(object sender, EventArgs e) { if (!MsgBox.Show(this, MsgBoxButtons.OKCancel, "This will delete all orders, results, and specimens for this MedLab as well as " + "any associated pdf files.")) { return; } int failedCount = MedLabs.DeleteLabsAndResults(_medLabCur); if (failedCount > 0) { MessageBox.Show(this, Lans.g(this, "Some images referenced by the MedLabResults could not be deleted and will have to be removed manually.") + "\r\n" + Lans.g(this, "Number failed") + ": " + failedCount); } DialogResult = DialogResult.OK; }
private void butProvSelect_Click(object sender, EventArgs e) { FormProviderPick FormPP = new FormProviderPick(); FormPP.ShowDialog(); if (FormPP.DialogResult != DialogResult.OK) { return; } if (FormPP.SelectedProvNum != _medLabCur.ProvNum) { if (!MsgBox.Show(this, MsgBoxButtons.YesNo, "Update all lab tests and results for this specimen with the selected ordering provider?")) { return; } } Provider prov = Providers.GetProv(FormPP.SelectedProvNum); for (int i = 0; i < ListMedLabs.Count; i++) { ListMedLabs[i].OrderingProvLName = prov.LName; ListMedLabs[i].OrderingProvFName = prov.FName; ListMedLabs[i].OrderingProvNPI = prov.NationalProvID; ListMedLabs[i].OrderingProvLocalID = prov.ProvNum.ToString(); ListMedLabs[i].ProvNum = prov.ProvNum; MedLabs.Update(ListMedLabs[i]); } string provName = prov.LName; if (provName != "" && prov.FName != "") { provName += ", "; } provName += prov.FName; textPhysicianName.Text = provName; textPhysicianNPI.Text = prov.NationalProvID; textPhysicianID.Text = prov.ProvNum.ToString(); }
private void FillGrid() { if (IsDisposed) //This can happen if an auto logoff happens with FormMedLabEdit open { return; } if (textDateStart.errorProvider1.GetError(textDateStart) != "" || textDateEnd.errorProvider1.GetError(textDateEnd) != "") { return; } textPatient.Text = ""; if (_selectedPat != null) { textPatient.Text = _selectedPat.GetNameLF(); checkOnlyNoPat.Checked = false; } Application.DoEvents(); gridMain.BeginUpdate(); gridMain.Columns.Clear(); gridMain.Columns.Add(new ODGridColumn("Date & Time Reported", 135, GridSortingStrategy.DateParse)); //most recent date and time a result came in gridMain.Columns.Add(new ODGridColumn("Date & Time Entered", 135, GridSortingStrategy.DateParse)); gridMain.Columns.Add(new ODGridColumn("Status", 75)); gridMain.Columns.Add(new ODGridColumn("Patient", 180)); gridMain.Columns.Add(new ODGridColumn("Provider", 70)); gridMain.Columns.Add(new ODGridColumn("Specimen ID", 100)); //should be the ID sent on the specimen container to lab gridMain.Columns.Add(new ODGridColumn("Test(s) Description", 235)); //description of the test ordered if (PrefC.HasClinicsEnabled) { gridMain.Columns.Add(new ODGridColumn("Clinic", 150)); } gridMain.Rows.Clear(); ODGridRow row; DateTime dateEnd = PIn.Date(textDateEnd.Text); if (dateEnd == DateTime.MinValue) { dateEnd = DateTime.MaxValue; } Cursor = Cursors.WaitCursor; Clinic clinCur = new Clinic(); if (PrefC.HasClinicsEnabled) { clinCur = _listUserClinics[comboClinic.SelectedIndex]; } List <Clinic> listClinicsSelected = new List <Clinic>(); if (clinCur.ClinicNum == -1) //"All" clinic { listClinicsSelected = _listUserClinics.FindAll(x => x.ClinicNum > -1); //will include ClinicNum 0 ("Unassigned" clinic) if user is unrestricted } else //a single clinic was selected, either the "Unassigned" clinic or a regular clinic { listClinicsSelected.Add(clinCur); } List <MedLab> listMedLabs = MedLabs.GetOrdersForPatient(_selectedPat, checkIncludeNoPat.Checked, checkOnlyNoPat.Checked, PIn.Date(textDateStart.Text), dateEnd, listClinicsSelected); Dictionary <long, Patient> dictPats = Patients.GetLimForPats(listMedLabs.Select(x => x.PatNum).Where(x => x > 0).Distinct().ToList()) .ToDictionary(x => x.PatNum); foreach (MedLab medLabCur in listMedLabs) { row = new ODGridRow(); row.Cells.Add(medLabCur.DateTimeReported.ToString("MM/dd/yyyy hh:mm tt")); row.Cells.Add(medLabCur.DateTimeEntered.ToString("MM/dd/yyyy hh:mm tt")); if (medLabCur.IsPreliminaryResult) //check whether the test or any of the most recent results for the test is marked as preliminary { row.Cells.Add(MedLabs.GetStatusDescript(ResultStatus.P)); } else { row.Cells.Add(MedLabs.GetStatusDescript(medLabCur.ResultStatus)); } string nameFL = ""; if (dictPats.ContainsKey(medLabCur.PatNum)) { nameFL = dictPats[medLabCur.PatNum].GetNameFLnoPref(); } row.Cells.Add(nameFL); row.Cells.Add(Providers.GetAbbr(medLabCur.ProvNum)); //will be blank if ProvNum=0 row.Cells.Add(medLabCur.SpecimenID); row.Cells.Add(medLabCur.ObsTestDescript); if (PrefC.HasClinicsEnabled) { string clinicDesc = ""; if (_dictLabAcctClinic.ContainsKey(medLabCur.PatAccountNum)) { clinicDesc = _dictLabAcctClinic[medLabCur.PatAccountNum]; } row.Cells.Add(clinicDesc); } row.Tag = medLabCur.PatNum.ToString() + "," + medLabCur.SpecimenID + "," + medLabCur.SpecimenIDFiller; gridMain.Rows.Add(row); } gridMain.EndUpdate(); Cursor = Cursors.Default; }
private void FormMedLabs_Load(object sender, EventArgs e) { _selectedPat = PatCur; if (_selectedPat == null) { checkIncludeNoPat.Checked = true; checkOnlyNoPat.Checked = true; } textDateStart.Text = DateTime.Today.AddMonths(-3).ToShortDateString(); //default list to start with showing the last three months //One time reconcile may need to be run to create embedded PDFs for MedLabs that are not attached to a patient. if (!PrefC.GetBool(PrefName.MedLabReconcileDone) && PrefC.AtoZfolderUsed != DataStorageType.InDatabase) { int countMedLabs = MedLabs.GetCountForPatient(0); if (MessageBox.Show(this, Lan.g(this, "There are MedLabs in the database that have not been associated with a patient.\r\nA one time " + "reconciliation must be performed that will reprocess the HL7 messages for these MedLabs. This can take some time.\r\nDo you want to " + "continue?\r\nNumber of MedLabs not associated with a patient") + ": " + countMedLabs + ".", "", MessageBoxButtons.YesNo) == DialogResult.No) { Close(); return; } Cursor = Cursors.WaitCursor; int reconcileFailedCount = MedLabs.Reconcile(); Cursor = Cursors.Default; if (reconcileFailedCount > 0) { MessageBox.Show(this, Lan.g(this, "Some of the MedLab objects in the database could not be reconciled.\r\nThis may be due to an issue " + "processing the original HL7 message text file.\r\nNumber failed") + ": " + reconcileFailedCount); } Prefs.UpdateBool(PrefName.MedLabReconcileDone, true); DataValid.SetInvalid(InvalidType.Prefs); } _dictLabAcctClinic = new Dictionary <string, string>(); _listUserClinics = new List <Clinic>(); if (PrefC.HasClinicsEnabled) { _listUserClinics.Add(new Clinic() { ClinicNum = -1, Description = Lan.g(this, "All") }); //ClinicNum will be -1 at index 0, "All" means all the user has access to if (!Security.CurUser.ClinicIsRestricted) { //ClinicNum 0 at index==1, "Headquarters" means any where MedLab.PatAccountNum does not match any clinic.MedLabAccountNum _listUserClinics.Add(new Clinic() { ClinicNum = 0, Description = Lan.g(this, "Unassigned") }); } _listUserClinics.AddRange(Clinics.GetForUserod(Security.CurUser)); _listUserClinics.ForEach(x => comboClinic.Items.Add(x.Description)); _dictLabAcctClinic = _listUserClinics.Where(x => !string.IsNullOrEmpty(x.MedLabAccountNum)) .ToDictionary(x => x.MedLabAccountNum, x => x.Description); if (!Security.CurUser.ClinicIsRestricted && Clinics.ClinicNum == 0) //if unrestricted and the currently selected clinic is HQ { comboClinic.SelectedIndex = 1; //all users will have the "All" clinic, unrestricted users will also have the "Unassigned" clinic, so index==1 } else { comboClinic.SelectedIndex = _listUserClinics.FindIndex(x => x.ClinicNum == Clinics.ClinicNum); } if (comboClinic.SelectedIndex < 0) { comboClinic.SelectedIndex = 0; } } else { comboClinic.Visible = false; labelClinic.Visible = false; FillGrid(); //if clinics are enabled, comboClinic.SelectedIndexChanged event handler will fill the grid, no need to call FillGrid } }
private void FillGridResultHist() { MedLab medLabCur = MedLabs.GetOne(ResultCur.MedLabNum); if (medLabCur == null) //should never happen, but we must have a MedLab object to fill the grid { return; } gridResultHist.BeginUpdate(); gridResultHist.Columns.Clear(); ODGridColumn col; col = new ODGridColumn("Result Description / Value", 425); gridResultHist.Columns.Add(col); col = new ODGridColumn("Flag", 110); gridResultHist.Columns.Add(col); col = new ODGridColumn("Units", 65); gridResultHist.Columns.Add(col); col = new ODGridColumn("Date/Time Reported", 130); //OBR-22, Date/Time Observations Reported col.SortingStrategy = GridSortingStrategy.DateParse; gridResultHist.Columns.Add(col); col = new ODGridColumn("Date/Time Observed", 130); //OBX-11, Date/Time of Observation col.SortingStrategy = GridSortingStrategy.DateParse; gridResultHist.Columns.Add(col); col = new ODGridColumn("Status", 70); gridResultHist.Columns.Add(col); gridResultHist.Rows.Clear(); ODGridRow row; long patNum = 0; if (PatCur != null) { patNum = PatCur.PatNum; } List <MedLabResult> listResults = MedLabResults.GetResultHist(ResultCur, patNum, medLabCur.SpecimenID, medLabCur.SpecimenIDFiller); for (int i = 0; i < listResults.Count; i++) { row = new ODGridRow(); string obsVal = listResults[i].ObsText; if (listResults[i].ObsValue != "Test Not Performed") { obsVal += "\r\n " + listResults[i].ObsValue.Replace("\r\n", "\r\n "); } if (listResults[i].Note != "") { obsVal += "\r\n " + listResults[i].Note.Replace("\r\n", "\r\n "); } row.Cells.Add(obsVal); row.Cells.Add(MedLabResults.GetAbnormalFlagDescript(listResults[i].AbnormalFlag)); row.Cells.Add(listResults[i].ObsUnits); medLabCur = MedLabs.GetOne(listResults[i].MedLabNum); string dateReported = ""; if (medLabCur != null) { dateReported = medLabCur.DateTimeReported.ToString("MM/dd/yyyy hh:mm tt"); //DT format matches LabCorp examples (US only company) } row.Cells.Add(dateReported); row.Cells.Add(listResults[i].DateTimeObs.ToString("MM/dd/yyyy hh:mm tt")); //DT format matches LabCorp examples (US only company) row.Cells.Add(MedLabs.GetStatusDescript(listResults[i].ResultStatus)); gridResultHist.Rows.Add(row); } gridResultHist.EndUpdate(); }
///<summary>Moves all MedLab objects and any embedded PDFs tied to the MedLabResults to the PatCur. ///If the MedLab objects were not originally attached to a patient, any embedded PDFs will be in the image folder in a directory called ///"MedLabEmbeddedFiles" and will be moved to PatCur's image folder. ///If PatCur is null or the MedLabs are already attached to PatCur, does nothing.</summary> private void MoveLabsAndImagesHelper() { //if they have selected the same patient, nothing to do if (PatCur == null || PatCur.PatNum == _medLabCur.PatNum) { return; } //if the MedLab object(s) were attached to a patient and they are being moved to another patient, move the associated documents Patient patOld = Patients.GetPat(_medLabCur.PatNum); MedLabs.UpdateAllPatNums(ListMedLabs.Select(x => x.MedLabNum).ToList(), PatCur.PatNum); string atozFrom = ""; string atozTo = ""; if (PrefC.AtoZfolderUsed == DataStorageType.LocalAtoZ) { string atozPath = ImageStore.GetPreferredAtoZpath(); //if patOld is null, the file was placed into the image folder in a directory named MedLabEmbeddedFiles, not a patient's image folder if (patOld == null) { atozFrom = ODFileUtils.CombinePaths(atozPath, "MedLabEmbeddedFiles"); } else { atozFrom = ImageStore.GetPatientFolder(patOld, atozPath); } atozTo = ImageStore.GetPatientFolder(PatCur, atozPath); } else if (CloudStorage.IsCloudStorage) { atozFrom = ODFileUtils.CombinePaths(ImageStore.GetPreferredAtoZpath(), "MedLabEmbeddedFiles", '/'); atozTo = ImageStore.GetPatientFolder(PatCur, ""); } //get list of all DocNums of files referenced by MedLabResults which were embedded in the MedLab HL7 message as base64 text //in order to move the file (if not storing images in db) and assign (or reassign) the FileName List <long> listDocNums = ListMedLabs .SelectMany(x => x.ListMedLabResults .Select(y => y.DocNum) .Where(y => y > 0)) .Distinct().ToList(); List <Document> listDocs = Documents.GetByNums(listDocNums); int fileMoveFailures = 0; for (int i = 0; i < listDocs.Count; i++) { Document doc = listDocs[i]; string destFileName = Documents.GetUniqueFileNameForPatient(PatCur, doc.DocNum, Path.GetExtension(doc.FileName)); if (PrefC.AtoZfolderUsed == DataStorageType.LocalAtoZ) { string fromFilePath = ODFileUtils.CombinePaths(atozFrom, doc.FileName); if (!File.Exists(fromFilePath)) { //the DocNum in the MedLabResults table is pointing to a file that either doesn't exist or is not accessible, can't move/copy it fileMoveFailures++; continue; } string destFilePath = ODFileUtils.CombinePaths(atozTo, destFileName); if (File.Exists(destFilePath)) //should never happen, since we already got a unique file name, but just in case //The file being copied has the same name as a file that exists in the destination folder, use a unique file name and update document table { destFileName = patOld.PatNum.ToString() + "_" + doc.FileName; //try to prepend patient's PatNum to the original file name destFilePath = ODFileUtils.CombinePaths(atozTo, destFileName); while (File.Exists(destFilePath)) { //if still not unique, try appending date/time to seconds precision until the file name is unique destFileName = patOld.PatNum.ToString() + "_" + Path.GetFileNameWithoutExtension(doc.FileName) + "_" + DateTime.Now.ToString("yyyyMMddhhmmss") + Path.GetExtension(doc.FileName); destFilePath = ODFileUtils.CombinePaths(atozTo, destFileName); } } try { File.Copy(fromFilePath, destFilePath); } catch (Exception ex) { ex.DoNothing(); fileMoveFailures++; continue; } //try to delete the original file try { File.Delete(fromFilePath); } catch (Exception ex) { ex.DoNothing(); //If we cannot delete the file, could be a permission issue or someone has the file open currently //Just skip deleting the file, which means there could be an image in the old pat's folder that may need to be deleted manually fileMoveFailures++; } } else if (CloudStorage.IsCloudStorage) { //move files around in the cloud FormProgress FormP = new FormProgress(false); FormP.DisplayText = "Uploading..."; FormP.NumberFormat = "F"; FormP.NumberMultiplication = 1; FormP.MaxVal = 100; //Doesn't matter what this value is as long as it is greater than 0 FormP.TickMS = 1000; OpenDentalCloud.Core.TaskStateMove state = CloudStorage.MoveAsync(atozFrom , atozTo , new OpenDentalCloud.ProgressHandler(FormP.OnProgress)); FormP.ShowDialog(); //Don't allow users to cancel from here due to the limitations of the current feature for figuring out which files were moved successfully. } //if we get here the file was copied successfully or not storing images in the database, so update the document row //Safe to update the document FileName and PatNum to PatCur and new file name doc.PatNum = PatCur.PatNum; doc.FileName = destFileName; Documents.Update(doc); } ListMedLabs.ForEach(x => x.PatNum = PatCur.PatNum); //update local list, done after moving files _medLabCur = ListMedLabs[0]; if (fileMoveFailures > 0) //will never be > 0 if storing images in the db { MessageBox.Show(Lan.g(this, "Some files attached to the MedLab objects could not be moved.") + "\r\n" + Lan.g(this, "This could be due to a missing file, a file being open, or a permission issue on the file which is preventing the move.") + "\r\n" + Lan.g(this, "The file(s) will have to be moved manually from the Image module.") + "\r\n" + Lan.g(this, "Number of files not moved") + ": " + fileMoveFailures.ToString()); } }
///<summary>Formatting for fields in this grid designed to emulate as accurately as possible the sample provided by LabCorp.</summary> private void FillGridResults() { gridResults.BeginUpdate(); gridResults.Columns.Clear(); ODGridColumn col; col = new ODGridColumn("Test / Result", 500); gridResults.Columns.Add(col); col = new ODGridColumn("Flag", 115); gridResults.Columns.Add(col); col = new ODGridColumn("Units", 110); gridResults.Columns.Add(col); col = new ODGridColumn("Reference Interval", 145); gridResults.Columns.Add(col); col = new ODGridColumn("Lab", 60); gridResults.Columns.Add(col); gridResults.Rows.Clear(); ODGridRow row; string obsDescriptPrev = ""; for (int i = 0; i < _listResults.Count; i++) { //LabCorp requested that these non-performance results not be displayed on the report if ((_listResults[i].ResultStatus == ResultStatus.F || _listResults[i].ResultStatus == ResultStatus.X) && _listResults[i].ObsValue == "" && _listResults[i].Note == "") { continue; } string obsDescript = ""; MedLab medLabCur = MedLabs.GetOne(_listResults[i].MedLabNum); //Only dipslay full medLabCur.ObsTestDescript if different than previous Descript. if (i == 0 || _listResults[i].MedLabNum != _listResults[i - 1].MedLabNum) { if (medLabCur.ActionCode != ResultAction.G) { if (obsDescriptPrev == medLabCur.ObsTestDescript) { obsDescript = "."; } else { obsDescript = medLabCur.ObsTestDescript; obsDescriptPrev = obsDescript; } } } //Set tabs using spaces and spaces2, can be changed further down in the code string spaces = " "; string spaces2 = " "; string obsVal = ""; int padR = 78; string newLine = ""; if (obsDescript != "") { if (obsDescript == _listResults[i].ObsText) { spaces = ""; spaces2 = " "; padR = 80; } else { obsVal += obsDescript + "\r\n"; newLine += "\r\n"; } } if (_listResults[i].ObsValue == "Test Not Performed") { obsVal += spaces + _listResults[i].ObsText; } else if (_listResults[i].ObsText == "." || _listResults[i].ObsValue.Contains(":") || _listResults[i].ObsValue.Length > 20 || medLabCur.ActionCode == ResultAction.G) { obsVal += spaces + _listResults[i].ObsText + "\r\n" + spaces2 + _listResults[i].ObsValue.Replace("\r\n", "\r\n" + spaces2); newLine += "\r\n"; } else { obsVal += spaces + _listResults[i].ObsText.PadRight(padR, ' ') + _listResults[i].ObsValue; } if (_listResults[i].Note != "") { obsVal += "\r\n" + spaces2 + _listResults[i].Note.Replace("\r\n", "\r\n" + spaces2); } row = new ODGridRow(); row.Cells.Add(obsVal); row.Cells.Add(newLine + MedLabResults.GetAbnormalFlagDescript(_listResults[i].AbnormalFlag)); row.Cells.Add(newLine + _listResults[i].ObsUnits); row.Cells.Add(newLine + _listResults[i].ReferenceRange); row.Cells.Add(newLine + _listResults[i].FacilityID); row.Tag = _listResults[i]; gridResults.Rows.Add(row); } gridResults.EndUpdate(); }