///<summary>Fills both the Specialty and Clinic combo boxes according to the available clinics to the user and the unused specialties for the patient. ///Only fills the combo box of clinics with clinics that are associated to specialties that have not been used for this patient yet. ///E.g. Even if the user has access to Clinic X, if there is already a clone of this patient for Clinic X, it will no longer show. ///Throws exceptions that should be shown to the user which should then be followed by closing the window.</summary> private void FillClinicComboBoxes() { _dictSpecialtyClinics = new Dictionary <long, List <Clinic> >(); //Fill the list of clinics for this user. List <Clinic> listClinicsForUser = Clinics.GetForUserod(Security.CurUser); //Make a deep copy of the list of clinics so that we can filter down to the clinics that have no specialty specified if all are hidden. List <Clinic> listClinicsNoSpecialty = listClinicsForUser.Select(x => x.Copy()).ToList(); //Fill the list of defLinks used by clones of this patient. List <long> listClonePatNum = PatientLinks.GetPatNumsLinkedFrom(_patientMaster.PatNum, PatientLinkType.Clone); List <DefLink> listPatCurDefLinks = DefLinks.GetListByFKeys(listClonePatNum, DefLinkType.Patient); //Fill the list of clinics defLink List <DefLink> listClinicDefLinks = DefLinks.GetDefLinksByType(DefLinkType.Clinic); //Filter out any specialties that are currently in use by clones of this patient. if (listPatCurDefLinks.Count > 0) { listClinicDefLinks.RemoveAll(x => x.DefNum.In(listPatCurDefLinks.Select(y => y.DefNum).ToList())); } //Get all non-hidden specialties List <Def> listSpecialtyDefs = Defs.GetDefsForCategory(DefCat.ClinicSpecialty, true); //If there are specialties present, we need to know which clinics have no specialty set so that the user can always make clones for that specialty. if (listSpecialtyDefs.Count > 0) { listClinicsNoSpecialty.RemoveAll(x => x.ClinicNum.In(listClinicDefLinks.Select(y => y.FKey).ToList())); } //Remove all clinics that do not have any specialties from the original list of clinics for the user. listClinicsForUser.RemoveAll(x => !x.ClinicNum.In(listClinicDefLinks.Select(y => y.FKey).ToList())); //Filter out any specialties that are not associated to any available clinics for this user. listSpecialtyDefs.RemoveAll(x => !x.DefNum.In(listClinicDefLinks.Select(y => y.DefNum).ToList())); //Lump all of the left over specialties into a dictionary and slap the associated clinics to them. comboSpecialty.Items.Clear(); //Create a dummy specialty of 0 if there are any clinics that do not have a specialty. if (listClinicsNoSpecialty != null && listClinicsNoSpecialty.Count > 0) { comboSpecialty.Items.Add(new ODBoxItem <Def>(Lan.g(this, "Unspecified"), new Def() { DefNum = 0 })); _dictSpecialtyClinics[0] = listClinicsNoSpecialty; } foreach (Def specialty in listSpecialtyDefs) { comboSpecialty.Items.Add(new ODBoxItem <Def>(specialty.ItemName, specialty)); //Get a list of all deflinks for the def List <DefLink> listLinkForDef = listClinicDefLinks.FindAll(x => x.DefNum == specialty.DefNum).ToList(); _dictSpecialtyClinics[specialty.DefNum] = listClinicsForUser.FindAll(x => x.ClinicNum.In(listLinkForDef.Select(y => y.FKey).ToList())); } //If there are no specialties to show, we need to let the user know that they need to associate at least one clinic to a specialty. if (_dictSpecialtyClinics.Count < 1) { MsgBox.Show(this, "This patient already has a clone for every Clinic Specialty available.\r\n" + "In the main menu, click Setup, Definitions, Clinic Specialties category to add new specialties.\r\n" + "In the main menu, click Lists, Clinics, and double click a clinic to set a Specialty."); DialogResult = DialogResult.Abort; return; } comboSpecialty.SelectedIndex = 0; FillComboClinic(); }
///<summary>Returns true if the user switched to a different patient.</summary> public static bool PromptForMerge(Patient patCur, out Patient newPatCur) { newPatCur = patCur; if (patCur == null) { return(false); } List <PatientLink> listMergedPats = PatientLinks.GetLinks(patCur.PatNum, PatientLinkType.Merge); if (!PatientLinks.WasPatientMerged(patCur.PatNum, listMergedPats)) { return(false); } //This patient has been merged before. Get a list of all patients that this patient has been merged into. List <Patient> listPats = Patients.GetMultPats(listMergedPats.Where(x => x.PatNumTo != patCur.PatNum) .Select(x => x.PatNumTo).ToList()).ToList(); //Notify the user that the currently selected patient has been merged before and then ask them if they want to switch to the correct patient. foreach (Patient pat in listPats) { if (pat.PatStatus.In(PatientStatus.Patient, PatientStatus.Inactive) && (MessageBox.Show(Lan.g("ContrAppt", "The currently selected patient has been merged into another patient.\r\n" + "Switch to patient") + " " + pat.GetNameLF() + " #" + pat.PatNum.ToString() + "?", "", MessageBoxButtons.YesNo) == DialogResult.Yes)) { newPatCur = pat; return(true); } } //The user has declined every possible patient that the current patient was merged to. Let them keep the merge from patient selected. return(false); }
///<summary>Used in the case when clinics are disabled. Requires special logic that doesn't use clinics.</summary> private void FillComboSpecialtyNoClinics() { //Get all non-hidden specialties List <Def> listSpecialtyDefs = Defs.GetDefsForCategory(DefCat.ClinicSpecialty, true); //Fill the list of defLinks used by clones of this patient. List <long> listClonePatNums = PatientLinks.GetPatNumsLinkedFrom(_patientMaster.PatNum, PatientLinkType.Clone); List <DefLink> listPatCurDefLinks = DefLinks.GetListByFKeys(listClonePatNums, DefLinkType.Patient); //Filter out any specialties that are currently in use by clones of this patient. if (listPatCurDefLinks.Count > 0) { listSpecialtyDefs.RemoveAll(x => x.DefNum.In(listPatCurDefLinks.Select(y => y.DefNum).ToList())); } comboSpecialty.Items.Clear(); //Create a dummy specialty of 0. Always allow the user to make Unspecified clones. comboSpecialty.Items.Add(new ODBoxItem <Def>(Lan.g(this, "Unspecified"), new Def() { DefNum = 0 })); foreach (Def specialty in listSpecialtyDefs) { comboSpecialty.Items.Add(new ODBoxItem <Def>(specialty.ItemName, specialty)); } comboSpecialty.SelectedIndex = 0; }
private void FillList() { listPats.Items.Clear(); for (int i = 0; i < FamCur.ListPats.Length; i++) { if (PatientLinks.WasPatientMerged(FamCur.ListPats[i].PatNum, _listMergeLinks)) { continue; //Don't show merged patients } listPats.Items.Add(new ODBoxItem <Patient>(FamCur.ListPats[i].GetNameFL(), FamCur.ListPats[i])); } }
private void FillList() { listPats.Items.Clear(); for (int i = 0; i < FamCur.ListPats.Length; i++) { if (PatientLinks.WasPatientMerged(FamCur.ListPats[i].PatNum, _listMergeLinks)) { continue; //Don't show merged patients } listPats.Items.Add(new ODBoxItem <Patient>(FamCur.ListPats[i].GetNameFL() + " (" + Lan.g("enumPatientStatus", FamCur.ListPats[i].PatStatus.GetDescription()) + ")", FamCur.ListPats[i])); } }
private void FormCloneAdd_Load(object sender, EventArgs e) { //Make sure that this patient is not already a clone of another patient. We don't allow clones of clones. //PatientLink.PatNumFrom is the master and PatientLink.PatNumTo is the actual clone. We care if this patient has ever been a "PatNumTo". if (PatientLinks.IsPatientAClone(_patientMaster.PatNum)) { MsgBox.Show(this, "Cannot create a clone of a clone. Please select the original patient in order to create another clone."); return; } textLName.Text = _patientMaster.LName; textFName.Text = _patientMaster.FName; textPreferred.Text = _patientMaster.Preferred; textMiddleI.Text = _patientMaster.MiddleI; textBirthDate.Text = (_patientMaster.Birthdate.Year < 1880) ? "" : _patientMaster.Birthdate.ToShortDateString(); textAge.Text = PatientLogic.DateToAgeString(_patientMaster.Birthdate, _patientMaster.DateTimeDeceased); //We intentionally don't synch the patient's provider since the clone feature is so the clone can be assigned to a different provider for tracking production. _provNumSelected = PrefC.GetLong(PrefName.PracticeDefaultProv); _listProviders = Providers.GetDeepCopy(true); comboPriProv.Items.Clear(); for (int i = 0; i < _listProviders.Count; i++) { comboPriProv.Items.Add(_listProviders[i].GetLongDesc()); if (_listProviders[i].ProvNum == _provNumSelected) { comboPriProv.SelectedIndex = i; } } if (_provNumSelected == 0) { comboPriProv.SelectedIndex = 0; _provNumSelected = _listProviders[0].ProvNum; } if (comboPriProv.SelectedIndex == -1) { comboPriProv.Text = Providers.GetLongDesc(_provNumSelected); } labelSpecialty.Visible = true; comboSpecialty.Visible = true; if (PrefC.HasClinicsEnabled) { labelClinic.Visible = true; comboClinic.Visible = true; FillClinicComboBoxes(); } else //Without clinics enabled the specialty box is filled differently. { FillComboSpecialtyNoClinics(); } }
///<summary>Deletes the PaySimple token if there is one. Returns false if deleting the token failed.</summary> private bool DeletePaySimpleToken() { if (CreditCardCur.PaySimpleToken != "") { Cursor = Cursors.WaitCursor; try { if (CreditCardCur.CCSource == CreditCardSource.PaySimpleACH) { PaySimple.DeleteACHAccount(CreditCardCur); } else if (CreditCardCur.CCSource == CreditCardSource.PaySimple) //Credit card { PaySimple.DeleteCreditCard(CreditCardCur); } } catch (PaySimpleException ex) { MessageBox.Show(ex.Message); if (ex.ErrorType == PaySimpleError.CustomerDoesNotExist && MsgBox.Show(this, MsgBoxButtons.OKCancel, "Delete the link to the customer id for this patient?")) { PatientLinks.DeletePatNumTos(ex.CustomerId, PatientLinkType.PaySimple); } return(false); } catch (Exception ex) { if (MessageBox.Show(Lans.g(this, "Error when deleting from PaySimple:") + "\r\n" + ex.Message + "\r\n\r\n" + Lans.g(this, "Do you still want to delete the card from ") + PrefC.GetString(PrefName.SoftwareName) + "?", "", MessageBoxButtons.YesNo) == DialogResult.No) { return(false); } } finally { Cursor = Cursors.Default; } } return(true); }
private void FillFamily() { PatNumSelected = _patCur.PatNum; //just in case user has selected a different family member _listRecalls = Recalls.GetList(_famCur.ListPats.ToList()); //Appointment[] aptsOnePat; List <PatientLink> listLinks = PatientLinks.GetLinks(_famCur.ListPats.Select(x => x.PatNum).ToList(), PatientLinkType.Merge); listViewFamily.Items.Clear(); ListViewItem item; DateTime dateDue; DateTime dateSched; for (int i = 0; i < _famCur.ListPats.Length; i++) { if (PatientLinks.WasPatientMerged(_famCur.ListPats[i].PatNum, listLinks)) { continue; //Do not include Merged patients in the displayed list. } item = new ListViewItem(_famCur.GetNameInFamFLI(i)); item.Tag = _famCur.ListPats[i]; if (_famCur.ListPats[i].PatNum == _patCur.PatNum) { item.BackColor = Color.Silver; } item.SubItems.Add(_famCur.ListPats[i].Age.ToString()); item.SubItems.Add(_famCur.ListPats[i].Gender.ToString()); dateDue = DateTime.MinValue; dateSched = DateTime.MinValue; bool isdisabled = false; for (int j = 0; j < _listRecalls.Count; j++) { if (_listRecalls[j].PatNum == _famCur.ListPats[i].PatNum && (_listRecalls[j].RecallTypeNum == RecallTypes.PerioType || _listRecalls[j].RecallTypeNum == RecallTypes.ProphyType)) { dateDue = _listRecalls[j].DateDue; dateSched = _listRecalls[j].DateScheduled; isdisabled = _listRecalls[j].IsDisabled; } } if (isdisabled) { item.SubItems.Add(Lan.g(this, "disabled")); } else if (dateDue.Year < 1880) { item.SubItems.Add(""); } else { item.SubItems.Add(dateDue.ToShortDateString()); } if (dateDue <= DateTime.Today) { item.ForeColor = Color.Red; } if (dateSched.Year < 1880) { item.SubItems.Add(""); } else { item.SubItems.Add(dateSched.ToShortDateString()); } listViewFamily.Items.Add(item); } checkDone.Checked = _patCur.PlannedIsDone; textFinUrg.Text = _famCur.ListPats[0].FamFinUrgNote; }
public static bool Trigger <T>(AutomationTrigger trigger, List <string> procCodes, long patNum, long aptNum = 0, T triggerObj = default(T)) { if (patNum == 0) //Could happen for OpenPatient trigger { return(false); } List <Automation> listAutomations = Automations.GetDeepCopy(); bool automationHappened = false; for (int i = 0; i < listAutomations.Count; i++) { if (listAutomations[i].Autotrigger != trigger) { continue; } if (trigger == AutomationTrigger.CompleteProcedure || trigger == AutomationTrigger.ScheduleProcedure) { if (procCodes == null || procCodes.Count == 0) { continue; //fail silently } string[] arrayCodes = listAutomations[i].ProcCodes.Split(','); if (procCodes.All(x => !arrayCodes.Contains(x))) { continue; } } //matching automation item has been found //Get possible list of conditions that exist for this automation item List <AutomationCondition> autoConditionsList = AutomationConditions.GetListByAutomationNum(listAutomations[i].AutomationNum); if (autoConditionsList.Count > 0 && !CheckAutomationConditions(autoConditionsList, patNum, triggerObj)) { continue; } SheetDef sheetDef; Sheet sheet; FormSheetFillEdit FormSF; Appointment aptNew; Appointment aptOld; switch (listAutomations[i].AutoAction) { case AutomationAction.CreateCommlog: if (Plugins.HookMethod(null, "AutomationL.Trigger_CreateCommlog_start", patNum, aptNum, listAutomations[i].CommType, listAutomations[i].MessageContent, trigger)) { automationHappened = true; continue; } Commlog commlogCur = new Commlog(); commlogCur.PatNum = patNum; commlogCur.CommDateTime = DateTime.Now; commlogCur.CommType = listAutomations[i].CommType; commlogCur.Note = listAutomations[i].MessageContent; commlogCur.Mode_ = CommItemMode.None; commlogCur.UserNum = Security.CurUser.UserNum; commlogCur.IsNew = true; FormCommItem commItemView = new FormCommItem(commlogCur); commItemView.ShowDialog(); automationHappened = true; continue; case AutomationAction.PopUp: MessageBox.Show(listAutomations[i].MessageContent); automationHappened = true; continue; case AutomationAction.PopUpThenDisable10Min: Plugins.HookAddCode(null, "AutomationL.Trigger_PopUpThenDisable10Min_begin", listAutomations[i], procCodes, patNum); long automationNum = listAutomations[i].AutomationNum; bool hasAutomationBlock = FormOpenDental.DicBlockedAutomations.ContainsKey(automationNum); if (hasAutomationBlock && FormOpenDental.DicBlockedAutomations[automationNum].ContainsKey(patNum)) //Automation block exist for current patient. { continue; } if (hasAutomationBlock) { FormOpenDental.DicBlockedAutomations[automationNum].Add(patNum, DateTime.Now.AddMinutes(10)); //Disable for 10 minutes. } else //Add automationNum to higher level dictionary . { FormOpenDental.DicBlockedAutomations.Add(automationNum, new Dictionary <long, DateTime>() { { patNum, DateTime.Now.AddMinutes(10) } //Disable for 10 minutes. }); } MessageBox.Show(listAutomations[i].MessageContent); automationHappened = true; continue; case AutomationAction.PrintPatientLetter: case AutomationAction.ShowExamSheet: case AutomationAction.ShowConsentForm: sheetDef = SheetDefs.GetSheetDef(listAutomations[i].SheetDefNum); sheet = SheetUtil.CreateSheet(sheetDef, patNum); SheetParameter.SetParameter(sheet, "PatNum", patNum); SheetFiller.FillFields(sheet); SheetUtil.CalculateHeights(sheet); FormSF = new FormSheetFillEdit(sheet); FormSF.ShowDialog(); automationHappened = true; continue; case AutomationAction.PrintReferralLetter: long referralNum = RefAttaches.GetReferralNum(patNum); if (referralNum == 0) { MsgBox.Show("Automations", "This patient has no referral source entered."); automationHappened = true; continue; } sheetDef = SheetDefs.GetSheetDef(listAutomations[i].SheetDefNum); sheet = SheetUtil.CreateSheet(sheetDef, patNum); SheetParameter.SetParameter(sheet, "PatNum", patNum); SheetParameter.SetParameter(sheet, "ReferralNum", referralNum); //Don't fill these params if the sheet doesn't use them. if (sheetDef.SheetFieldDefs.Any(x => (x.FieldType == SheetFieldType.Grid && x.FieldName == "ReferralLetterProceduresCompleted") || (x.FieldType == SheetFieldType.Special && x.FieldName == "toothChart"))) { List <Procedure> listProcs = Procedures.GetCompletedForDateRange(DateTime.Today, DateTime.Today , listPatNums: new List <long>() { patNum } , includeNote: true , includeGroupNote: true ); if (sheetDef.SheetFieldDefs.Any(x => x.FieldType == SheetFieldType.Grid && x.FieldName == "ReferralLetterProceduresCompleted")) { SheetParameter.SetParameter(sheet, "CompletedProcs", listProcs); } if (sheetDef.SheetFieldDefs.Any(x => x.FieldType == SheetFieldType.Special && x.FieldName == "toothChart")) { SheetParameter.SetParameter(sheet, "toothChartImg", SheetPrinting.GetToothChartHelper(patNum, false, listProceduresFilteredOverride: listProcs)); } } SheetFiller.FillFields(sheet); SheetUtil.CalculateHeights(sheet); FormSF = new FormSheetFillEdit(sheet); FormSF.ShowDialog(); automationHappened = true; continue; case AutomationAction.SetApptASAP: aptNew = Appointments.GetOneApt(aptNum); if (aptNew == null) { MsgBox.Show("Automations", "Invalid appointment for automation."); automationHappened = true; continue; } aptOld = aptNew.Copy(); aptNew.Priority = ApptPriority.ASAP; Appointments.Update(aptNew, aptOld); //Appointments S-Class handles Signalods continue; case AutomationAction.SetApptType: aptNew = Appointments.GetOneApt(aptNum); if (aptNew == null) { MsgBox.Show("Automations", "Invalid appointment for automation."); automationHappened = true; continue; } aptOld = aptNew.Copy(); aptNew.AppointmentTypeNum = listAutomations[i].AppointmentTypeNum; AppointmentType aptTypeCur = AppointmentTypes.GetFirstOrDefault(x => x.AppointmentTypeNum == aptNew.AppointmentTypeNum); if (aptTypeCur != null) { aptNew.ColorOverride = aptTypeCur.AppointmentTypeColor; aptNew.Pattern = AppointmentTypes.GetTimePatternForAppointmentType(aptTypeCur); List <Procedure> listProcs = Appointments.ApptTypeMissingProcHelper(aptNew, aptTypeCur, new List <Procedure>()); Procedures.UpdateAptNums(listProcs.Select(x => x.ProcNum).ToList(), aptNew.AptNum, aptNew.AptStatus == ApptStatus.Planned); } Appointments.Update(aptNew, aptOld); //Appointments S-Class handles Signalods continue; case AutomationAction.PatRestrictApptSchedTrue: if (!Security.IsAuthorized(Permissions.PatientApptRestrict, true)) { SecurityLogs.MakeLogEntry(Permissions.PatientApptRestrict, patNum, "Attempt to restrict patient scheduling was blocked due to lack of user permission."); continue; } PatRestrictions.Upsert(patNum, PatRestrict.ApptSchedule); automationHappened = true; continue; case AutomationAction.PatRestrictApptSchedFalse: if (!Security.IsAuthorized(Permissions.PatientApptRestrict, true)) { SecurityLogs.MakeLogEntry(Permissions.PatientApptRestrict, patNum, "Attempt to allow patient scheduling was blocked due to lack of user permission."); continue; } PatRestrictions.RemovePatRestriction(patNum, PatRestrict.ApptSchedule); automationHappened = true; continue; case AutomationAction.PrintRxInstruction: List <RxPat> listRx = (List <RxPat>)(object) triggerObj; if (listRx == null) { //Got here via a pre-existing trigger that doesn't pass in triggerObj. We now block creation of automation triggers that could get //here via code that does not pass in triggerObj. continue; } //We go through each new Rx where the patient note isn't blank. //There should only usually be one new rx, but we'll loop just in case. foreach (RxPat rx in listRx.Where(x => !string.IsNullOrWhiteSpace(x.PatientInstruction))) { //This logic is an exact copy of FormRxManage.butPrintSelect_Click()'s logic when 1 Rx is selected. //If this is updated, that method needs to be updated as well. sheetDef = SheetDefs.GetSheetDef(listAutomations[i].SheetDefNum); sheet = SheetUtil.CreateSheet(sheetDef, patNum); SheetParameter.SetParameter(sheet, "RxNum", rx.RxNum); SheetFiller.FillFields(sheet); SheetUtil.CalculateHeights(sheet); FormSF = new FormSheetFillEdit(sheet); FormSF.ShowDialog(); automationHappened = true; } continue; case AutomationAction.ChangePatStatus: Patient pat = Patients.GetPat(patNum); Patient patOld = pat.Copy(); pat.PatStatus = listAutomations[i].PatStatus; //Don't allow changing status from Archived if this is a merged patient. if (patOld.PatStatus != pat.PatStatus && patOld.PatStatus == PatientStatus.Archived && PatientLinks.WasPatientMerged(patOld.PatNum)) { MsgBox.Show("FormPatientEdit", "Not allowed to change the status of a merged patient."); continue; } switch (pat.PatStatus) { case PatientStatus.Deceased: if (patOld.PatStatus != PatientStatus.Deceased) { List <Appointment> listFutureAppts = Appointments.GetFutureSchedApts(pat.PatNum); if (listFutureAppts.Count > 0) { string apptDates = string.Join("\r\n", listFutureAppts.Take(10).Select(x => x.AptDateTime.ToString())); if (listFutureAppts.Count > 10) { apptDates += "(...)"; } if (MessageBox.Show( Lan.g("FormPatientEdit", "This patient has scheduled appointments in the future") + ":\r\n" + apptDates + "\r\n" + Lan.g("FormPatientEdit", "Would you like to delete them and set the patient to Deceased?"), Lan.g("FormPatientEdit", "Delete future appointments?"), MessageBoxButtons.YesNo) == DialogResult.Yes) { foreach (Appointment appt in listFutureAppts) { Appointments.Delete(appt.AptNum, true); } } else { continue; } } } break; } //Re-activate or disable recalls depending on the the status that the patient is changing to. Patients.UpdateRecalls(pat, patOld, "ChangePatStatus automation"); if (Patients.Update(pat, patOld)) { SecurityLogs.MakeLogEntry(Permissions.PatientEdit, patNum, "Patient status changed from " + patOld.PatStatus.GetDescription() + " to " + listAutomations[i].PatStatus.GetDescription() + " through ChangePatStatus automation."); } automationHappened = true; continue; } } return(automationHappened); }
///<summary>Processes a PaySimple ACH payment via the PaySimple API.</summary> private PaySimple.ApiResponse ProcessPaymentACH() { PaySimple.ApiResponse retVal = null; string accountNumber = textCheckSaveNumber.Text; //if the user has chosen to store CC tokens and the stored CC has a token and the token is not expired, //then use it instead of the CC number and CC expiration. if (!checkOneTimePaymentACH.Checked && _creditCardCur != null && //if the user selected a saved CC !string.IsNullOrWhiteSpace(_creditCardCur.PaySimpleToken) && //there is a stored token for this card _creditCardCur.CCSource == CreditCardSource.PaySimpleACH) { accountNumber = _creditCardCur.PaySimpleToken; } else if (PIn.Bool(ProgramProperties.GetPropVal(_progCur.ProgramNum, PaySimple.PropertyDescs.PaySimplePreventSavingNewCC, _clinicNum))) { MsgBox.Show(this, "Cannot add a new ACH payment."); return(null); } try { if (_isAddingCard) { retVal = PaySimple.AddACHAccount(_patCur, textRoutingNumber.Text, textCheckSaveNumber.Text, textBankName.Text, radioCheckings.Checked, _clinicNum); } else { retVal = PaySimple.MakePaymentACH(_patCur, _creditCardCur, PIn.Decimal(textAmountACH.Text), textRoutingNumber.Text, textCheckSaveNumber.Text, textBankName.Text, radioCheckings.Checked, checkOneTimePaymentACH.Checked, _clinicNum); try { string result = WebServiceMainHQProxy.GetWebServiceMainHQInstance() .InsertPaySimpleACHId(PayloadHelper.CreatePayload( PayloadHelper.CreatePayloadContent(retVal.RefNumber.ToString(), "PaymentId"), eServiceCode.PaySimple)); PayloadHelper.CheckForError(result); } catch (Exception ex) { FriendlyException.Show("Unable to register for ACH Settled event", ex); } } } catch (PaySimpleException ex) { MessageBox.Show(ex.Message); if (ex.ErrorType == PaySimpleError.CustomerDoesNotExist && MsgBox.Show(this, MsgBoxButtons.OKCancel, "Delete the link to the customer id for this patient?")) { PatientLinks.DeletePatNumTos(ex.CustomerId, PatientLinkType.PaySimple); } return(null); } catch (ODException ex) { MessageBox.Show(ex.Message); //This should have already been Lans.g if applicable. return(null); } catch (Exception ex) { FriendlyException.Show(Lan.g(this, "Error:") + " " + ex.Message, ex); return(null); } if (!_isAddingCard) { retVal.BuildReceiptString(accountNumber, -1, -1, _patCur?.GetNameFL(), _clinicNum, wasSwiped: false, isACH: true); PrintReceipt(retVal.TransactionReceipt); } if (checkOneTimePaymentACH.Checked) //not storing the account token { return(retVal); } UpsertCreditCard(retVal, textCheckSaveNumber.Text.Right(4).PadLeft(textCheckSaveNumber.Text.Length, '*'), CreditCardSource.PaySimpleACH, DateTime.MinValue); return(retVal); }
///<summary>Processes a PaySimple payment via the PaySimple API.</summary> private PaySimple.ApiResponse ProcessPayment(int expYear, int expMonth) { PaySimple.ApiResponse retVal = null; string refNumber = ""; if (_trantype == PaySimple.TransType.VOID || _trantype == PaySimple.TransType.RETURN) { refNumber = textRefNumber.Text; } string magData = null; if (_parser != null) { magData = _parser.Track2; } string cardNumber = textCardNumber.Text; //if using a stored CC and there is an X-Charge token saved for the CC and the user enters the whole card number to get a PaySimple token //and the number entered doesn't have the same last 4 digits and exp date, then assume it's not the same card and clear out the X-Charge token. if (_creditCardCur != null && //using a saved CC !string.IsNullOrEmpty(_creditCardCur.XChargeToken) && //there is an X-Charge token saved (cardNumber.Right(4) != _creditCardCur.CCNumberMasked.Right(4) || //the card number entered doesn't have the same last 4 digits expYear != _creditCardCur.CCExpiration.Year || //the card exp date entered doesn't have the same year expMonth != _creditCardCur.CCExpiration.Month)) //the card exp date entered doesn't have the same month { if (MsgBox.Show(this, MsgBoxButtons.YesNo, "The card number or expiration date entered does not match the X-Charge card on file. Do you wish " + "to replace the X-Charge card with this one?")) { _creditCardCur.XChargeToken = ""; } else { Cursor = Cursors.Default; return(null); } } //if the user has chosen to store CC tokens and the stored CC has a token and the token is not expired, //then use it instead of the CC number and CC expiration. if (!checkOneTimePayment.Checked && _creditCardCur != null && //if the user selected a saved CC !string.IsNullOrWhiteSpace(_creditCardCur.PaySimpleToken)) //there is a stored token for this card { cardNumber = _creditCardCur.PaySimpleToken; expYear = _creditCardCur.CCExpiration.Year; expMonth = _creditCardCur.CCExpiration.Month; } else if (PIn.Bool(ProgramProperties.GetPropVal(_progCur.ProgramNum, PaySimple.PropertyDescs.PaySimplePreventSavingNewCC, _clinicNum))) { MsgBox.Show(this, "Cannot add a new credit card."); return(null); } try { switch (_trantype) { case PaySimple.TransType.SALE: //If _patCur is null or the PatNum is 0, we will make a one time payment for an UNKNOWN patient. //This is currently only intended for prepaid insurance cards. retVal = PaySimple.MakePayment((_patCur == null ? 0 : _patCur.PatNum), _creditCardCur, PIn.Decimal(textAmount.Text), textCardNumber.Text , new DateTime(expYear, expMonth, 1), checkOneTimePayment.Checked, textZipCode.Text, textSecurityCode.Text, _clinicNum, _carrierName); break; case PaySimple.TransType.AUTH: //Will retreive a new customer id from PaySimple if the patient doesn't exist already. long paySimpleCustomerId = PaySimple.GetCustomerIdForPat(_patCur.PatNum, _patCur.FName, _patCur.LName, _clinicNum); //I have no idea if an insurance can make an auth payment but incase they can I check for it. if (paySimpleCustomerId == 0) //Insurance payment, make a new customer id every time per Nathan on 04/26/2018 { if ((_patCur == null || _patCur.PatNum == 0)) { paySimpleCustomerId = PaySimple.AddCustomer("UNKNOWN", "UNKNOWN", "", _clinicNum); } else { throw new ODException(Lan.g(this, "Invalid PaySimple Customer Id found.")); } } try { retVal = PaySimple.AddCreditCard(paySimpleCustomerId, textCardNumber.Text, new DateTime(expYear, expMonth, 1), textZipCode.Text, _clinicNum); } catch (PaySimpleException ex) { PaySimple.HandlePaySimpleException(ex, paySimpleCustomerId); } break; case PaySimple.TransType.RETURN: if (string.IsNullOrWhiteSpace(textRefNumber.Text)) { throw new ODException(Lan.g(this, "Invalid PaySimple Payment ID.")); } if (!MsgBox.Show(this, MsgBoxButtons.OKCancel, "You are about to return a payment. This action is irreversible. Continue?")) { throw new ODException(Lan.g(this, "Payment return was cancelled by user.")); } retVal = PaySimple.ReversePayment(textRefNumber.Text, _clinicNum); break; case PaySimple.TransType.VOID: if (string.IsNullOrWhiteSpace(textRefNumber.Text)) { throw new ODException(Lan.g(this, "Invalid PaySimple Payment ID.")); } if (!MsgBox.Show(this, MsgBoxButtons.OKCancel, "You are about to void a payment. This action is irreversible. Continue?")) { throw new ODException(Lan.g(this, "Payment void was cancelled by user.")); } retVal = PaySimple.VoidPayment(textRefNumber.Text, _clinicNum); break; default: throw new Exception("Invalid transmission type: " + _trantype.ToString()); } } catch (PaySimpleException ex) { MessageBox.Show(ex.Message); if (ex.ErrorType == PaySimpleError.CustomerDoesNotExist && MsgBox.Show(this, MsgBoxButtons.OKCancel, "Delete the link to the customer id for this patient?")) { PatientLinks.DeletePatNumTos(ex.CustomerId, PatientLinkType.PaySimple); } return(null); } catch (ODException wex) { MessageBox.Show(wex.Message); //This should have already been Lans.g if applicable. return(null); } catch (Exception ex) { MessageBox.Show(Lan.g(this, "Error:") + " " + ex.Message); return(null); } if (_trantype.In(PaySimple.TransType.SALE, PaySimple.TransType.RETURN, PaySimple.TransType.VOID)) //Only print a receipt if transaction is an approved SALE, RETURN, or VOID //The isSwiped boolean could be incorrectly set if the user swipes a card and then changes the data that was entered to a different card. { retVal.BuildReceiptString(cardNumber, expMonth, expYear, textNameOnCard.Text, _clinicNum, _parser != null); PrintReceipt(retVal.TransactionReceipt); } if (checkOneTimePayment.Checked) //not storing the card token { return(retVal); } UpsertCreditCard(retVal, textCardNumber.Text.Right(4).PadLeft(textCardNumber.Text.Length, 'X'), CreditCardSource.PaySimple, new DateTime(expYear, expMonth, DateTime.DaysInMonth(expYear, expMonth))); return(retVal); }
private void FormSubscriberSelect_Load(object sender, System.EventArgs e) { _listMergeLinks = PatientLinks.GetLinks(FamCur.ListPats.Select(x => x.PatNum).ToList(), PatientLinkType.Merge); FillList(); }