///<summary>Throws exceptions if the PaySimple program or program properties are not valid. ///If this method doesn't throw an exception, everything is assumed to be valid.</summary> private static void ValidateProgram(long clinicNum = -1) { if (clinicNum == -1) { clinicNum = Clinics.ClinicNum; } Program progPaySimple = Programs.GetCur(ProgramName.PaySimple); if (progPaySimple == null) { throw new ODException(Lans.g("PaySimple", "PaySimple program does not exist in the database. Please call support.")); } if (!progPaySimple.Enabled) { throw new ODException(Lans.g("PaySimple", "PaySimple is not enabled.")); } string apiUserName = ProgramProperties.GetPropValForClinicOrDefault(progPaySimple.ProgramNum, PropertyDescs.PaySimpleApiUserName, clinicNum); string apiKey = ProgramProperties.GetPropValForClinicOrDefault(progPaySimple.ProgramNum, PropertyDescs.PaySimpleApiKey, clinicNum); string payType = ProgramProperties.GetPropValForClinicOrDefault(progPaySimple.ProgramNum, PropertyDescs.PaySimplePayType, clinicNum); if (string.IsNullOrWhiteSpace(apiUserName) || string.IsNullOrWhiteSpace(apiKey) || string.IsNullOrWhiteSpace(payType)) { throw new ODException(Lans.g("PaySimple", "PaySimple Username, Key, or PayType is empty.")); } }
/// <summary>Inserts a TsiTransLog for the adjustment if necessary.</summary> public static void CheckAndInsertLogsIfAdjTypeExcluded(Adjustment adj, bool isFromTsi = false) { Program progCur = Programs.GetCur(ProgramName.Transworld); if (progCur == null || !progCur.Enabled) { return; } Patient guar = Patients.GetGuarForPat(adj.PatNum); if (guar == null || !IsTransworldEnabled(guar.ClinicNum) || !Patients.IsGuarCollections(guar.PatNum)) { return; } string msgText = "This was not a message sent to Transworld. This adjustment was entered due to a payment received from Transworld."; TsiTransType typeCur = TsiTransType.None; if (!isFromTsi) //if not an adj due to a payment from TSI, see if it is an excluded adj type { Dictionary <long, List <ProgramProperty> > dictClinicProps = ProgramProperties .GetWhere(x => x.ProgramNum == progCur.ProgramNum && x.PropertyDesc.In(ExcludeAdjustTypes) && x.ClinicNum.In(0, guar.ClinicNum)) .GroupBy(x => x.ClinicNum) .ToDictionary(x => x.Key, x => x.ToList()); //use guar's clinic if clinics are enabled and props for that clinic exist, otherwise use ClinicNum 0 long clinicNum = (PrefC.HasClinicsEnabled && dictClinicProps.ContainsKey(guar.ClinicNum))?guar.ClinicNum:0; if (!dictClinicProps.TryGetValue(clinicNum, out List <ProgramProperty> listPropsCur) || //should always be props for ClinicNum 0 listPropsCur.All(x => PIn.Long(x.PropertyValue, false) != adj.AdjType)) { return; //if this adjustment is not an excluded type, return } msgText = "Adjustment type is set to excluded type from transworld program properties."; typeCur = TsiTransType.Excluded; } InsertTsiLogsForAdjustment(guar.PatNum, adj, msgText, typeCur); }
public static bool IsTransworldEnabled(long clinicNum) { //No need to check RemotingRole;no call to db. Program progCur = Programs.GetCur(ProgramName.Transworld); if (progCur == null || !progCur.Enabled) { return(false); } Dictionary <long, List <ProgramProperty> > dictAllProps = ProgramProperties.GetForProgram(progCur.ProgramNum) .GroupBy(x => x.ClinicNum) .ToDictionary(x => x.Key, x => x.ToList()); if (dictAllProps.Count == 0) { return(false); } List <long> listDisabledClinicNums = new List <long>(); if (!PrefC.HasClinicsEnabled) { return(TsiTransLogs.ValidateClinicSftpDetails(dictAllProps[0], false)); } List <Clinic> listAllClinics = Clinics.GetDeepCopy(); listDisabledClinicNums.AddRange(dictAllProps.Where(x => !TsiTransLogs.ValidateClinicSftpDetails(x.Value, false)).Select(x => x.Key)); listDisabledClinicNums.AddRange(listAllClinics .FindAll(x => x.IsHidden || (listDisabledClinicNums.Contains(0) && !dictAllProps.ContainsKey(x.ClinicNum)))//if no props for HQ, skip other clinics without props .Select(x => x.ClinicNum) ); return(!listDisabledClinicNums.Contains(clinicNum)); }
public static PayConnectService.signatureResponse ProcessSignature(PayConnectService.signatureRequest sigRequest, long clinicNum, Action <string> showError) { try { Program prog = Programs.GetCur(ProgramName.PayConnect); PayConnectService.Credentials cred = GetCredentials(prog, clinicNum); PayConnectService.MerchantService ms = new PayConnectService.MerchantService(); #if DEBUG ms.Url = "https://prelive.dentalxchange.com/merchant/MerchantService?wsdl"; #else ms.Url = "https://webservices.dentalxchange.com/merchant/MerchantService?wsdl"; #endif PayConnectService.signatureResponse response = ms.processSignature(cred, sigRequest); ms.Dispose(); if (response.Status.code != 0) //Error { showError(Lans.g("PayConnect", "Signature capture failed") + ". \r\n" + Lans.g("PayConnect", "Error message from") + " Pay Connect: \"" + response.Status.description + "\""); } return(response); } catch (Exception ex) { showError(Lans.g("PayConnect", "Signature capture failed") + ". \r\n" + Lans.g("PayConnect", "Error message from") + " Open Dental: \"" + ex.Message + "\""); } return(null); }
///<summary>Insert Payment and PaySplit. Returns newly inserted Payment.PayNum. Throws exceptions if PayConnect Program Properties are invalid.</summary> public static long InsertFromPayConnect(long patNum, long provNum, long clinicNum, double amount, string payNote, string receipt, CreditCardSource ccSource) { //No need to check RemotingRole;no call to db. long ret = Payments.Insert(new Payment() { ClinicNum = clinicNum, IsRecurringCC = false, IsSplit = false, PatNum = patNum, PayAmt = amount, PayDate = DateTime.Now, PaymentSource = ccSource, PayType = PIn.Long(ProgramProperties.GetPropVal(Programs.GetCur(ProgramName.PayConnect).ProgramNum, "PaymentType", clinicNum)), ProcessStatus = ProcessStat.OnlinePending, Receipt = receipt, PayNote = payNote, }); PaySplits.Insert(new PaySplit() { ClinicNum = clinicNum, DatePay = DateTime.Now, PatNum = patNum, PayNum = ret, ProvNum = provNum, SplitAmt = amount, }); SecurityLogs.MakeLogEntry(Permissions.PaymentCreate, patNum, Lans.g("Payments.InsertFromPayConnect", "PayConnect payment by") + " " + OpenDentBusiness.Patients.GetLim(patNum).GetNameLF() + ", " + amount.ToString("c"), LogSources.PatientPortal); return(ret); }
///<summary>Returns true if either the XCharge program or PayConnect program is enabled and at least one clinic has online payments enabled. ///progEnabledForPayments will return the program that is enabled for online payments if it is allowed. Both programs cannot be enabled at the same time</summary> public static bool HasOnlinePaymentEnabled(out ProgramName progEnabledForPayments) { progEnabledForPayments = ProgramName.None; Program progXCharge = Programs.GetCur(ProgramName.Xcharge); Program progPayConnect = Programs.GetCur(ProgramName.PayConnect); if (!progXCharge.Enabled && !progPayConnect.Enabled) { return(false); } if (progXCharge.Enabled) { List <ProgramProperty> listXChargeProps = ProgramProperties.GetForProgram(progXCharge.ProgramNum); if (listXChargeProps.Any(x => x.PropertyDesc == "IsOnlinePaymentsEnabled" && x.PropertyValue == "1")) { progEnabledForPayments = ProgramName.Xcharge; return(true); } } if (progPayConnect.Enabled) { List <ProgramProperty> listPayConnectProps = ProgramProperties.GetForProgram(progPayConnect.ProgramNum); if (listPayConnectProps.Any(x => x.PropertyDesc == PayConnect.ProgramProperties.PatientPortalPaymentsEnabled && x.PropertyValue == "1")) { progEnabledForPayments = ProgramName.PayConnect; return(true); } } return(false); }
///<summary>If isRemovable is false, then the file referenced in the program property will be cleared. ///If isRemovable is true, then the file referenced in the program property will be deleted.</summary> private static void ScrubFileForProperty(ProgramName programName, string strFileProperty, string strFilePropertySuffix, bool isRemovable) { Program program = Programs.GetCur(programName); if (!program.Enabled) { return; } string strFileToScrub = CodeBase.ODFileUtils.CombinePaths(ProgramProperties.GetPropVal(program.ProgramNum, strFileProperty), strFilePropertySuffix); if (!File.Exists(strFileToScrub)) { return; } try { File.WriteAllText(strFileToScrub, ""); //Always clear the file contents, in case deleting fails below. } catch { //Another instance of OD might be closing at the same time, in which case the delete will fail. Could also be a permission issue or a concurrency issue. Ignore. } if (!isRemovable) { return; } try { File.Delete(strFileToScrub); } catch { //Another instance of OD might be closing at the same time, in which case the delete will fail. Could also be a permission issue or a concurrency issue. Ignore. } }
///<summary>Safe to call on any program. Only returns true if the program is not enabled ///AND the program has a property of "Disable Advertising" = 1 OR "Disable Advertising HQ" = 1. ///This means that either the office has disabled the ad or HQ has disabled the ad.</summary> public static bool IsAdvertisingDisabled(ProgramName progName) { Program program = Programs.GetCur(progName); if (program == null || program.Enabled) { return(false); //do not block advertising } return(GetForProgram(program.ProgramNum).Any(x => (x.PropertyDesc == "Disable Advertising" && x.PropertyValue == "1") || //Office has decided to hide the advertising (x.PropertyDesc == "Disable Advertising HQ" && x.PropertyValue == "1")));//HQ has decided to hide the advertising }
///<summary>Returns true if the XCharge program is enabled and at least one clinic has online payments enabled.</summary> public static bool HasOnlinePaymentEnabled() { Program prog = Programs.GetCur(ProgramName.Xcharge); if (!prog.Enabled) { return(false); } List <ProgramProperty> listXChargeProps = ProgramProperties.GetForProgram(prog.ProgramNum); return(listXChargeProps.Any(x => x.PropertyDesc == "IsOnlinePaymentsEnabled" && x.PropertyValue == "1")); }
public static ErxOption GetErxOption() { Program progCur = Programs.GetCur(ProgramName.eRx); if (progCur == null) { throw new ODException(Lans.g("eRx", "The eRx bridge is missing from the database.")); } List <ProgramProperty> listProgramProperties = ProgramProperties.GetForProgram(progCur.ProgramNum); ProgramProperty propCur = listProgramProperties.FirstOrDefault(x => x.PropertyDesc == PropertyDescs.ErxOption); if (propCur == null) { throw new ODException(Lans.g("eRx", "The eRx Option program property is missing from the database.")); } return(PIn.Enum <ErxOption>(propCur.PropertyValue)); }
///<summary>Returns the Authorization header for the api call, using the passed in clinicNum if provided, otherwise uses the currently selected clinic.</summary> private static string GetAuthHeader(long clinicNum = -1) { if (clinicNum == -1) { clinicNum = Clinics.ClinicNum; } string apiUserName = ProgramProperties.GetPropValForClinicOrDefault(Programs.GetCur(ProgramName.PaySimple).ProgramNum , PropertyDescs.PaySimpleApiUserName , clinicNum); string apiKey = ProgramProperties.GetPropValForClinicOrDefault(Programs.GetCur(ProgramName.PaySimple).ProgramNum , PropertyDescs.PaySimpleApiKey , clinicNum); #if DEBUG //string apiUserName="******"; //string apiKey="QkQRj8i0QDPOtUBhbTWx7irBrqospeY8RDC4HxW2LD3IDIfo1bcumTMomp7IJbYONjIna84QPwMwfFLMTtZcMJ2Bm4meQIfojgsDrZr5HxAnQkylHJgF7t2XUDoVy6I0"; #endif return(PaySimpleApi.GetAuthHeader(apiUserName, apiKey)); }
///<summary>Shows a message box on error.</summary> public static PayConnectService.transResponse ProcessCreditCard(PayConnectService.creditCardRequest request, long clinicNum, Action <string> showError) { try { Program prog = Programs.GetCur(ProgramName.PayConnect); PayConnectService.Credentials cred = GetCredentials(prog, clinicNum); PayConnectService.MerchantService ms = new PayConnectService.MerchantService(); ms.Url = Introspection.GetOverride(Introspection.IntrospectionEntity.PayConnectRestURL, "https://webservices.dentalxchange.com/merchant/MerchantService?wsdl"); #if DEBUG ms.Url = "https://prelive.dentalxchange.com/merchant/MerchantService?wsdl"; #endif PayConnectService.transResponse response = ms.processCreditCard(cred, request); ms.Dispose(); if (response.Status.code != 0 && response.Status.description.ToLower().Contains("duplicate")) { showError(Lans.g("PayConnect", "Payment failed") + ". \r\n" + Lans.g("PayConnect", "Error message from") + " Pay Connect: \"" + response.Status.description + "\"\r\n" + Lans.g("PayConnect", "Try using the Force Duplicate checkbox if a duplicate is intended.")); } if (response.Status.code != 0 && response.Status.description.ToLower().Contains("invalid user")) { showError(Lans.g("PayConnect", "Payment failed") + ".\r\n" + Lans.g("PayConnect", "PayConnect username and password combination invalid.") + "\r\n" + Lans.g("PayConnect", "Verify account settings by going to") + "\r\n" + Lans.g("PayConnect", "Setup | Program Links | PayConnect. The PayConnect username and password are probably the same as the DentalXChange login ID and password.")); } else if (response.Status.code != 0) //Error { showError(Lans.g("PayConnect", "Payment failed") + ". \r\n" + Lans.g("PayConnect", "Error message from") + " Pay Connect: \"" + response.Status.description + "\""); } return(response); } catch (Exception ex) { showError(Lans.g("PayConnect", "Payment failed") + ". \r\n" + Lans.g("PayConnect", "Error message") + ": \"" + ex.Message + "\""); } return(null); }
///<summary>Sends an SFTP message to TSI to suspend the account for the guarantor passed in. Returns empty string if successful. ///Returns a translated error message that should be displayed to the user if anything goes wrong.</summary> public static string SuspendGuar(Patient guar) { PatAging patAging = Patients.GetAgingListFromGuarNums(new List <long>() { guar.PatNum }).FirstOrDefault(); if (patAging == null) //this would only happen if the patient was not in the db??, just in case { return(Lans.g("TsiTransLogs", "An error occurred when trying to send a suspend message to TSI.")); } long clinicNum = (PrefC.HasClinicsEnabled?guar.ClinicNum:0); Program prog = Programs.GetCur(ProgramName.Transworld); if (prog == null) //shouldn't be possible, the program link should always exist, just in case { return(Lans.g("TsiTransLogs", "The Transworld program link does not exist. Contact support.")); } Dictionary <long, List <ProgramProperty> > dictAllProps = ProgramProperties.GetForProgram(prog.ProgramNum) .GroupBy(x => x.ClinicNum) .ToDictionary(x => x.Key, x => x.ToList()); if (dictAllProps.Count == 0) //shouldn't be possible, there should always be a set of props for ClinicNum 0 even if disabled, just in case { return(Lans.g("TsiTransLogs", "The Transworld program link is not setup properly.")); } if (PrefC.HasClinicsEnabled && !dictAllProps.ContainsKey(clinicNum) && dictAllProps.ContainsKey(0)) { clinicNum = 0; } string clinicDesc = clinicNum == 0?"Headquarters":Clinics.GetDesc(clinicNum); if (!dictAllProps.ContainsKey(clinicNum) || !ValidateClinicSftpDetails(dictAllProps[clinicNum], true)) //the props should be valid, but this will test the connection using the props { return(Lans.g("TsiTransLogs", "The Transworld program link is not enabled") + " " + (PrefC.HasClinicsEnabled?(Lans.g("TsiTransLogs", "for the guarantor's clinic") + ", " + clinicDesc + ", "):"") + Lans.g("TsiTransLogs", "or is not setup properly.")); } List <ProgramProperty> listProps = dictAllProps[clinicNum]; long newBillType = PrefC.GetLong(PrefName.TransworldPaidInFullBillingType); if (newBillType == 0 || Defs.GetDef(DefCat.BillingTypes, newBillType) == null) { return(Lans.g("TsiTransLogs", "The default paid in full billing type is not set. An automated suspend message cannot be sent until the " + "default paid in full billing type is set in the Transworld program link") + (PrefC.HasClinicsEnabled?(" " + Lans.g("TsiTransLogs", "for the guarantor's clinic") + ", " + clinicDesc):"") + "."); } string clientId = ""; if (patAging.ListTsiLogs.Count > 0) { clientId = patAging.ListTsiLogs[0].ClientId; } if (string.IsNullOrEmpty(clientId)) { clientId = listProps.Find(x => x.PropertyDesc == "ClientIdAccelerator")?.PropertyValue; } if (string.IsNullOrEmpty(clientId)) { clientId = listProps.Find(x => x.PropertyDesc == "ClientIdCollection")?.PropertyValue; } if (string.IsNullOrEmpty(clientId)) { return(Lans.g("TsiTransLogs", "There is no client ID in the Transworld program link") + (PrefC.HasClinicsEnabled?(" " + Lans.g("TsiTransLogs", "for the guarantor's clinic") + ", " + clinicDesc):"") + "."); } string sftpAddress = listProps.Find(x => x.PropertyDesc == "SftpServerAddress")?.PropertyValue ?? ""; int sftpPort; if (!int.TryParse(listProps.Find(x => x.PropertyDesc == "SftpServerPort")?.PropertyValue ?? "", out sftpPort)) { sftpPort = 22; //default to port 22 } string userName = listProps.Find(x => x.PropertyDesc == "SftpUsername")?.PropertyValue ?? ""; string userPassword = listProps.Find(x => x.PropertyDesc == "SftpPassword")?.PropertyValue ?? ""; if (new[] { sftpAddress, userName, userPassword }.Any(x => string.IsNullOrEmpty(x))) { return(Lans.g("TsiTransLogs", "The SFTP address, username, or password for the Transworld program link") + " " + (PrefC.HasClinicsEnabled?(Lans.g("TsiTransLogs", "for the guarantor's clinic") + ", " + clinicDesc + ", "):"") + Lans.g("TsiTransLogs", "is blank.")); } string msg = TsiMsgConstructor.GenerateUpdate(patAging.PatNum, clientId, TsiTransType.SS, 0.00, patAging.AmountDue); try { byte[] fileContents = Encoding.ASCII.GetBytes(TsiMsgConstructor.GetUpdateFileHeader() + "\r\n" + msg); TaskStateUpload state = new Sftp.Upload(sftpAddress, userName, userPassword, sftpPort) { Folder = "/xfer/incoming", FileName = "TsiUpdates_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".txt", FileContent = fileContents, HasExceptions = true }; state.Execute(false); } catch (Exception ex) { return(Lans.g("TsiTransLogs", "There was an error sending the update message to Transworld") + (PrefC.HasClinicsEnabled?(" " + Lans.g("TsiTransLogs", "using the program properties for the guarantor's clinic") + ", " + clinicDesc):"") + ".\r\n" + ex.Message); } //Upload was successful TsiTransLog log = new TsiTransLog() { PatNum = patAging.PatNum, UserNum = Security.CurUser.UserNum, TransType = TsiTransType.SS, //TransDateTime=DateTime.Now,//set on insert, not editable by user //DemandType=TsiDemandType.Accelerator,//only valid for placement msgs //ServiceCode=TsiServiceCode.Diplomatic,//only valid for placement msgs ClientId = clientId, TransAmt = 0.00, AccountBalance = patAging.AmountDue, FKeyType = TsiFKeyType.None, //only used for account trans updates FKey = 0, //only used for account trans updates RawMsgText = msg, ClinicNum = clinicNum //,TransJson=""//only valid for placement msgs }; TsiTransLogs.Insert(log); //update family billing type to the paid in full billing type pref Patients.UpdateFamilyBillingType(newBillType, patAging.PatNum); return(""); }
///<summary>Safe to call on any program. Only returns true if the program is not enabled ///AND the program has a property of "Disable Advertising" = 1 OR "Disable Advertising HQ" = 1. ///This means that either the office has disabled the ad or HQ has disabled the ad.</summary> public static bool IsAdvertisingDisabled(ProgramName progName) { Program program = Programs.GetCur(progName); return(IsAdvertisingDisabled(program)); }
///<summary>Called by local practice db to query HQ for EService setup info. Must remain very lite and versionless. Will be used by signup portal. ///If HasClinics==true then any SignupOut.EServices entries where ClinicNum==0 are invalid and should be ignored. ///If HasClinics==false then SignupOut.EServices should only pay attention items where ClinicNum==0. ///This list is kept completely unfiltered by ClinicNum for forward compatibility reasons. ///The ClinicNum 0 items are always used by the Signup portal to determine default signup preferences. ///However, these items are only used for validation and billing in the case where HasClinics==true.</summary> public static EServiceSetup.SignupOut GetEServiceSetupFull(SignupPortalPermission permission, bool isSwitchClinicPref = false) { //Clinics will be stored in this order at HQ to allow signup portal to display them in proper order. List <Clinic> clinics = Clinics.GetDeepCopy().OrderBy(x => x.ItemOrder).ToList(); if (PrefC.GetBool(PrefName.ClinicListIsAlphabetical)) { clinics = clinics.OrderBy(x => x.Abbr).ToList(); } #if DEBUG bool isMockChanged = false; if (WebServiceMainHQProxy.MockWebServiceMainHQ == null) { WebServiceMainHQProxy.MockWebServiceMainHQ = new WebServiceMainHQMockDemo(); isMockChanged = true; } #endif EServiceSetup.SignupOut signupOut = ReadXml <EServiceSetup.SignupOut> ( WebSerializer.DeserializePrimitiveOrThrow <string> ( GetWebServiceMainHQInstance().EServiceSetup ( CreateWebServiceHQPayload ( WriteXml(new EServiceSetup.SignupIn() { MethodNameInt = (int)EServiceSetup.SetupMethod.GetSignupOutFull, HasClinics = PrefC.HasClinicsEnabled, //ClinicNum is not currently used as input. ClinicNum = 0, ProgramVersionStr = PrefC.GetString(PrefName.ProgramVersion), SignupPortalPermissionInt = (int)permission, Clinics = clinics .Select(x => new EServiceSetup.SignupIn.ClinicLiteIn() { ClinicNum = x.ClinicNum, ClinicTitle = x.Abbr, IsHidden = x.IsHidden, }).ToList(), IsSwitchClinicPref = isSwitchClinicPref, }), eServiceCode.Undefined ) ) ) ); #if DEBUG if (isMockChanged) { WebServiceMainHQProxy.MockWebServiceMainHQ = null; } #endif //We just got the latest sync info from HQ so update the local db to reflect what HQ says is true. #region Reconcile Phones List <SmsPhone> listPhonesHQ = signupOut.Phones.Select(x => new SmsPhone() { ClinicNum = x.ClinicNum, CountryCode = x.CountryCode, DateTimeActive = x.DateTimeActive, DateTimeInactive = x.DateTimeInactive, InactiveCode = x.InactiveCode, PhoneNumber = x.PhoneNumber, }).ToList(); SmsPhones.UpdateOrInsertFromList(listPhonesHQ); #endregion #region Reconcile practice and clinics List <EServiceSetup.SignupOut.SignupOutSms> smsSignups = GetSignups <EServiceSetup.SignupOut.SignupOutSms>(signupOut, eServiceCode.IntegratedTexting); bool isCacheInvalid = false; bool isSmsEnabled = false; if (PrefC.HasClinicsEnabled) //Clinics are ON so loop through all clinics and reconcile with HQ. { List <Clinic> listClinicsAll = Clinics.GetDeepCopy(); foreach (Clinic clinicDb in listClinicsAll) { WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms clinicSignup = smsSignups.FirstOrDefault(x => x.ClinicNum == clinicDb.ClinicNum) ?? new WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms() { //Not found so turn it off. SmsContractDate = DateTime.MinValue, MonthlySmsLimit = 0, IsEnabled = false, }; Clinic clinicNew = clinicDb.Copy(); clinicNew.SmsContractDate = clinicSignup.SmsContractDate; clinicNew.SmsMonthlyLimit = clinicSignup.MonthlySmsLimit; isCacheInvalid |= Clinics.Update(clinicNew, clinicDb); isSmsEnabled |= clinicSignup.IsEnabled; } } else //Clinics are off so ClinicNum 0 is the practice clinic. { WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms practiceSignup = smsSignups.FirstOrDefault(x => x.ClinicNum == 0) ?? new WebServiceMainHQProxy.EServiceSetup.SignupOut.SignupOutSms() { //Not found so turn it off. SmsContractDate = DateTime.MinValue, MonthlySmsLimit = 0, IsEnabled = false, }; isCacheInvalid |= Prefs.UpdateDateT(PrefName.SmsContractDate, practiceSignup.SmsContractDate) | Prefs.UpdateLong(PrefName.TextingDefaultClinicNum, 0) | Prefs.UpdateDouble(PrefName.SmsMonthlyLimit, practiceSignup.MonthlySmsLimit); isSmsEnabled |= practiceSignup.IsEnabled; } #endregion #region Reconcile CallFire //Turn off CallFire if SMS has been activated. //This only happens the first time SMS is turned on and CallFire is still activated. if (isSmsEnabled && Programs.IsEnabled(ProgramName.CallFire)) { Program callfire = Programs.GetCur(ProgramName.CallFire); if (callfire != null) { callfire.Enabled = false; Programs.Update(callfire); Signalods.Insert(new Signalod() { IType = InvalidType.Providers }); signupOut.Prompts.Add("Call Fire has been disabled. Cancel Integrated Texting and access program properties to retain Call Fire."); } } #endregion #region eConfirmations if (Prefs.UpdateBool(PrefName.ApptConfirmAutoSignedUp, IsEServiceActive(signupOut, eServiceCode.ConfirmationRequest))) { //HQ does not match the local pref. Make it match with HQ. isCacheInvalid = true; SecurityLogs.MakeLogEntry(Permissions.Setup, 0, "Automated appointment eConfirmations automatically changed by HQ. Local pref set to " + IsEServiceActive(signupOut, eServiceCode.ConfirmationRequest).ToString() + "."); } #endregion if (isCacheInvalid) //Something changed in the db. Alert other workstations and change this workstation immediately. { Signalods.Insert(new Signalod() { IType = InvalidType.Prefs }); Prefs.RefreshCache(); Signalods.Insert(new Signalod() { IType = InvalidType.Providers }); Providers.RefreshCache(); Clinics.RefreshCache(); } return(signupOut); }
///<summary>For each enabled bridge, if the bridge uses a file to transmit patient data to the other software, then we need to remove the files or clear the files when OD is exiting. ///Required for EHR 2014 module d.7 (as stated by proctor).</summary> public static void ScrubExportedPatientData() { //List all program links here. If there is nothing to do for that link, then create a comment stating so. string path = ""; //Apixia: ScrubFileForProperty(ProgramName.Apixia, "System path to Apixia Digital Imaging ini file", "", true); //C:\Program Files\Digirex\Switch.ini //Apteryx: Has no file paths containing outgoing patient data from Open Dental. //BioPAK: Has no file paths containing outgoing patient data from Open Dental. //CallFire: Has no file paths containing outgoing patient data from Open Dental. //Camsight: Has no file paths containing outgoing patient data from Open Dental. //CaptureLink: Has no file paths containing outgoing patient data from Open Dental. //Cerec: Has no file paths containing outgoing patient data from Open Dental. //CliniView: Has no file paths containing outgoing patient data from Open Dental. //ClioSoft: Has no file paths containing outgoing patient data from Open Dental. //DBSWin: ScrubFileForProperty(ProgramName.DBSWin, "Text file path", "", true); //C:\patdata.txt //DentalEye: Has no file paths containing outgoing patient data from Open Dental. //DentalStudio: Has no file paths containing outgoing patient data from Open Dental. //DentForms: Has no file paths containing outgoing patient data from Open Dental. //DentX: Has no file paths containing outgoing patient data from Open Dental. //Dexis: ScrubFileForProperty(ProgramName.Dexis, "InfoFile path", "", true); //InfoFile.txt //Digora: Has no file paths containing outgoing patient data from Open Dental. //Divvy: Has no file paths containing outgoing patient data from Open Dental. //Dolphin: ScrubFileForProperty(ProgramName.Dolphin, "Filename", "", true); //C:\Dolphin\Import\Import.txt //DrCeph: Has no file paths containing outgoing patient data from Open Dental. //Dxis: Has no file paths containing outgoing patient data from Open Dental. //EasyNotesPro: Has no file paths containing outgoing patient data from Open Dental. //eClinicalWorks: HL7 files are created, but eCW is supposed to consume and delete them. //EvaSoft: Has no file paths containing outgoing patient data from Open Dental. //EwooEZDent: Program program = Programs.GetCur(ProgramName.EwooEZDent); if (program.Enabled) { path = Programs.GetProgramPath(program); if (File.Exists(path)) { string dir = Path.GetDirectoryName(path); string linkage = CodeBase.ODFileUtils.CombinePaths(dir, "linkage.xml"); if (File.Exists(linkage)) { try { File.Delete(linkage); } catch { //Another instance of OD might be closing at the same time, in which case the delete will fail. Could also be a permission issue or a concurrency issue. Ignore. } } } } //FloridaProbe: Has no file paths containing outgoing patient data from Open Dental. //Guru: Has no file paths containing outgoing patient data from Open Dental. //HouseCalls: ScrubFileForProperty(ProgramName.HouseCalls, "Export Path", "Appt.txt", true); //C:\HouseCalls\Appt.txt //IAP: Has no file paths containing outgoing patient data from Open Dental. //iCat: ScrubFileForProperty(ProgramName.iCat, "XML output file path", "", true); //C:\iCat\Out\pm.xml //ImageFX: Has no file paths containing outgoing patient data from Open Dental. //Lightyear: Has no file paths containing outgoing patient data from Open Dental. //MediaDent: ScrubFileForProperty(ProgramName.MediaDent, "Text file path", "", true); //C:\MediadentInfo.txt //MiPACS: Has no file paths containing outgoing patient data from Open Dental. //Mountainside: Has no file paths containing outgoing patient data from Open Dental. //NewCrop: Has no file paths containing outgoing patient data from Open Dental. //Orion: Has no file paths containing outgoing patient data from Open Dental. //OrthoPlex: Has no file paths containing outgoing patient data from Open Dental. //Owandy: Has no file paths containing outgoing patient data from Open Dental. //PayConnect: Has no file paths containing outgoing patient data from Open Dental. //Patterson: ScrubFileForProperty(ProgramName.Patterson, "System path to Patterson Imaging ini", "", true); //C:\Program Files\PDI\Shared files\Imaging.ini //PerioPal: Has no file paths containing outgoing patient data from Open Dental. //Planmeca: Has no file paths containing outgoing patient data from Open Dental. //PracticeWebReports: Has no file paths containing outgoing patient data from Open Dental. //Progeny: Has no file paths containing outgoing patient data from Open Dental. //PT: Per our website "The files involved get deleted immediately after they are consumed." //PTupdate: Per our website "The files involved get deleted immediately after they are consumed." //RayMage: Has no file paths containing outgoing patient data from Open Dental. //Schick: Has no file paths containing outgoing patient data from Open Dental. //Sirona: program = Programs.GetCur(ProgramName.Sirona); if (program.Enabled) { path = Programs.GetProgramPath(program); //read file C:\sidexis\sifiledb.ini string iniFile = Path.GetDirectoryName(path) + "\\sifiledb.ini"; if (File.Exists(iniFile)) { string sendBox = ReadValueFromIni("FromStation0", "File", iniFile); if (File.Exists(sendBox)) { File.WriteAllText(sendBox, ""); //Clear the sendbox instead of deleting. } } } //Sopro: Has no file paths containing outgoing patient data from Open Dental. //TigerView: ScrubFileForProperty(ProgramName.TigerView, "Tiger1.ini path", "", false); //C:\Program Files\PDI\Shared files\Imaging.ini. TigerView complains if the file is not present. //Trojan: Has no file paths containing outgoing patient data from Open Dental. //Trophy: Has no file paths containing outgoing patient data from Open Dental. //TrophyEnhanced: Has no file paths containing outgoing patient data from Open Dental. //Tscan: Has no file paths containing outgoing patient data from Open Dental. //UAppoint: Has no file paths containing outgoing patient data from Open Dental. //Vipersoft: Has no file paths containing outgoing patient data from Open Dental. //VixWin: Has no file paths containing outgoing patient data from Open Dental. //VixWinBase41: Has no file paths containing outgoing patient data from Open Dental. //VixWinOld: Has no file paths containing outgoing patient data from Open Dental. //Xcharge: Has no file paths containing outgoing patient data from Open Dental. ScrubFileForProperty(ProgramName.XDR, "InfoFile path", "", true); //C:\XDRClient\Bin\infofile.txt }