Ejemplo n.º 1
0
        ///<summary></summary>
        public static long[] GetDepositAccounts()
        {
            //No need to check RemotingRole; no call to db.
            string depStr = PrefC.GetString(PrefName.AccountingDepositAccounts);

            string[]  depStrArray = depStr.Split(new char[] { ',' });
            ArrayList depAL       = new ArrayList();

            for (int i = 0; i < depStrArray.Length; i++)
            {
                if (depStrArray[i] == "")
                {
                    continue;
                }
                depAL.Add(PIn.Long(depStrArray[i]));
            }
            long[] retVal = new long[depAL.Count];
            depAL.CopyTo(retVal);
            return(retVal);
        }
Ejemplo n.º 2
0
        ///<summary>Throws exceptions.</summary>
        public static void BuildWebSchedNewPatApptURLs(List <long> listClinicNums, Action <XmlNode> aNodeParsed)
        {
            //Make a web call to HQ to get the URLs for all the clinics.
            string response = GetWebServiceMainHQInstance()
                              .BuildWebSchedNewPatApptURLs(PrefC.GetString(PrefName.RegistrationKey), String.Join("|", listClinicNums));
            //Parse Response
            XmlDocument doc          = new XmlDocument();
            XmlNode     nodeError    = null;
            XmlNode     nodeResponse = null;
            XmlNodeList nodeURLs     = null;

            //Invalid web service response passed in.  Node will be null and will throw correctly.
            ODException.SwallowAnyException(() => {
                doc.LoadXml(response);
                nodeError    = doc.SelectSingleNode("//Error");
                nodeResponse = doc.SelectSingleNode("//GetWebSchedURLsResponse");
            });
            #region Error Handling
            if (nodeError != null || nodeResponse == null)
            {
                string error = Lans.g("WebSched", "There was an error with the web request.  Please try again or give us a call.");
                //Either something went wrong or someone tried to get cute and use our Web Sched service when they weren't supposed to.
                if (nodeError != null)
                {
                    error += "\r\n" + Lans.g("WebSched", "Error Details") + ":\r\n" + nodeError.InnerText;
                }
                throw new Exception(error);
            }
            nodeURLs = doc.GetElementsByTagName("URL");
            if (nodeURLs == null)
            {
                throw new Exception("Invalid response from server recieved.");
            }
            #endregion
            //At this point we know we got a valid response from our web service.
            //Loop through all the URL nodes that were returned.
            foreach (XmlNode node in nodeURLs)
            {
                aNodeParsed(node);
            }
        }
Ejemplo n.º 3
0
        ///<summary>Creates a snapshot for the claimprocs passed in.  Used for reporting purposes.
        ///If called from Open Dental Service, ignore passed in claimprocs and make snapshots for the entire day of completed procedures in a different method.
        ///When passing in claimprocs, the implementor will need to ensure that only primary claimprocs are being saved.
        ///Only creates snapshots if the feature is enabled and if the claimproc is of certain statuses.</summary>
        public static void CreateClaimSnapshot(List <ClaimProc> listClaimProcs, ClaimSnapshotTrigger triggerType, string claimType)
        {
            //No need to check RemotingRole; no call to db.
            if (!PrefC.GetBool(PrefName.ClaimSnapshotEnabled) ||
                PIn.Enum <ClaimSnapshotTrigger>(PrefC.GetString(PrefName.ClaimSnapshotTriggerType), true) != triggerType)
            {
                return;
            }
            if (triggerType == ClaimSnapshotTrigger.Service)
            {
                CreateClaimSnapShotService();
                return;
            }
            Dictionary <long, double> dictCompletedProcFees = Procedures.GetProcsFromClaimProcs(listClaimProcs).ToDictionary(x => x.ProcNum, x => x.ProcFee);

            //Loop through all the claimprocs and create a claimsnapshot entry for each.
            foreach (ClaimProc cp in listClaimProcs)
            {
                //only create snapshots for 0=NotReceived, 1=Received, 4=Supplemental, 5=CapClaim, 6=Estimate (only if triggerType=Service),
                //7=CapComplete, and 8=CapEstimate (only if triggerType=Service)
                if (cp.Status.In(ClaimProcStatus.Preauth, ClaimProcStatus.Adjustment, ClaimProcStatus.Estimate, ClaimProcStatus.CapEstimate))
                {
                    continue;
                }
                //get the procfee
                double procFee;
                if (!dictCompletedProcFees.TryGetValue(cp.ProcNum, out procFee))
                {
                    procFee = 0;
                }
                ClaimSnapshot snapshot = new ClaimSnapshot();
                snapshot.ProcNum         = cp.ProcNum;
                snapshot.Writeoff        = cp.WriteOff;
                snapshot.InsPayEst       = cp.InsEstTotal;
                snapshot.Fee             = procFee;
                snapshot.ClaimProcNum    = cp.ClaimProcNum;
                snapshot.SnapshotTrigger = triggerType;
                snapshot.ClaimType       = claimType;
                ClaimSnapshots.Insert(snapshot);
            }
        }
Ejemplo n.º 4
0
        ///<summary>Called when logging user off or closing opendental.</summary>
        public static void LogOff()
        {
            if (!PrefC.HasClinicsEnabled)
            {
                _clinicNum = 0;
                return;
            }
            switch (PrefC.GetString(PrefName.ClinicTrackLast))
            {
            case "Workstation":
                ComputerPref compPref = ComputerPrefs.LocalComputer;
                compPref.ClinicNum = Clinics.ClinicNum;
                ComputerPrefs.Update(compPref);
                break;

            case "User":
                List <UserOdPref> UserPrefs = UserOdPrefs.GetByUserAndFkeyType(Security.CurUser.UserNum, UserOdFkeyType.ClinicLast);                      //should only be one or none.
                if (UserPrefs.Count == 0)
                {
                    //this situation should never happen.
                    UserOdPref pref =
                        new UserOdPref()
                    {
                        UserNum  = Security.CurUser.UserNum,
                        FkeyType = UserOdFkeyType.ClinicLast,
                        Fkey     = Clinics.ClinicNum
                    };
                    UserOdPrefs.Insert(pref);
                    break;
                }
                UserPrefs.ForEach(x => x.Fkey = Clinics.ClinicNum);
                UserPrefs.ForEach(UserOdPrefs.Update);
                break;

            case "None":
            default:
                break;
            }
            _clinicNum = 0;
        }
Ejemplo n.º 5
0
		///<summary>Returns true if a change was required, or false if no change needed.</summary>
		public static bool UpdateString(PrefName prefName,string newValue) {
			//Very unusual.  Involves cache, so Meth is used further down instead of here at the top.
			string curValue=PrefC.GetString(prefName);
			if(curValue==newValue) {
				return false;//no change needed
			}
			string command = "UPDATE preference SET "
				+"ValueString = '"+POut.String(newValue)+"' "
				+"WHERE PrefName = '"+POut.String(prefName.ToString())+"'";
			bool retVal=true;
			if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
				retVal=Meth.GetBool(MethodBase.GetCurrentMethod(),prefName,newValue);
			}
			else {
				Db.NonQ(command);
			}
			Pref pref=new Pref();
			pref.PrefName=prefName.ToString();
			pref.ValueString=newValue;
			Prefs.UpdateValueForKey(pref);
			return retVal;
		}
Ejemplo n.º 6
0
 ///<summary>Gets the Voice Mail Origination path for this current computer.</summary>
 public static string GetVoiceMailOriginationPath()
 {
     try {
         //The VoiceMailOriginationPath preference stores a list of KeyValuePairs where the key is the name of the computer and the value
         //is the path. When JSON-serialized it looks like this:
         //[{"Key":"SERVER153","Value":"\\\\110.10.6.249\\Voicemail\\default\\998\\INBOX"},{"Key":"CHRISM","Value":"C:\\development"}]
         List <KeyValuePair <string, string> > listPaths = JsonConvert.DeserializeObject <List <KeyValuePair <string, string> > >
                                                               (PrefC.GetString(PrefName.VoiceMailOriginationPath));
         foreach (KeyValuePair <string, string> kvp in listPaths)
         {
             if (kvp.Key == Environment.MachineName)
             {
                 return(kvp.Value);
             }
         }
         return(listPaths[0].Value);               //Return the first one in the list.
     }
     catch (Exception ex) {
         ex.DoNothing();
         return(Phones.PathPhoneMsg);               //If all else fails, return a hard-coded path.
     }
 }
Ejemplo n.º 7
0
        ///<summary>Called when logging user off or closing opendental.</summary>
        public static void LogOff()
        {
            if (!PrefC.HasClinicsEnabled)
            {
                _clinicNum = 0;
                return;
            }
            switch (PrefC.GetString(PrefName.ClinicTrackLast))
            {
            case "Workstation":
                ComputerPrefs.LocalComputer.ClinicNum = Clinics.ClinicNum;
                ComputerPrefs.Update(ComputerPrefs.LocalComputer);
                break;

            case "User":                    //handled below
            case "None":
            default:
                break;
            }
            //We want to always upsert a user pref for the user because we will be looking at it for MobileWeb regardless of the preference for
            //ClinicTrackLast.
            List <UserOdPref> UserPrefs = UserOdPrefs.GetByUserAndFkeyType(Security.CurUser.UserNum, UserOdFkeyType.ClinicLast);        //should only be one or none.

            if (UserPrefs.Count == 0)
            {
                UserOdPref pref = new UserOdPref()
                {
                    UserNum  = Security.CurUser.UserNum,
                    FkeyType = UserOdFkeyType.ClinicLast,
                    Fkey     = Clinics.ClinicNum
                };
                UserOdPrefs.Insert(pref);
            }
            UserPrefs.ForEach(x => {
                x.Fkey = Clinics.ClinicNum;
                UserOdPrefs.Update(x);
            });
            _clinicNum = 0;
        }
Ejemplo n.º 8
0
 ///<summary>Returns a clinic object with ClinicNum=0, and values filled using practice level preferences.
 /// Caution: do not attempt to save the clinic back to the DB. This should be used for read only purposes.</summary>
 public static Clinic GetPracticeAsClinicZero(string clinicName = null)
 {
     //No need to check RemotingRole; no call to db.
     if (clinicName == null)
     {
         clinicName = PrefC.GetString(PrefName.PracticeTitle);
     }
     return(new Clinic {
         ClinicNum = 0,
         Abbr = clinicName,
         Description = clinicName,
         Address = PrefC.GetString(PrefName.PracticeAddress),
         Address2 = PrefC.GetString(PrefName.PracticeAddress2),
         City = PrefC.GetString(PrefName.PracticeCity),
         State = PrefC.GetString(PrefName.PracticeST),
         Zip = PrefC.GetString(PrefName.PracticeZip),
         BillingAddress = PrefC.GetString(PrefName.PracticeBillingAddress),
         BillingAddress2 = PrefC.GetString(PrefName.PracticeBillingAddress2),
         BillingCity = PrefC.GetString(PrefName.PracticeBillingCity),
         BillingState = PrefC.GetString(PrefName.PracticeBillingST),
         BillingZip = PrefC.GetString(PrefName.PracticeBillingZip),
         PayToAddress = PrefC.GetString(PrefName.PracticePayToAddress),
         PayToAddress2 = PrefC.GetString(PrefName.PracticePayToAddress2),
         PayToCity = PrefC.GetString(PrefName.PracticePayToCity),
         PayToState = PrefC.GetString(PrefName.PracticePayToST),
         PayToZip = PrefC.GetString(PrefName.PracticePayToZip),
         Phone = PrefC.GetString(PrefName.PracticePhone),
         BankNumber = PrefC.GetString(PrefName.PracticeBankNumber),
         DefaultPlaceService = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService),
         InsBillingProv = PrefC.GetLong(PrefName.InsBillingProv),
         Fax = PrefC.GetString(PrefName.PracticeFax),
         EmailAddressNum = PrefC.GetLong(PrefName.EmailDefaultAddressNum),
         DefaultProv = PrefC.GetLong(PrefName.PracticeDefaultProv),
         SmsContractDate = PrefC.GetDate(PrefName.SmsContractDate),
         SmsMonthlyLimit = PrefC.GetDouble(PrefName.SmsMonthlyLimit),
         IsMedicalOnly = PrefC.GetBool(PrefName.PracticeIsMedicalOnly)
     });
 }
Ejemplo n.º 9
0
        ///<summary>The proxy's working directory.</summary>
        public static string SendAndReceiveUpdateRequestXml()
        {
            List <string> listProgramsEnabled = Programs.GetWhere(x => x.Enabled && !string.IsNullOrWhiteSpace(x.ProgName))
                                                .Select(x => x.ProgName).ToList();
            //prepare the xml document to send--------------------------------------------------------------------------------------
            XmlWriterSettings settings = new XmlWriterSettings();

            settings.Indent      = true;
            settings.IndentChars = ("    ");
            StringBuilder strbuild = new StringBuilder();

            using (XmlWriter writer = XmlWriter.Create(strbuild, settings)) {
                writer.WriteStartElement("UpdateRequest");
                writer.WriteStartElement("RegistrationKey");
                writer.WriteString(PrefC.GetString(PrefName.RegistrationKey));
                writer.WriteEndElement();
                writer.WriteStartElement("PracticeTitle");
                writer.WriteString(PrefC.GetString(PrefName.PracticeTitle));
                writer.WriteEndElement();
                writer.WriteStartElement("PracticePhone");
                writer.WriteString(PrefC.GetString(PrefName.PracticePhone));
                writer.WriteEndElement();
                writer.WriteStartElement("ProgramVersion");
                writer.WriteString(PrefC.GetString(PrefName.ProgramVersion));
                writer.WriteEndElement();
                writer.WriteStartElement("ClinicCount");
                writer.WriteString(PrefC.HasClinicsEnabled ? Clinics.GetCount(true).ToString() : "0");
                writer.WriteEndElement();
                writer.WriteStartElement("ListProgramsEnabled");
                new XmlSerializer(typeof(List <string>)).Serialize(writer, listProgramsEnabled);
                writer.WriteEndElement();
                writer.WriteStartElement("DateFormat");
                writer.WriteString(CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern);
                writer.WriteEndElement();
                writer.WriteEndElement();                //UpdateRequest
            }
            return(GetWebServiceInstance().RequestUpdate(strbuild.ToString()));
        }
Ejemplo n.º 10
0
        ///<summary>Only makes a call to the database on startup.  After that, just uses cached data.  Does not validate that the path exists except if the main one is used.  ONLY used from Client layer; no S classes.</summary>
        public static string GetPreferredAtoZpath()
        {
            if (!PrefC.UsingAtoZfolder)
            {
                return(null);
            }
            if (LocalAtoZpath == null)           //on startup
            {
                LocalAtoZpath = ComputerPrefs.LocalComputer.AtoZpath;
            }
            string replicationAtoZ = ReplicationServers.GetAtoZpath();

            if (replicationAtoZ != "")
            {
                return(replicationAtoZ);
            }
            if (LocalAtoZpath != "")
            {
                return(LocalAtoZpath);
            }
            //use this to handle possible multiple paths separated by semicolons.
            return(GetValidPathFromString(PrefC.GetString(PrefName.DocPath)));
        }
Ejemplo n.º 11
0
        ///<summary>Returns an email message for the patient based on the statement passed in.</summary>
        public static EmailMessage GetEmailMessageForStatement(Statement stmt, Patient pat)
        {
            if (stmt.PatNum != pat.PatNum)
            {
                string logMsg = Lans.g("Statements", "Mismatched PatNums detected between current patient and current statement:") + "\r\n"
                                + Lans.g("Statements", "Statement PatNum:") + " " + stmt.PatNum + " " + Lans.g("Statements", "(assumed correct)") + "\r\n"
                                + Lans.g("Statements", "Patient PatNum:") + " " + pat.PatNum + " " + Lans.g("Statements", "(possibly incorrect)");
                SecurityLogs.MakeLogEntry(Permissions.StatementPatNumMismatch, stmt.PatNum, logMsg, LogSources.Diagnostic);
            }
            //No need to check RemotingRole; no call to db.
            EmailMessage message = new EmailMessage();

            message.PatNum      = pat.PatNum;
            message.ToAddress   = pat.Email;
            message.FromAddress = EmailAddresses.GetByClinic(pat.ClinicNum).GetFrom();
            string str;

            if (stmt.EmailSubject != null && stmt.EmailSubject != "")
            {
                str = stmt.EmailSubject; //Set str to the email subject if one was already set.
            }
            else                         //Subject was not set.  Set str to the default billing email subject.
            {
                str = PrefC.GetString(PrefName.BillingEmailSubject);
            }
            message.Subject = Statements.ReplaceVarsForEmail(str, pat, stmt);
            if (stmt.EmailBody != null && stmt.EmailBody != "")
            {
                str = stmt.EmailBody; //Set str to the email body if one was already set.
            }
            else                      //Body was not set.  Set str to the default billing email body text.
            {
                str = PrefC.GetString(PrefName.BillingEmailBodyText);
            }
            message.BodyText = Statements.ReplaceVarsForEmail(str, pat, stmt);
            return(message);
        }
Ejemplo n.º 12
0
        ///<summary>Replaces variable tags with the information from the patient passed in.</summary>
        public static string ReplaceVarsForSms(string smsTemplate, Patient pat, Statement stmt)
        {
            //No need to check RemotingRole; no call to db.
            StringBuilder retVal = new StringBuilder();

            retVal.Append(smsTemplate);
            if (smsTemplate.Contains("[monthlyCardsOnFile]"))
            {
                retVal.RegReplace("\\[monthlyCardsOnFile]", CreditCards.GetMonthlyCardsOnFile(pat.PatNum));
            }
            retVal.RegReplace("\\[nameF]", pat.GetNameFirst());
            retVal.RegReplace("\\[namePref]", pat.Preferred);
            retVal.RegReplace("\\[PatNum]", pat.PatNum.ToString());
            retVal.RegReplace("\\[currentMonth]", DateTime.Now.ToString("MMMM"));
            Clinic clinic      = Clinics.GetClinic(pat.ClinicNum) ?? Clinics.GetPracticeAsClinicZero();
            string officePhone = clinic.Phone;

            if (string.IsNullOrEmpty(officePhone))
            {
                officePhone = PrefC.GetString(PrefName.PracticePhone);
            }
            retVal.RegReplace("\\[OfficePhone]", TelephoneNumbers.ReFormat(officePhone));
            string officeName = clinic.Description;

            if (string.IsNullOrEmpty(officeName))
            {
                officeName = PrefC.GetString(PrefName.PracticeTitle);
            }
            retVal.RegReplace("\\[OfficeName]", officeName);
            if (smsTemplate.ToLower().Contains("[statementurl]") || smsTemplate.ToLower().Contains("[statementshorturl]"))
            {
                AssignURLsIfNecessary(stmt, pat);
            }
            retVal.RegReplace("\\[StatementURL]", stmt.StatementURL);
            retVal.RegReplace("\\[StatementShortURL]", stmt.StatementShortURL);
            return(retVal.ToString());
        }
Ejemplo n.º 13
0
 ///<summary>Returns true if any Web Sched Recall text or email template contains a URL tag.</summary>
 public static bool TemplatesHaveURLTags()
 {
     foreach (PrefName pref in new List <PrefName> {
         PrefName.WebSchedSubject,
         PrefName.WebSchedMessage,
         PrefName.WebSchedMessageText,
         PrefName.WebSchedAggregatedEmailBody,
         PrefName.WebSchedAggregatedEmailSubject,
         PrefName.WebSchedAggregatedTextMessage,
         PrefName.WebSchedSubject2,
         PrefName.WebSchedMessage2,
         PrefName.WebSchedMessageText2,
         PrefName.WebSchedSubject3,
         PrefName.WebSchedMessage3,
         PrefName.WebSchedMessageText3,
     })
     {
         if (HasURLTag(PrefC.GetString(pref)))
         {
             return(true);
         }
     }
     return(false);
 }
Ejemplo n.º 14
0
        ///<summary>Returns a blank string if there were no errors while attempting to update internal carriers using iTrans n-cpl.json file.</summary>
        public static string TryCarrierUpdate(bool isAutomatic = true, ItransImportFields fieldsToImport = ItransImportFields.None)
        {
            string        json;
            DateTime      dateTimeTrans = DateTime.Now;
            Clearinghouse clearinghouse = Clearinghouses.GetDefaultDental();

            if (clearinghouse == null)
            {
                return(Lans.g("Clearinghosue", "Unable to update. No default dental clearinghouse set."));
            }
            //If ITRANS2 is fully setup, then use the local ITRANS2 install on server to import carrier data.
            if (clearinghouse.CommBridge == EclaimsCommBridge.ITRANS && !string.IsNullOrEmpty(clearinghouse.ResponsePath))
            {
                if (!File.Exists(ODFileUtils.CombinePaths(clearinghouse.ResponsePath, "ITRANS Claims Director.exe")))
                {
                    return(Lans.g("Clearinghouse", "Unable to find 'ITRANS Claims Director.exe'. Make sure the file exists and the path is correct."));
                }
                if (isAutomatic && PrefC.GetString(PrefName.WebServiceServerName).ToLower() != Dns.GetHostName().ToLower())               //Only server can run when isOnlyServer is true.
                {
                    return(Lans.g("Clearinghouse", "Update can only run on the web service server " + PrefC.GetString(PrefName.WebServiceServerName)) +
                           ". " + Lans.g("Clearinghouse", "Connect to the server and try again."));
                }
                Process process = new Process {
                    StartInfo = new ProcessStartInfo {
                        FileName  = ODFileUtils.CombinePaths(clearinghouse.ResponsePath, "ITRANS Claims Director.exe"),
                        Arguments = " --getncpl"
                    }
                };
                process.Start();
                process.WaitForExit();
                string ncplFilePath = ODFileUtils.CombinePaths(clearinghouse.ResponsePath, "n-cpl.json");
                json          = File.ReadAllText(ncplFilePath);     //Read n-cpl.json
                dateTimeTrans = File.GetCreationTime(ncplFilePath);
            }
            else              //ITRANS2 not used or not setup correctly, go to HQ for file content.
            {
                try {
                    string result = WebServiceMainHQProxy.GetWebServiceMainHQInstance().CanadaCarrierUpdate(PayloadHelper.CreatePayload("", eServiceCode.Undefined));
                    json = WebSerializer.DeserializePrimitiveOrThrow <string>(result);
                }
                catch (Exception ex) {
                    return(Lans.g("Clearinghouse", "Unable to update carrier list from HQ web services.") + "\r\n" + ex.Message.ToString());
                }
            }
            EtransMessageText msgTextPrev = EtransMessageTexts.GetMostRecentForType(EtransType.ItransNcpl);

            if (msgTextPrev != null && msgTextPrev.MessageText == json)
            {
                if (isAutomatic ||
                    ODMessageBox.Show("Carrier list has not changed since last checked.\r\nContinue?", "", MessageBoxButtons.YesNo) != DialogResult.Yes)
                {
                    return(Lans.g("Clearinghouse", "Carrier list has not changed since last checked."));                  //json has not changed since we last checked, no need to update.
                }
            }
            //Save json as new etrans entry.
            Etrans etrans = Etranss.CreateEtrans(dateTimeTrans, clearinghouse.HqClearinghouseNum, json, 0);

            etrans.Etype = EtransType.ItransNcpl;
            Etranss.Insert(etrans);
            ItransNCpl iTransNCpl = null;

            try {
                iTransNCpl = JsonConvert.DeserializeObject <ItransNCpl>(json);             //Deserialize n-cpl.json
            }
            catch (Exception ex) {
                ex.DoNothing();
                return(Lans.g("Clearinghouse", "Failed to import json."));
            }
            List <CanadianNetwork> listCanadianNetworks = CanadianNetworks.GetDeepCopy();
            //List of carriers from json file that were matched by electId to multiple internal carriers
            List <Carrier> listUnmatchedJsonCarriers = new List <Carrier>();
            List <long>    listMatchedDbCarrierNums  = new List <long> ();

            foreach (ItransNCpl.Carrier jsonCarrier in iTransNCpl.ListCarriers) //Update carriers.
            {
                string jsonCarrierPhone = jsonCarrier.Telephone?.First().Value; //Will be empty string if not found.
                List <OpenDentBusiness.Carrier> listDbCarriers = Carriers.GetAllByElectId(jsonCarrier.Bin).FindAll(x => x.IsCDA);
                if (listDbCarriers.Count > 1)                                   //Some Canadian carriers share ElectId, need to filter further.  This happens with carrier resellers.
                {
                    #region Additional matching based on phone numbers, 'continues' loop if a single match is not found.
                    List <OpenDentBusiness.Carrier> listPhoneMatchedDbCarriers = listDbCarriers.FindAll(x =>
                                                                                                        TelephoneNumbers.AreNumbersEqual(x.Phone, jsonCarrierPhone)
                                                                                                        );
                    if (listPhoneMatchedDbCarriers.Count != 1)                   //Either 0 or multiple matches, either way do not update any carriers.
                    //When 0 matches found:	jsonCarrier changed their phone number, can not determine which carrier to update.
                    //E.G. - JsonCarrier A matched to OD carriers B and C by electId.
                    //Phone number from JsonCarrier A did not match either carrier B or C due to jsonCarrier phone number change.
                    //Future iterations for jsonCarrier D might match to carrier B or C if phone number for jsonCarrier D did not change.
                    //If jsonCarrier D is matched to single OD carrier, then jsonCarrier A will attempt to match near end of method to a unmatched internal carrier.
                    //If ther are no future matches to OD carrier B or C then all unmatched jsonCarriers will not be imported and no OD carries will not be updated.
                    //----------------------------------------------------------------------//
                    //When greater than 1:	jsonCarrier number not changed and both internal carriers have matching electIds and phone numbers.
                    //This should be rare, most likely a setup error.
                    //There should not be multiple carriers that share electId and phone numbers. User should change or remove one of the matched carriers.
                    {
                        listUnmatchedJsonCarriers.Add(jsonCarrier);
                        continue;
                    }
                    listDbCarriers = listPhoneMatchedDbCarriers;
                    #endregion
                }
                //At this point listDbCarriers should either be empty or contain a single OD carrier.
                OpenDentBusiness.Carrier carrierInDb = listDbCarriers.FirstOrDefault(); //Null if list is empty.
                if (carrierInDb == null)                                                //Carrier can not be matched to internal Carrier based on ElectID.
                {
                    #region Insert new carrier
                    if (!fieldsToImport.HasFlag(ItransImportFields.AddMissing))
                    {
                        continue;
                    }
                    OpenDentBusiness.Carrier carrierNew = new OpenDentBusiness.Carrier();
                    carrierNew.CanadianEncryptionMethod = 1;                  //Default.  Deprecated for all Canadian carriers and will never be any other value.
                    TrySetCanadianNetworkNum(jsonCarrier, carrierNew, listCanadianNetworks);
                    carrierNew.ElectID     = jsonCarrier.Bin;
                    carrierNew.IsCDA       = true;
                    carrierNew.CarrierName = jsonCarrier.Name.En;
                    carrierNew.Phone       = TelephoneNumbers.AutoFormat(jsonCarrierPhone);
                    if (jsonCarrier.Address.Count() > 0)
                    {
                        Address add = jsonCarrier.Address.First();
                        carrierNew.Address  = add.Street1;
                        carrierNew.Address2 = add.Street2;
                        carrierNew.City     = add.City;
                        carrierNew.State    = add.Province;
                        carrierNew.Zip      = add.Postal_Code;
                    }
                    carrierNew.CanadianSupportedTypes = GetSupportedTypes(jsonCarrier);
                    carrierNew.CDAnetVersion          = POut.Int(jsonCarrier.Versions.Max(x => PIn.Int(x))).PadLeft(2, '0');        //Version must be in 2 digit format. ex. 02.
                    carrierNew.CarrierName            = jsonCarrier.Name.En;
                    try {
                        Carriers.Insert(carrierNew);
                    }
                    catch (Exception ex) {
                        ex.DoNothing();
                    }
                    #endregion
                    continue;
                }
                listMatchedDbCarrierNums.Add(carrierInDb.CarrierNum);
                UpdateCarrierInDb(carrierInDb, jsonCarrier, listCanadianNetworks, fieldsToImport, jsonCarrierPhone, isAutomatic);
            }
            foreach (Carrier jsonCarrier in listUnmatchedJsonCarriers)
            {
                List <OpenDentBusiness.Carrier> listDbCarriers = Carriers.GetWhere(x => x.IsCDA &&
                                                                                   x.ElectID == jsonCarrier.Bin && !listMatchedDbCarrierNums.Contains(x.CarrierNum)
                                                                                   );
                if (listDbCarriers.Count != 1)               //Either 0 or multiple matches, either way do not update any carriers.
                {
                    continue;
                }
                OpenDentBusiness.Carrier carrierInDb = listDbCarriers.FirstOrDefault();
                string jsonCarrierPhone = jsonCarrier.Telephone?.First().Value;
                UpdateCarrierInDb(carrierInDb, jsonCarrier, listCanadianNetworks, fieldsToImport, jsonCarrierPhone, isAutomatic);
            }
            return("");           //Blank string represents a completed update.
        }
Ejemplo n.º 15
0
 ///<summary>No need to pass in userNum, it's set before remoting role check and passed to the server if necessary.
 ///<para>This is the automation behind keeping treatplans correct.  Many calls to DB, consider optimizing or calling sparingly.</para>
 ///<para>Ensures patients only have one active treatplan, marks extras inactive and creates an active if necessary.</para>
 ///<para>Attaches procedures to the active plan if the proc status is TP or status is TPi and the procs is attached to a sched/planned appt.</para>
 ///<para>Creates an unassigned treatplan if necessary and attaches any unassigned procedures to it.</para>
 ///<para>Also maintains priorities of treatplanattaches and procedures and updates the procstatus of TP and TPi procs if necessary.</para></summary>
 public static void AuditPlans(long patNum, TreatPlanType tpType, long userNum = 0)
 {
     if (RemotingClient.RemotingRole != RemotingRole.ServerWeb)
     {
         userNum = Security.CurUser.UserNum;              //must be before normal remoting role check to get user at workstation
     }
     if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
     {
         Meth.GetVoid(MethodBase.GetCurrentMethod(), patNum, tpType, userNum);
         return;
     }
     #region Pseudo Code
     //Get all treatplans for the patient
     //Find active TP if it already exists
     //If more than one active TP, update all but the first to Inactive
     //Find unassigned TP if it already exists
     //Get all treatplanattaches for the treatplans
     //Get all TP and TPi procs for the patient
     //Get list of procs for the active plan, i.e. TPA exists linking to active plan or ProcStatus is TP or attached to sched/planned appt
     //Get list of inactive procs, i.e. ProcStatus is TPi and AptNum is 0 and PlannedAptNum is 0 and no TPA exists linking it to the active plan
     //Create an active plan if one doesn't exist and there are procs that need to be attached to it
     //Create an unassigned plan if one doesn't exist and there are unassigned TPi procs
     //For each proc that should be attached to the active plan
     //  update status from TPi to TP
     //  if TPA exists linking to active plan, update priority to TPA priority
     //  delete any TPA that links the proc to the unassigned plan
     //  if TPA linking the proc to the active plan does not exist, insert one with TPA priority set to the proc priority
     //For each proc that is not attached to the active plan (ProcStatus is TPi)
     //  set proc priority to 0
     //  if TPA does not exist, insert one linking the proc to the unassigned plan with TPA priority 0
     //  if multiple TPAs exist with one linking the proc to the unassigned plan, delete the TPA linking to the unassigned plan
     //Foreach TPA
     //  if TPA links proc to the unassigned plan and TPA exists linking the proc to any other plan, delete the link to the unassigned plan
     //If an unassigned plan exists and there are no TPAs pointing to it, delete the unassigned plan
     #endregion Pseudo Code
     #region Variables
     List <TreatPlan>       listTreatPlans       = TreatPlans.GetAllForPat(patNum);                                                                                               //All treatplans for the pat. [([Includes Saved Plans]}};
     TreatPlan              activePlan           = listTreatPlans.FirstOrDefault(x => x.TPStatus == TreatPlanStatus.Active);                                                      //can be null
     TreatPlan              unassignedPlan       = listTreatPlans.FirstOrDefault(x => x.TPStatus == TreatPlanStatus.Inactive && x.Heading == Lans.g("TreatPlans", "Unassigned")); //can be null
     List <TreatPlanAttach> listTPAs             = TreatPlanAttaches.GetAllForTPs(listTreatPlans.Select(x => x.TreatPlanNum).ToList());
     List <Procedure>       listProcsTpTpi       = Procedures.GetProcsByStatusForPat(patNum, new[] { ProcStat.TP, ProcStat.TPi });                                                //All TP and TPi procs for the pat.
     List <Procedure>       listProcsForActive   = new List <Procedure>();                                                                                                        //All procs that should be linked to the active plan (can be linked to inactive plans as well)
     List <Procedure>       listProcsForInactive = new List <Procedure>();                                                                                                        //All procs that should not be linked to the active plan (linked to inactive or unnasigned)
     long[] arrayTpaProcNums = listTPAs.Select(x => x.ProcNum).ToArray();                                                                                                         //All procnums from listTPAs, makes it easier to see if a TPA exists for a proc
     #endregion Variables
     #region Fill Proc Lists and Create Active and Unassigned Plans
     foreach (Procedure procCur in listProcsTpTpi)             //puts each procedure in listProcsForActive or listProcsForInactive
     {
         if (procCur.ProcStatus == ProcStat.TP ||              //all TP procs should be linked to active plan
             procCur.AptNum > 0 ||                             //all procs attached to an appt should be linked to active plan
             procCur.PlannedAptNum > 0 ||                      //all procs attached to a planned appt should be linked to active plan
             (activePlan != null &&                            //if active plan exists and proc is linked to it, add to list
              listTPAs.Any(x => x.ProcNum == procCur.ProcNum && x.TreatPlanNum == activePlan.TreatPlanNum)))
         {
             listProcsForActive.Add(procCur);
         }
         else                  //TPi status, AptNum=0, PlannedAptNum=0, and not attached to active plan
         {
             listProcsForInactive.Add(procCur);
         }
     }
     //Create active plan if needed
     if (activePlan == null && listProcsForActive.Count > 0)
     {
         activePlan = new TreatPlan()
         {
             Heading  = Lans.g("TreatPlans", "Active Treatment Plan"),
             Note     = PrefC.GetString(PrefName.TreatmentPlanNote),
             TPStatus = TreatPlanStatus.Active,
             PatNum   = patNum,
             //UserNumPresenter=userNum,
             SecUserNumEntry = userNum,
             TPType          = tpType
         };
         TreatPlans.Insert(activePlan);
         listTreatPlans.Add(activePlan);
     }
     //Update extra active plans to Inactive status, should only ever be one Active status plan
     //All TP procs are linked to the active plan, so proc statuses won't have to change to TPi for procs attached to an "extra" active plan
     foreach (TreatPlan tp in listTreatPlans.FindAll(x => x.TPStatus == TreatPlanStatus.Active && activePlan != null && x.TreatPlanNum != activePlan.TreatPlanNum))
     {
         tp.TPStatus = TreatPlanStatus.Inactive;
         TreatPlans.Update(tp);
     }
     //Create unassigned plan if needed
     if (unassignedPlan == null && listProcsForInactive.Any(x => !arrayTpaProcNums.Contains(x.ProcNum)))
     {
         unassignedPlan = new TreatPlan()
         {
             Heading  = Lans.g("TreatPlans", "Unassigned"),
             Note     = PrefC.GetString(PrefName.TreatmentPlanNote),
             TPStatus = TreatPlanStatus.Inactive,
             PatNum   = patNum,
             //UserNumPresenter=userNum,
             SecUserNumEntry = userNum,
             TPType          = tpType
         };
         TreatPlans.Insert(unassignedPlan);
         listTreatPlans.Add(unassignedPlan);
     }
     #endregion Fill Proc Lists and Create Active and Unassigned Plans
     #region Procs for Active Plan
     //Update proc status to TP for all procs that should be linked to the active plan.
     //For procs with an existing TPA linking it to the active plan, update proc priority to the TPA priority.
     //Remove any TPAs linking the proc to the unassigned plan.
     //Create TPAs linking the proc to the active plan if needed with TPA priority set to the proc priority.
     foreach (Procedure procActive in listProcsForActive)
     {
         Procedure procOld = procActive.Copy();
         procActive.ProcStatus = ProcStat.TP;
         //checking the array of ProcNums for an existing TPA is fast, so check the list first
         if (arrayTpaProcNums.Contains(procActive.ProcNum))
         {
             if (unassignedPlan != null)                   //remove any TPAs linking the proc to the unassigned plan
             {
                 listTPAs.RemoveAll(x => x.ProcNum == procActive.ProcNum && x.TreatPlanNum == unassignedPlan.TreatPlanNum);
             }
             TreatPlanAttach tpaActivePlan = listTPAs.FirstOrDefault(x => x.ProcNum == procActive.ProcNum && x.TreatPlanNum == activePlan.TreatPlanNum);
             if (tpaActivePlan == null)                   //no TPA linking the proc to the active plan, create one with priority equal to the proc priority
             {
                 listTPAs.Add(new TreatPlanAttach()
                 {
                     ProcNum = procActive.ProcNum, TreatPlanNum = activePlan.TreatPlanNum, Priority = procActive.Priority
                 });
             }
             else                      //TPA linking this proc to the active plan exists, update proc priority to equal TPA priority
             {
                 procActive.Priority = tpaActivePlan.Priority;
             }
         }
         else                  //no TPAs exist for this proc, add one linking the proc to the active plan and set the TPA priority equal to the proc priority
         {
             listTPAs.Add(new TreatPlanAttach()
             {
                 ProcNum = procActive.ProcNum, TreatPlanNum = activePlan.TreatPlanNum, Priority = procActive.Priority
             });
         }
         Procedures.Update(procActive, procOld);
     }
     #endregion Procs for Active Plan
     #region Procs for Inactive and Unassigned Plans
     //Update proc priority to 0 for all inactive procs.
     //If no TPA exists for the proc, create a TPA with priority 0 linking the proc to the unassigned plan.
     foreach (Procedure procInactive in listProcsForInactive)
     {
         Procedure procOld = procInactive.Copy();
         procInactive.Priority = 0;
         Procedures.Update(procInactive, procOld);
         if (unassignedPlan != null && !arrayTpaProcNums.Contains(procInactive.ProcNum))
         {
             //no TPAs for this proc, add a new one to the list linking proc to the unassigned plan
             listTPAs.Add(new TreatPlanAttach {
                 TreatPlanNum = unassignedPlan.TreatPlanNum, ProcNum = procInactive.ProcNum, Priority = 0
             });
         }
     }
     #endregion Procs for Inactive and Unassigned Plans
     #region Sync and Clean-Up TreatPlanAttach List
     //Remove any TPAs if the proc isn't in listProcsTpTpi, status could've changed or possibly proc is for a different pat.
     listTPAs.RemoveAll(x => !listProcsTpTpi.Select(y => y.ProcNum).Contains(x.ProcNum));
     if (unassignedPlan != null)           //if an unassigned plan exists
     //Remove any TPAs from the list that link a proc to the unassigned plan if there is a TPA that links the proc to any other plan
     {
         listTPAs.RemoveAll(x => x.TreatPlanNum == unassignedPlan.TreatPlanNum &&
                            listTPAs.Any(y => y.ProcNum == x.ProcNum && y.TreatPlanNum != unassignedPlan.TreatPlanNum));
     }
     listTreatPlans.ForEach(x => TreatPlanAttaches.Sync(listTPAs.FindAll(y => y.TreatPlanNum == x.TreatPlanNum), x.TreatPlanNum));
     if (unassignedPlan != null)                                                       //Must happen after Sync. Delete the unassigned plan if it exists and there are no TPAs pointing to it.
     {
         listTPAs = TreatPlanAttaches.GetAllForTreatPlan(unassignedPlan.TreatPlanNum); //from DB.
         if (listTPAs.Count == 0)                                                      //nothing attached to unassigned anymore
         {
             Crud.TreatPlanCrud.Delete(unassignedPlan.TreatPlanNum);
         }
     }
     #endregion Sync and Clean-Up TreatPlanAttach List
 }
Ejemplo n.º 16
0
        private static Procedure AddRepeatingChargeHelper(RepeatCharge repeatCharge, DateTime billingDate, DateTime dateNow)
        {
            //No remoting role check; no call to db
            Procedure     procedure = new Procedure();
            ProcedureCode procCode  = ProcedureCodes.GetProcCode(repeatCharge.ProcCode);
            Patient       pat       = Patients.GetPat(repeatCharge.PatNum);

            procedure.CodeNum    = procCode.CodeNum;
            procedure.ClinicNum  = pat.ClinicNum;
            procedure.DateEntryC = dateNow;
            procedure.PatNum     = repeatCharge.PatNum;
            procedure.ProcDate   = billingDate;
            procedure.DateTP     = billingDate;
            procedure.ProcFee    = repeatCharge.ChargeAmt;
            procedure.ProcStatus = ProcStat.C;
            if (procCode.ProvNumDefault == 0)
            {
                procedure.ProvNum = pat.PriProv;
            }
            else
            {
                procedure.ProvNum = procCode.ProvNumDefault;
            }
            procedure.MedicalCode     = ProcedureCodes.GetProcCode(procedure.CodeNum).MedicalCode;
            procedure.BaseUnits       = ProcedureCodes.GetProcCode(procedure.CodeNum).BaseUnits;
            procedure.DiagnosticCode  = PrefC.GetString(PrefName.ICD9DefaultForNewProcs);
            procedure.RepeatChargeNum = repeatCharge.RepeatChargeNum;
            procedure.PlaceService    = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService);       //Default Proc Place of Service for the Practice is used.
            //Check if the repeating charge has been flagged to copy it's note into the billing note of the procedure.
            if (repeatCharge.CopyNoteToProc)
            {
                procedure.BillingNote = repeatCharge.Note;
                if (repeatCharge.ErxAccountId != "")
                {
                    procedure.BillingNote =
                        "NPI=" + repeatCharge.Npi + "  " + "ErxAccountId=" + repeatCharge.ErxAccountId;
                    if (!string.IsNullOrEmpty(repeatCharge.ProviderName))                     //Provider name would be empty if older and no longer updated from eRx.
                    {
                        procedure.BillingNote += "\r\nProviderName=" + repeatCharge.ProviderName;
                    }
                    if (!string.IsNullOrEmpty(repeatCharge.Note))
                    {
                        procedure.BillingNote += "\r\n" + repeatCharge.Note;
                    }
                }
            }
            if (!PrefC.GetBool(PrefName.EasyHidePublicHealth))
            {
                procedure.SiteNum = pat.SiteNum;
            }
            Procedures.Insert(procedure);             //no recall synch needed because dental offices don't use this feature
            //Using Prepayments for this Procedure
            if (repeatCharge.UsePrepay)
            {
                //NOTE: ProvNum=0 on these splits, so I'm pretty sure they aren't allocated to anything.
                List <PaySplit> prePaySplits             = PaySplits.GetPrepayForFam(Patients.GetFamily(repeatCharge.PatNum));
                List <PaySplit> paySplitsForPrePaySplits = PaySplits.GetSplitsForPrepay(prePaySplits);
                Payment         payCur = new Payment();
                payCur.ClinicNum = procedure.ClinicNum;
                payCur.DateEntry = billingDate;
                payCur.IsSplit   = true;
                payCur.PatNum    = repeatCharge.PatNum;
                payCur.PayDate   = billingDate;
                payCur.PayType   = 0;           //Income transfer (will always be income transfer)
                payCur.PayAmt    = 0;           //Income transfer payment
                payCur.PayNum    = Payments.Insert(payCur);
                decimal payAmt   = 0;
                string  noteText = "";
                foreach (PaySplit prePaySplit in prePaySplits)
                {
                    prePaySplit.SplitAmt += paySplitsForPrePaySplits.Where(x => x.FSplitNum == prePaySplit.SplitNum).Sum(y => y.SplitAmt);                //Reduce prepay split amount.
                    PaySplit split  = new PaySplit();
                    PaySplit split2 = new PaySplit();
                    if (prePaySplit.SplitAmt > procedure.ProcFee - (double)payAmt)
                    {
                        //Split amount is more than the remainder of the procfee requires, use partial from split
                        split.SplitAmt  = procedure.ProcFee - (double)payAmt;
                        split2.SplitAmt = 0 - (procedure.ProcFee - (double)payAmt);
                        payAmt          = (decimal)procedure.ProcFee;
                    }
                    else
                    {
                        //Split amount is less than or equal to the remainder of the procfee
                        split.SplitAmt  = prePaySplit.SplitAmt;
                        split2.SplitAmt = 0 - prePaySplit.SplitAmt;
                        payAmt         += (decimal)prePaySplit.SplitAmt;
                    }
                    if (split.SplitAmt == 0)
                    {
                        continue;                        //Don't make splits for 0 amount.
                    }
                    //Positive split, attached to proc and for proc's prov and clinic
                    split.DateEntry = billingDate;
                    split.DatePay   = billingDate;
                    split.PatNum    = procedure.PatNum;
                    split.PayNum    = payCur.PayNum;
                    split.ProcNum   = procedure.ProcNum;
                    split.ProvNum   = procedure.ProvNum;
                    split.ClinicNum = procedure.ClinicNum;
                    if (noteText != "")
                    {
                        noteText += ", ";
                    }
                    noteText += split.SplitAmt.ToString("c");
                    PaySplits.Insert(split);
                    //Negative split, attached to prepay's prov and clinic, but not proc
                    split2.DateEntry = billingDate;
                    split2.DatePay   = billingDate;
                    split2.PatNum    = procedure.PatNum;
                    split2.PayNum    = payCur.PayNum;
                    split2.FSplitNum = prePaySplit.SplitNum;
                    split2.ProvNum   = prePaySplit.ProvNum;
                    split2.ClinicNum = prePaySplit.ClinicNum;
                    PaySplits.Insert(split2);
                    if (payAmt >= (decimal)procedure.ProcFee)
                    {
                        //Break out of loop
                        break;
                    }
                }
                payCur.PayNote = "Allocated " + noteText + " prepayments to repeating charge.";
                Payments.Update(payCur, false);
            }
            return(procedure);
        }
Ejemplo n.º 17
0
        ///<summary>Should only be called if ODHQ.</summary>
        private static List <Procedure> AddSmsRepeatingChargesHelper(DateTime dateRun)
        {
            //No remoting role check; no call to db
            DateTime          dateStart       = new DateTime(dateRun.AddMonths(-1).AddDays(-20).Year, dateRun.AddMonths(-1).AddDays(-20).Month, 1);
            DateTime          dateStop        = dateRun.AddDays(1);
            List <SmsBilling> listSmsBilling  = SmsBillings.GetByDateRange(dateStart, dateStop);
            List <Patient>    listPatients    = Patients.GetMultPats(listSmsBilling.Select(x => x.CustPatNum).Distinct().ToList()).ToList();    //local cache
            ProcedureCode     procCodeAccess  = ProcedureCodes.GetProcCode("038");
            ProcedureCode     procCodeUsage   = ProcedureCodes.GetProcCode("039");
            ProcedureCode     procCodeConfirm = ProcedureCodes.GetProcCode("040");
            List <Procedure>  listProcsAccess = Procedures.GetCompletedForDateRange(dateStart, dateStop, new List <long> {
                procCodeAccess.CodeNum
            });
            List <Procedure> listProcsUsage = Procedures.GetCompletedForDateRange(dateStart, dateStop, new List <long> {
                procCodeUsage.CodeNum
            });
            List <Procedure> listProcsConfirm = Procedures.GetCompletedForDateRange(dateStart, dateStop, new List <long> {
                procCodeConfirm.CodeNum
            });
            List <Procedure> retVal = new List <Procedure>();

            foreach (SmsBilling smsBilling in listSmsBilling)
            {
                Patient pat = listPatients.FirstOrDefault(x => x.PatNum == smsBilling.CustPatNum);
                if (pat == null)
                {
                    EServiceSignal eSignal = new EServiceSignal {
                        ServiceCode = (int)eServiceCode.IntegratedTexting,
                        SigDateTime = MiscData.GetNowDateTime(),
                        Severity    = eServiceSignalSeverity.Error,
                        Description = "Sms billing row found for non existent patient PatNum:" + smsBilling.CustPatNum
                    };
                    EServiceSignals.Insert(eSignal);
                    continue;
                }
                //Find the billing date based on the date usage.
                DateTime billingDate = smsBilling.DateUsage.AddMonths(1);              //we always bill the month after usage posts. Example: all January usage = 01/01/2015
                billingDate = new DateTime(
                    billingDate.Year,
                    billingDate.Month,
                    Math.Min(pat.BillingCycleDay, DateTime.DaysInMonth(billingDate.Year, billingDate.Month)));
                //example: dateUsage=08/01/2015, billing cycle date=8/14/2012, billing date should be 9/14/2015.
                if (billingDate > dateRun || billingDate < dateRun.AddMonths(-1).AddDays(-20))
                {
                    //One month and 20 day window. Bill regardless of presence of "038" repeat charge.
                    continue;
                }
                if (smsBilling.AccessChargeTotalUSD == 0 && smsBilling.MsgChargeTotalUSD == 0 && smsBilling.ConfirmationChargeTotalUSD == 0)
                {
                    //No charges so skip this customer.
                    continue;
                }
                //Only post confirmation charge if valid.
                if (smsBilling.ConfirmationChargeTotalUSD > 0 &&
                    (billingDate <= DateTime.Today || PrefC.GetBool(PrefName.FutureTransDatesAllowed) &&
                     !listProcsConfirm.Exists(x => x.PatNum == pat.PatNum && x.ProcDate.Year == billingDate.Year && x.ProcDate.Month == billingDate.Month)))
                {
                    //The calculated access charge was greater than 0 and there is not an existing "038" procedure on the account for that month.
                    Procedure procConfirm = new Procedure();
                    procConfirm.CodeNum        = procCodeConfirm.CodeNum;
                    procConfirm.DateEntryC     = DateTime.Today;
                    procConfirm.PatNum         = pat.PatNum;
                    procConfirm.ProcDate       = billingDate;
                    procConfirm.DateTP         = billingDate;
                    procConfirm.ProcFee        = smsBilling.ConfirmationChargeTotalUSD;
                    procConfirm.ProcStatus     = ProcStat.C;
                    procConfirm.ProvNum        = PrefC.GetLong(PrefName.PracticeDefaultProv);
                    procConfirm.MedicalCode    = procCodeConfirm.MedicalCode;
                    procConfirm.BaseUnits      = procCodeConfirm.BaseUnits;
                    procConfirm.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs);
                    procConfirm.BillingNote    = smsBilling.BillingDescConfirmation;
                    procConfirm.PlaceService   = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService);                //Default Proc Place of Service for the Practice is used.
                    Procedures.Insert(procConfirm);
                    listProcsConfirm.Add(procConfirm);
                    retVal.Add(procConfirm);
                }
                //Confirmation charges may wipe out access charges. We still want to see the $0 charge in this case so post this charge if either of the 2 are valid.
                if ((smsBilling.AccessChargeTotalUSD > 0 || smsBilling.ConfirmationChargeTotalUSD > 0) &&
                    (billingDate <= DateTime.Today || PrefC.GetBool(PrefName.FutureTransDatesAllowed)) &&
                    !listProcsAccess.Exists(x => x.PatNum == pat.PatNum && x.ProcDate.Year == billingDate.Year && x.ProcDate.Month == billingDate.Month))
                {
                    //The calculated access charge was greater than 0 and there is not an existing "038" procedure on the account for that month.
                    Procedure procAccess = new Procedure();
                    procAccess.CodeNum        = procCodeAccess.CodeNum;
                    procAccess.DateEntryC     = DateTime.Today;
                    procAccess.PatNum         = pat.PatNum;
                    procAccess.ProcDate       = billingDate;
                    procAccess.DateTP         = billingDate;
                    procAccess.ProcFee        = smsBilling.AccessChargeTotalUSD;
                    procAccess.ProcStatus     = ProcStat.C;
                    procAccess.ProvNum        = PrefC.GetLong(PrefName.PracticeDefaultProv);
                    procAccess.MedicalCode    = procCodeAccess.MedicalCode;
                    procAccess.BaseUnits      = procCodeAccess.BaseUnits;
                    procAccess.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs);
                    procAccess.BillingNote    = smsBilling.BillingDescSms;
                    procAccess.PlaceService   = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService);                //Default Proc Place of Service for the Practice is used.
                    Procedures.Insert(procAccess);
                    listProcsAccess.Add(procAccess);
                    retVal.Add(procAccess);
                }
                //Only post usage charge if valid.
                if (smsBilling.MsgChargeTotalUSD > 0 &&
                    (billingDate <= DateTime.Today || PrefC.GetBool(PrefName.FutureTransDatesAllowed)) &&
                    !listProcsUsage.Exists(x => x.PatNum == pat.PatNum && x.ProcDate.Year == billingDate.Year && x.ProcDate.Month == billingDate.Month))
                {
                    //Calculated Usage charge > 0 and not already billed, may exist without access charge
                    Procedure procUsage = new Procedure();
                    procUsage.CodeNum        = procCodeUsage.CodeNum;
                    procUsage.DateEntryC     = DateTime.Today;
                    procUsage.PatNum         = pat.PatNum;
                    procUsage.ProcDate       = billingDate;
                    procUsage.DateTP         = billingDate;
                    procUsage.ProcFee        = smsBilling.MsgChargeTotalUSD;
                    procUsage.ProcStatus     = ProcStat.C;
                    procUsage.ProvNum        = PrefC.GetLong(PrefName.PracticeDefaultProv);
                    procUsage.MedicalCode    = procCodeUsage.MedicalCode;
                    procUsage.BaseUnits      = procCodeUsage.BaseUnits;
                    procUsage.DiagnosticCode = PrefC.GetString(PrefName.ICD9DefaultForNewProcs);
                    procUsage.PlaceService   = (PlaceOfService)PrefC.GetInt(PrefName.DefaultProcedurePlaceService);                //Default Proc Place of Service for the Practice is used.
                    procUsage.BillingNote    = "Texting Usage charge for " + smsBilling.DateUsage.ToString("MMMM yyyy") + ".";
                    Procedures.Insert(procUsage);
                    listProcsUsage.Add(procUsage);
                    retVal.Add(procUsage);
                }
            }
            return(retVal);
        }
Ejemplo n.º 18
0
        ///<summary>Gets one EServiceSignalHQ from the serviceshq db located on SERVER184. Returns null in case of failure.</summary>
        public static EServiceMetrics GetEServiceMetricsFromSignalHQ()
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                return(Meth.GetObject <EServiceMetrics>(MethodBase.GetCurrentMethod()));
            }
            EServiceMetrics eServiceMetric = new EServiceMetrics();

            if (PrefC.ContainsKey("ServicesHqDoNotConnect") && PrefC.GetBool(PrefName.ServicesHqDoNotConnect))
            {
                eServiceMetric.ErrorMessage = "Not allowed to connect to the serviceshq database.";
                return(eServiceMetric);
            }
            string dbPassword;

            if (!CDT.Class1.Decrypt(PrefC.GetString(PrefName.ServicesHqMySqpPasswordObf), out dbPassword))
            {
                eServiceMetric.ErrorMessage = "Unable to decrypt serviceshq password";
                return(eServiceMetric);
            }
            try {
                DataAction.Run(() => {
                    //See EServiceSignalHQs.GetEServiceMetrics() for details.
                    string command = @"SELECT 0 EServiceSignalNum, h.* FROM eservicesignalhq h 
							WHERE h.ReasonCode=1024
								AND h.ReasonCategory=1
								AND h.ServiceCode=2
								AND h.RegistrationKeyNum=-1
							ORDER BY h.SigDateTime DESC 
							LIMIT 1"                            ;
                    EServiceSignal eServiceSignal = Crud.EServiceSignalCrud.SelectOne(command);
                    if (eServiceSignal != null)
                    {
                        using (XmlReader reader = XmlReader.Create(new System.IO.StringReader(eServiceSignal.Tag))) {
                            eServiceMetric = (EServiceMetrics) new XmlSerializer(typeof(EServiceMetrics)).Deserialize(reader);
                        }
                        eServiceMetric.IsValid = true;
                    }
                },
                               PrefC.GetString(PrefName.ServicesHqServer), PrefC.GetString(PrefName.ServicesHqDatabase), PrefC.GetString(PrefName.ServicesHqMySqlUser),
                               dbPassword, "", "", DatabaseType.MySql);
            }
            catch (Exception ex) {
                eServiceMetric.ErrorMessage = ex.Message;
            }
            return(eServiceMetric);
        }
Ejemplo n.º 19
0
        ///<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);
        }
Ejemplo n.º 20
0
        public static EmailMessage GetEmailMessageForPortalStatement(Statement stmt, Patient pat)
        {
            //No need to check RemotingRole; no call to db.
            if (stmt.PatNum != pat.PatNum)
            {
                string logMsg = Lans.g("Statements", "Mismatched PatNums detected between current patient and current statement:") + "\r\n"
                                + Lans.g("Statements", "Statement PatNum:") + " " + stmt.PatNum + " " + Lans.g("Statements", "(assumed correct)") + "\r\n"
                                + Lans.g("Statements", "Patient PatNum:") + " " + pat.PatNum + " " + Lans.g("Statements", "(possibly incorrect)");
                SecurityLogs.MakeLogEntry(Permissions.StatementPatNumMismatch, stmt.PatNum, logMsg, LogSources.Diagnostic);
            }
            EmailMessage message = new EmailMessage();

            message.PatNum      = pat.PatNum;
            message.ToAddress   = pat.Email;
            message.FromAddress = EmailAddresses.GetByClinic(pat.ClinicNum).GetFrom();
            string emailBody;

            if (stmt.EmailSubject != null && stmt.EmailSubject != "")
            {
                message.Subject = stmt.EmailSubject;
            }
            else              //Subject was not preset, set a default subject.
            {
                message.Subject = Lans.g("Statements", "New Statement Available");
            }
            if (stmt.EmailBody != null && stmt.EmailBody != "")
            {
                emailBody = stmt.EmailBody;
            }
            else              //Body was not preset, set a body text.
            {
                emailBody = Lans.g("Statements", "Dear") + " [nameFLnoPref],\r\n\r\n"
                            + Lans.g("Statements", "A new account statement is available.") + "\r\n\r\n"
                            + Lans.g("Statements", "To view your account statement, log on to our portal by following these steps:") + "\r\n\r\n"
                            + Lans.g("Statements", "1. Visit the following URL in a web browser:") + " " + PrefC.GetString(PrefName.PatientPortalURL) + ".\r\n"
                            + Lans.g("Statements", "2. Enter your credentials to gain access to your account.") + "\r\n"
                            + Lans.g("Statements", "3. Click the Account icon on the left and select the Statements tab.");
            }
            message.BodyText = Statements.ReplaceVarsForEmail(emailBody, pat, stmt);
            return(message);
        }
Ejemplo n.º 21
0
        ///<summary>Only called from Chart for now.  No validation is performed here.  Validate before calling.  There are many validtion checks, including the NPI must be exactly 10 digits.</summary>
        public static string BuildClickThroughXml(Provider prov, Employee emp, Patient pat)
        {
            NCScript ncScript = new NCScript();

            ncScript.Credentials                = new CredentialsType();
            ncScript.Credentials.partnerName    = NewCropPartnerName;
            ncScript.Credentials.name           = NewCropAccountName;
            ncScript.Credentials.password       = NewCropAccountPasssword;
            ncScript.Credentials.productName    = NewCropProductName;
            ncScript.Credentials.productVersion = NewCropProductVersion;
            ncScript.UserRole = new UserRoleType();
            if (emp == null)
            {
                ncScript.UserRole.user = UserType.LicensedPrescriber;
                ncScript.UserRole.role = RoleType.doctor;
            }
            else
            {
                ncScript.UserRole.user = UserType.Staff;
                ncScript.UserRole.role = RoleType.nurse;
            }
            ncScript.Destination = new DestinationType();
            ncScript.Destination.requestedPage = RequestedPageType.compose;                                //This is the tab that the user will want 90% of the time.
            string practiceTitle    = PrefC.GetString(PrefName.PracticeTitle);                             //May be blank.
            string practicePhone    = PrefC.GetString(PrefName.PracticePhone);                             //Validated to be 10 digits within the chart.
            string practiceFax      = PrefC.GetString(PrefName.PracticeFax);                               //Validated to be 10 digits within the chart.
            string practiceAddress  = PrefC.GetString(PrefName.PracticeAddress);                           //Validated to exist in chart.
            string practiceAddress2 = PrefC.GetString(PrefName.PracticeAddress2);                          //May be blank.
            string practiceCity     = PrefC.GetString(PrefName.PracticeCity);                              //Validated to exist in chart.
            string practiceState    = PrefC.GetString(PrefName.PracticeST);                                //Validated to be a US state code in chart.
            string practiceZip      = Regex.Replace(PrefC.GetString(PrefName.PracticeZip), "[^0-9]*", ""); //Zip with all non-numeric characters removed. Validated to be 9 digits in chart.
            string practiceZip4     = practiceZip.Substring(5);                                            //Last 4 digits of zip.

            practiceZip = practiceZip.Substring(0, 5);                                                     //First 5 digits of zip.
            string country = "US";                                                                         //Always United States for now.

            //if(CultureInfo.CurrentCulture.Name.Length>=2) {
            //  country=CultureInfo.CurrentCulture.Name.Substring(CultureInfo.CurrentCulture.Name.Length-2);
            //}
            ncScript.Account = new AccountTypeRx();
            //Each LicensedPrescriberID must be unique within an account. Since we send ProvNum for LicensedPrescriberID, each OD database must have a unique AccountID.
            ncScript.Account.ID                        = PrefC.GetString(PrefName.NewCropAccountId); //Customer account number then a dash then a random alpha-numeric string of 3 characters, followed by 2 digits.
            ncScript.Account.accountName               = practiceTitle;                              //May be blank.
            ncScript.Account.siteID                    = "1";                                        //Always send 1.  For each AccountID/SiteID pair, a separate database will be created in NewCrop.
            ncScript.Account.AccountAddress            = new AddressType();
            ncScript.Account.AccountAddress.address1   = practiceAddress;                            //Validated to exist in chart.
            ncScript.Account.AccountAddress.address2   = practiceAddress2;                           //May be blank.
            ncScript.Account.AccountAddress.city       = practiceCity;                               //Validated to exist in chart.
            ncScript.Account.AccountAddress.state      = practiceState;                              //Validated to be a US state code in chart.
            ncScript.Account.AccountAddress.zip        = practiceZip;                                //Validated to be 9 digits in chart. First 5 digits go in this field.
            ncScript.Account.AccountAddress.zip4       = practiceZip4;                               //Validated to be 9 digits in chart. Last 4 digits go in this field.
            ncScript.Account.AccountAddress.country    = country;                                    //Validated above.
            ncScript.Account.accountPrimaryPhoneNumber = practicePhone;                              //Validated to be 10 digits within the chart.
            ncScript.Account.accountPrimaryFaxNumber   = practiceFax;                                //Validated to be 10 digits within the chart.
            ncScript.Location = new LocationType();
            if (PrefC.GetBool(PrefName.EasyNoClinics) || pat.ClinicNum == 0)                         //No clinics.
            {
                ncScript.Location.ID                       = "0";                                    //Always 0, since clinicnums must be >= 1, will never overlap with a clinic if the office turns clinics on after first use.
                ncScript.Location.locationName             = practiceTitle;                          //May be blank.
                ncScript.Location.LocationAddress          = new AddressType();
                ncScript.Location.LocationAddress.address1 = practiceAddress;                        //Validated to exist in chart.
                ncScript.Location.LocationAddress.address2 = practiceAddress2;                       //May be blank.
                ncScript.Location.LocationAddress.city     = practiceCity;                           //Validated to exist in chart.
                ncScript.Location.LocationAddress.state    = practiceState;                          //Validated to be a US state code in chart.
                ncScript.Location.LocationAddress.zip      = practiceZip;                            //Validated to be 9 digits in chart. First 5 digits go in this field.
                ncScript.Location.LocationAddress.zip4     = practiceZip4;                           //Validated to be 9 digits in chart. Last 4 digits go in this field.
                ncScript.Location.LocationAddress.country  = country;                                //Validated above.
                ncScript.Location.primaryPhoneNumber       = practicePhone;                          //Validated to be 10 digits within the chart.
                ncScript.Location.primaryFaxNumber         = practiceFax;                            //Validated to be 10 digits within the chart.
                ncScript.Location.pharmacyContactNumber    = practicePhone;                          //Validated to be 10 digits within the chart.
            }
            else                                                                                     //Using clinics.
            {
                Clinic clinic = Clinics.GetClinic(pat.ClinicNum);
                ncScript.Location.ID                       = clinic.ClinicNum.ToString(); //A positive integer.
                ncScript.Location.locationName             = clinic.Description;          //May be blank.
                ncScript.Location.LocationAddress          = new AddressType();
                ncScript.Location.LocationAddress.address1 = clinic.Address;              //Validated to exist in chart.
                ncScript.Location.LocationAddress.address2 = clinic.Address2;             //May be blank.
                ncScript.Location.LocationAddress.city     = clinic.City;                 //Validated to exist in chart.
                ncScript.Location.LocationAddress.state    = clinic.State;                //Validated to be a US state code in chart.
                string clinicZip  = Regex.Replace(clinic.Zip, "[^0-9]*", "");             //Zip with all non-numeric characters removed. Validated to be 9 digits in chart.
                string clinicZip4 = clinicZip.Substring(5);                               //Last 4 digits of zip.
                clinicZip = clinicZip.Substring(0, 5);                                    //First 5 digits of zip.
                ncScript.Location.LocationAddress.zip     = clinicZip;                    //Validated to be 9 digits in chart. First 5 digits go in this field.
                ncScript.Location.LocationAddress.zip4    = clinicZip4;                   //Validated to be 9 digits in chart. Last 4 digits go in this field.
                ncScript.Location.LocationAddress.country = country;                      //Validated above.
                ncScript.Location.primaryPhoneNumber      = clinic.Phone;                 //Validated to be 10 digits within the chart.
                ncScript.Location.primaryFaxNumber        = clinic.Fax;                   //Validated to be 10 digits within the chart.
                ncScript.Location.pharmacyContactNumber   = clinic.Phone;                 //Validated to be 10 digits within the chart.
            }
            ncScript.LicensedPrescriber = new LicensedPrescriberType();
            //Each unique provider ID sent to NewCrop will cause a billing charge.
            //Some customer databases have provider duplicates, because they have one provider record per clinic with matching NPIs.
            //We send NPI as the ID to prevent extra NewCrop charges.
            //Conversation with NewCrop:
            //Question: If one of our customers clicks through to NewCrop with 2 different LicensedPrescriber.ID values,
            //          but with the same provider name and NPI, will Open Dental be billed twice or just one time for the NPI used?
            //Answer:   "They would be billed twice. The IDs you send us should always be maintained and unique.
            //          Users are always identified by LicensedPrescriber ID, since their name or credentials could potentially change."
            ncScript.LicensedPrescriber.ID = prov.NationalProvID;
            //UPIN is obsolete
            ncScript.LicensedPrescriber.LicensedPrescriberName        = new PersonNameType();
            ncScript.LicensedPrescriber.LicensedPrescriberName.last   = prov.LName.Trim();    //Cannot be blank.
            ncScript.LicensedPrescriber.LicensedPrescriberName.first  = prov.FName.Trim();    //Cannot be blank.
            ncScript.LicensedPrescriber.LicensedPrescriberName.middle = prov.MI;              //May be blank.
            ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.DDS; //There is no blank or none option, so we have to pick a default value. DDS=0, so would be default anyway.
            string[] suffixes = prov.Suffix.ToUpper().Split(' ', '.');
            for (int i = 0; i < suffixes.Length; i++)
            {
                if (suffixes[i] == "I")
                {
                    ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.I;
                    break;
                }
                else if (suffixes[i] == "II")
                {
                    ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.II;
                    break;
                }
                else if (suffixes[i] == "III")
                {
                    ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.III;
                    break;
                }
                else if (suffixes[i] == "JR")
                {
                    ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.Jr;
                    break;
                }
                else if (suffixes[i] == "SR")
                {
                    ncScript.LicensedPrescriber.LicensedPrescriberName.suffix = PersonNameSuffix.Sr;
                    break;
                }
            }
            if (prov.DEANum.ToLower() == "none")
            {
                ncScript.LicensedPrescriber.dea = "NONE";
            }
            else
            {
                ncScript.LicensedPrescriber.dea = prov.DEANum;
            }
            ncScript.LicensedPrescriber.licenseState  = prov.StateWhereLicensed; //Validated to be a US state code in the chart.
            ncScript.LicensedPrescriber.licenseNumber = prov.StateLicense;       //Validated to exist in chart.
            ncScript.LicensedPrescriber.npi           = prov.NationalProvID;     //Validated to be 10 digits in chart.
            //ncScript.LicensedPrescriber.freeformCredentials=;//This is where DDS and DMD should go, but we don't support this yet. Probably not necessary anyway.
            if (emp != null)
            {
                ncScript.Staff                  = new StaffType();
                ncScript.Staff.ID               = "emp" + emp.EmployeeNum.ToString(); //A positive integer. Returned in the ExternalUserID field when retreiving prescriptions from NewCrop. Also, provider ID is returned in the same field if a provider created the prescription, so that we can create a distintion between employee IDs and provider IDs.
                ncScript.Staff.StaffName        = new PersonNameType();
                ncScript.Staff.StaffName.first  = emp.FName;                          //First name or last name will not be blank. Validated in Chart.
                ncScript.Staff.StaffName.last   = emp.LName;                          //First name or last name will not be blank. Validated in Chart.
                ncScript.Staff.StaffName.middle = emp.MiddleI;                        //May be blank.
            }
            ncScript.Patient                     = new PatientType();
            ncScript.Patient.ID                  = pat.PatNum.ToString(); //A positive integer.
            ncScript.Patient.PatientName         = new PersonNameType();
            ncScript.Patient.PatientName.last    = pat.LName;             //Validated to exist in Patient Edit window.
            ncScript.Patient.PatientName.first   = pat.FName;             //May be blank.
            ncScript.Patient.PatientName.middle  = pat.MiddleI;           //May be blank.
            ncScript.Patient.medicalRecordNumber = pat.PatNum.ToString(); //A positive integer.
            //NewCrop specifically requested that we do not send SSN.
            //ncScript.Patient.socialSecurityNumber=Regex.Replace(pat.SSN,"[^0-9]*","");//Removes all non-numerical characters.
            ncScript.Patient.PatientAddress               = new AddressOptionalType();
            ncScript.Patient.PatientAddress.address1      = pat.Address;                        //May be blank.
            ncScript.Patient.PatientAddress.address2      = pat.Address2;                       //May be blank.
            ncScript.Patient.PatientAddress.city          = pat.City;                           //May be blank.
            ncScript.Patient.PatientAddress.state         = pat.State;                          //May be blank. Validated in chart to be blank or to be a valid US state code.
            ncScript.Patient.PatientAddress.zip           = pat.Zip;                            //May be blank.
            ncScript.Patient.PatientAddress.country       = country;                            //Validated above.
            ncScript.Patient.PatientContact               = new ContactType();
            ncScript.Patient.PatientContact.homeTelephone = pat.HmPhone;                        //May be blank. Does not need to be 10 digits.
            ncScript.Patient.PatientCharacteristics       = new PatientCharacteristicsType();
            ncScript.Patient.PatientCharacteristics.dob   = pat.Birthdate.ToString("yyyyMMdd"); //DOB must be in CCYYMMDD format.
            if (pat.Gender == PatientGender.Male)
            {
                ncScript.Patient.PatientCharacteristics.gender = GenderType.M;
            }
            else if (pat.Gender == PatientGender.Female)
            {
                ncScript.Patient.PatientCharacteristics.gender = GenderType.F;
            }
            else
            {
                ncScript.Patient.PatientCharacteristics.gender = GenderType.U;
            }
            ncScript.Patient.PatientCharacteristics.genderSpecified = true;
            //NewCrop programmer's comments regarding other fields we are not currently using (these fields are sent back when fetching prescriptions in the Chart):
            //ExternalPrescriptionId = your unique identifier for the prescription, only to be used if you are generating the prescription on your own UI.
            //	This is referenced by NewCrop, and cannot be populated with any other value.
            //EncounterIdentifier = unique ID for the patient visit (e.g. John Doe, 11/11/2013).
            //	This is used by NewCrop for reporting events against a visit, but otherwise does not impact the session.
            //EpisodeIdentifier = unique ID for the patient’s issue (e.g. John Doe’s broken leg) which may include multiple visits.
            //	Currently not used by NewCrop except for being echoed back; it is possible this functionality would be expanded in the future based on its intent as noted.
            //ExternalSource = a codified field noting the origin of the prescription. This may not be used.
            //Serialize
            MemoryStream  memoryStream  = new MemoryStream();
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(NCScript));

            xmlSerializer.Serialize(memoryStream, ncScript);
            byte[] memoryStreamInBytes = memoryStream.ToArray();
            return(Encoding.UTF8.GetString(memoryStreamInBytes, 0, memoryStreamInBytes.Length));
        }
Ejemplo n.º 22
0
 ///<summary>Attempts to retrieve OAuth authorization Url for Google.</summary>
 public static string GetGoogleAuthorizationUrl(string emailAddress)
 {
     try {
         string url = GetApiUrl(UrlEndpoint.Root);
         url += "?" + JsonConvert.DeserializeObject(
             WebServiceMainHQProxy.GetWebServiceMainHQInstance().BuildOAuthUrl(PrefC.GetString(PrefName.RegistrationKey), OAuthApplicationNames.Google.ToString()));
         url += "&login_hint=" + emailAddress;
         return(url);
     }
     catch (Exception ex) {
         throw new ApplicationException("Error occured retrieving Authorization Url: " + ex.Message);
     }
 }
Ejemplo n.º 23
0
        ///<summary>Gets the proc codes as a comma separated list from the preference and finds the corresponding code nums.</summary>
        private static List <long> GetCodeNumsForPref(PrefName pref)
        {
            List <string> listCodes = PrefC.GetString(pref).Split(',').ToList();

            return(GetWhereFromList(x => x.ProcCode.In(listCodes)).Select(x => x.CodeNum).ToList());
        }
Ejemplo n.º 24
0
        ///<summary>Generates a username and password if necessary for this patient. If the patient is not eligible to be given access, this will return null.
        ///Otherwise returns the UserWeb (Item1), PlainTextPassword (Item2), PasswordContainer (Item3).
        ///If PlainTextPassword (Item2) is empty then assume new password generation was not necessary.
        ///Will insert a new UserWeb if none found for this Patient. Will leave UserWeb.PasswordHash blank.
        ///Call UpdateNewPatientPortalCredentials() using results of this method if you want to save password to db.</summary>
        ///<param name="passwordOverride">If a password has already been generated for this patient, pass it in here so that the password returned
        ///will match.</param>
        public static Tuple <UserWeb, string, PasswordContainer> GetNewPatientPortalCredentials(Patient pat, string passwordOverride = "")
        {
            //No need to check RemotingRole; no call to db.
            if (string.IsNullOrEmpty(PrefC.GetString(PrefName.PatientPortalURL)))
            {
                return(null);               //Haven't set up patient portal yet.
            }
            string errors;

            if (!UserWebs.ValidatePatientAccess(pat, out errors))
            {
                return(null);               //Patient is missing necessary fields.
            }
            UserWeb userWeb = UserWebs.GetByFKeyAndType(pat.PatNum, UserWebFKeyType.PatientPortal);

            if (userWeb == null)
            {
                userWeb = new UserWeb()
                {
                    UserName = UserWebs.CreateUserNameFromPat(pat, UserWebFKeyType.PatientPortal, new List <string>()),
                    FKey     = pat.PatNum,
                    FKeyType = UserWebFKeyType.PatientPortal,
                    RequireUserNameChange = true,
                    LoginDetails          = new PasswordContainer(HashTypes.None, "", ""),
                    IsNew = true,
                };
                //Always insert here. We may not ever end up updating UserWeb.PasswordHash if an email is not sent to this patient.
                //This will leave a UserWeb row with a UserName (for next time) but no password. This row will be updated with a password at the appropriate time.
                UserWebs.Insert(userWeb);
            }
            bool isNewPasswordRequired = false;

            if (string.IsNullOrEmpty(userWeb.UserName))              //Fixing B11013 so new UserName and Password should be generated.
            {
                userWeb.UserName = UserWebs.CreateUserNameFromPat(pat, UserWebFKeyType.PatientPortal, new List <string>());
                userWeb.RequireUserNameChange = true;
                //UserName fields have been changed so update db.
                UserWebs.Update(userWeb);
                isNewPasswordRequired = true;
            }
            if (userWeb.RequirePasswordChange)              //Could be a new UserWeb or a subsequent invite being generated for the same patient (had a second appointment).
            {
                isNewPasswordRequired = true;
            }
            if (string.IsNullOrEmpty(userWeb.PasswordHash))              //Patient has no password so portal access has not been previously granted.
            {
                isNewPasswordRequired = true;
            }
            string            passwordPlainText = "";
            PasswordContainer loginDetails      = userWeb.LoginDetails;

            if (isNewPasswordRequired)
            {
                //PP invites will often times call this method and get this far but not actually want to save the new creds to the db.
                //For that reason we won't actually update the db with the new password here.
                //The caller of this method will need to call ProcessNewPatientPortalCredentialsOut() if they really want this new password to persist to the db.
                passwordPlainText = passwordOverride == "" ? UserWebs.GenerateRandomPassword(8) : passwordOverride;
                loginDetails      = Authentication.GenerateLoginDetails(passwordPlainText, HashTypes.SHA3_512);
            }
            return(new Tuple <UserWeb, string, PasswordContainer>(userWeb, passwordPlainText, loginDetails));
        }
Ejemplo n.º 25
0
        ///<summary>Used when viewing securityLog from the security admin window.  PermTypes can be length 0 to get all types.</summary>
        public static SecurityLog[] Refresh(DateTime dateFrom, DateTime dateTo, Permissions permType, long patNum, long userNum,
                                            DateTime datePreviousFrom, DateTime datePreviousTo, bool includeArchived, int limit = 0)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                return(Meth.GetObject <SecurityLog[]>(MethodBase.GetCurrentMethod(), dateFrom, dateTo, permType, patNum, userNum, datePreviousFrom, datePreviousTo, includeArchived, limit));
            }
            string command = "SELECT securitylog.*,LName,FName,Preferred,MiddleI,LogHash FROM securitylog "
                             + "LEFT JOIN patient ON patient.PatNum=securitylog.PatNum "
                             + "LEFT JOIN securityloghash ON securityloghash.SecurityLogNum=securitylog.SecurityLogNum "
                             + "WHERE LogDateTime >= " + POut.Date(dateFrom) + " "
                             + "AND LogDateTime <= " + POut.Date(dateTo.AddDays(1)) + " "
                             + "AND DateTPrevious >= " + POut.Date(datePreviousFrom) + " "
                             + "AND DateTPrevious <= " + POut.Date(datePreviousTo.AddDays(1));

            if (patNum != 0)
            {
                command += " AND securitylog.PatNum IN (" + string.Join(",",
                                                                        PatientLinks.GetPatNumsLinkedToRecursive(patNum, PatientLinkType.Merge).Select(x => POut.Long(x))) + ")";
            }
            if (permType != Permissions.None)
            {
                command += " AND PermType=" + POut.Long((int)permType);
            }
            if (userNum != 0)
            {
                command += " AND UserNum=" + POut.Long(userNum);
            }
            command += " ORDER BY LogDateTime DESC";          //Using DESC so that the most recent ones appear in the list
            if (limit > 0)
            {
                command = DbHelper.LimitOrderBy(command, limit);
            }
            DataTable          table    = Db.GetTable(command);
            List <SecurityLog> listLogs = Crud.SecurityLogCrud.TableToList(table);

            for (int i = 0; i < listLogs.Count; i++)
            {
                if (table.Rows[i]["PatNum"].ToString() == "0")
                {
                    listLogs[i].PatientName = "";
                }
                else
                {
                    listLogs[i].PatientName = table.Rows[i]["PatNum"].ToString() + "-"
                                              + Patients.GetNameLF(table.Rows[i]["LName"].ToString()
                                                                   , table.Rows[i]["FName"].ToString()
                                                                   , table.Rows[i]["Preferred"].ToString()
                                                                   , table.Rows[i]["MiddleI"].ToString());
                }
                listLogs[i].LogHash = table.Rows[i]["LogHash"].ToString();
            }
            if (includeArchived && dateFrom <= PrefC.GetDate(PrefName.ArchiveDate))           //They are attempting to find security logs that are prior to archived date.
            {
                string decryptedPass;
                CDT.Class1.Decrypt(PrefC.GetString(PrefName.ArchivePassHash), out decryptedPass);
                string         connectionStrOrig = DataConnection.GetCurrentConnectionString();
                DatabaseType   dbTypeOrig        = DataConnection.DBtype;
                DataConnection dcon = new DataConnection();
                //Connect to archive database
                dcon.SetDb(PrefC.GetString(PrefName.ArchiveServerName) == ""?PrefC.GetString(PrefName.ArchiveServerURI):PrefC.GetString(PrefName.ArchiveServerName),
                           "opendentalarchive", PrefC.GetString(PrefName.ArchiveUserName), decryptedPass, "", "", dbTypeOrig);
                DataTable          tableArchive    = Db.GetTable(command);  //Query the archive
                List <SecurityLog> listLogsArchive = Crud.SecurityLogCrud.TableToList(tableArchive);
                dcon.SetDb(connectionStrOrig, "", dbTypeOrig);              //Reconnect to initial db
                Dictionary <long, Patient> dictPats = Patients.GetMultPats(listLogsArchive.Select(x => x.PatNum).Distinct().ToList())
                                                      .ToDictionary(x => x.PatNum);
                for (int i = 0; i < listLogsArchive.Count; i++)
                {
                    Patient pat;
                    if (listLogsArchive[i].PatNum == 0 || !dictPats.TryGetValue(listLogsArchive[i].PatNum, out pat))
                    {
                        listLogsArchive[i].PatientName = "";
                    }
                    else
                    {
                        listLogsArchive[i].PatientName = listLogsArchive[i].PatNum + "-" + pat.GetNameLF();
                    }
                    listLogsArchive[i].LogHash = tableArchive.Rows[i]["LogHash"].ToString();
                }
                listLogs.AddRange(listLogsArchive);                //Add archived entries to returned list.
            }
            return(listLogs.OrderBy(x => x.LogDateTime).ToArray());
        }
Ejemplo n.º 26
0
        ///<summary>Used when viewing various audit trails of specific types.  This overload will return security logs for multiple objects (or fKeys).  Typically you will only need a specific type audit log for one type.  However, for things like ortho charts, each row (FK) in the database represents just one part of a larger ortho chart "object".  Thus, to get the full experience of a specific type audit trail window, we need to get security logs for multiple objects (FKs) that comprise the larger object (what the user sees).  Only implemented with ortho chart so far.  FKeys can be null.</summary>
        public static SecurityLog[] Refresh(long patNum, List <Permissions> permTypes, List <long> fKeys, bool includeArchived)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                return(Meth.GetObject <SecurityLog[]>(MethodBase.GetCurrentMethod(), patNum, permTypes, fKeys, includeArchived));
            }
            string types = "";

            for (int i = 0; i < permTypes.Count; i++)
            {
                if (i > 0)
                {
                    types += " OR";
                }
                types += " PermType=" + POut.Long((int)permTypes[i]);
            }
            string command = "SELECT * FROM securitylog "
                             + "WHERE (" + types + ") ";

            if (fKeys != null && fKeys.Count > 0)
            {
                command += "AND FKey IN (" + String.Join(",", fKeys) + ") ";
            }
            if (patNum != 0)           //appointments
            {
                command += " AND PatNum IN (" + string.Join(",",
                                                            PatientLinks.GetPatNumsLinkedToRecursive(patNum, PatientLinkType.Merge).Select(x => POut.Long(x))) + ")";
            }
            command += "ORDER BY LogDateTime";
            List <SecurityLog> listLogs = Crud.SecurityLogCrud.SelectMany(command);

            if (includeArchived)
            {
                string decryptedPass;
                CDT.Class1.Decrypt(PrefC.GetString(PrefName.ArchivePassHash), out decryptedPass);
                string         connectionStrOrig = DataConnection.GetCurrentConnectionString();
                DatabaseType   dbTypeOrig        = DataConnection.DBtype;
                DataConnection dcon = new DataConnection();
                //Connect to archive database
                dcon.SetDb(PrefC.GetString(PrefName.ArchiveServerName) == ""?PrefC.GetString(PrefName.ArchiveServerURI):PrefC.GetString(PrefName.ArchiveServerName),
                           "opendentalarchive", PrefC.GetString(PrefName.ArchiveUserName), decryptedPass, "", "", dbTypeOrig);
                listLogs.AddRange(Crud.SecurityLogCrud.SelectMany(command)); //Append results
                dcon.SetDb(connectionStrOrig, "", dbTypeOrig);               //Reconnect to initial db
            }
            return(listLogs.OrderBy(x => x.LogDateTime).ToArray());
        }
Ejemplo n.º 27
0
        ///<summary>In progress.  Probably needs a different name.  Info must be validated first.
        ///Set dependent to the currently selected patient, compares dependent.PatNum to subscriber.PatNum to either contruct a subscriber based or dependent based benefit request.</summary>
        public static string GenerateMessageText(Clearinghouse clearinghouseClin, Carrier carrier, Provider billProv, Clinic clinic, InsPlan insPlan, Patient subscriber, InsSub insSub, Patient patForRequest)
        {
            bool          isSubscriberRequest = (subscriber.PatNum == patForRequest.PatNum);
            int           batchNum            = Clearinghouses.GetNextBatchNumber(clearinghouseClin);
            string        groupControlNumber  = batchNum.ToString();  //Must be unique within file.  We will use batchNum
            int           transactionNum      = 1;
            StringBuilder strb = new StringBuilder();

            //Interchange Control Header
            strb.Append("ISA*00*          *");            //ISA01,ISA02: 00 + 10 spaces
            if (IsEmdeonDental(clearinghouseClin))
            {
                strb.Append("00*" + Sout(clearinghouseClin.Password, 10, 10) + "*"   //ISA03,ISA04: 00 + emdeon password padded to 10 characters
                            + clearinghouseClin.ISA05 + "*"                          //ISA05: Sender ID type: ZZ=mutually defined. 30=TIN. Validated
                            + "316:" + Sout(clearinghouseClin.LoginID, 11, 11) + "*" //ISA06: Emdeon vendor number + username
                            + clearinghouseClin.ISA07 + "*"                          //ISA07: Receiver ID type: ZZ=mutually defined. 30=TIN. Validated
                            + Sout("EMDEONDENTAL", 15, 15) + "*");                   //ISA08: Receiver ID. Validated to make sure length is at least 2.
            }
            else
            {
                strb.Append("00*          *"                                 //ISA03,ISA04: 00 + 10 spaces
                            + clearinghouseClin.ISA05 + "*"                  //ISA05: Sender ID type: ZZ=mutually defined. 30=TIN. Validated
                            + X12Generator.GetISA06(clearinghouseClin) + "*" //ISA06: Sender ID(TIN). Or might be TIN of Open Dental
                            + clearinghouseClin.ISA07 + "*"                  //ISA07: Receiver ID type: ZZ=mutually defined. 30=TIN. Validated
                            + Sout(clearinghouseClin.ISA08, 15, 15) + "*");  //ISA08: Receiver ID. Validated to make sure length is at least 2.
            }
            strb.AppendLine(DateTime.Today.ToString("yyMMdd") + "*"          //ISA09: today's date
                            + DateTime.Now.ToString("HHmm") + "*"            //ISA10: current time
                            + "U*00401*"                                     //ISA11 and ISA12.
                                                                             //ISA13: interchange control number, right aligned:
                            + batchNum.ToString().PadLeft(9, '0') + "*"
                            + "0*"                                           //ISA14: no acknowledgment requested
                            + clearinghouseClin.ISA15 + "*"                  //ISA15: T=Test P=Production. Validated.
                            + ":~");                                         //ISA16: use ':'
            //Functional Group Header
            if (IsEmdeonDental(clearinghouseClin))
            {
                strb.Append("GS*HS*"                                        //GS01: HS for 270 benefit inquiry
                            + X12Generator.GetGS02(clearinghouseClin) + "*" //GS02: Senders Code. Sometimes Jordan Sparks.  Sometimes the sending clinic.
                            + Sout("EMDEONDENTAL", 15, 15) + "*");          //GS03: Application Receiver's Code
            }
            else
            {
                strb.Append("GS*HS*"                                        //GS01: HS for 270 benefit inquiry
                            + X12Generator.GetGS02(clearinghouseClin) + "*" //GS02: Senders Code. Sometimes Jordan Sparks.  Sometimes the sending clinic.
                            + Sout(clearinghouseClin.GS03, 15, 2) + "*");   //GS03: Application Receiver's Code
            }
            strb.AppendLine(DateTime.Today.ToString("yyyyMMdd") + "*"       //GS04: today's date
                            + DateTime.Now.ToString("HHmm") + "*"           //GS05: current time
                            + groupControlNumber + "*"                      //GS06: Group control number. Max length 9. No padding necessary.
                            + "X*"                                          //GS07: X
                            + "004010X092~");                               //GS08: Version
            //Beginning of transaction--------------------------------------------------------------------------------
            int seg = 0;                                                    //count segments for the ST-SE transaction

            //Transaction Set Header
            //ST02 Transact. control #. Must be unique within ISA
            seg++;
            strb.AppendLine("ST*270*"                                           //ST01
                            + transactionNum.ToString().PadLeft(4, '0') + "~"); //ST02
            seg++;
            strb.AppendLine("BHT*0022*13*"                                      //BHT02: 13=request
                            + transactionNum.ToString().PadLeft(4, '0') + "*"   //BHT03. Can be same as ST02
                            + DateTime.Now.ToString("yyyyMMdd") + "*"           //BHT04: Date
                            + DateTime.Now.ToString("HHmmss") + "~");           //BHT05: Time, BHT06: not used
            //HL Loops-----------------------------------------------------------------------------------------------
            int HLcount = 1;

            //2000A HL: Information Source--------------------------------------------------------------------------
            seg++;
            strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID.  Here, it's always 1.
                            + "*"                            //HL02: No parent. Not used
                            + "20*"                          //HL03: Heirarchical level code. 20=Information source
                            + "1~");                         //HL04: Heirarchical child code. 1=child HL present
            //2100A NM1
            seg++;
            strb.AppendLine("NM1*PR*"                              //NM101: PR=Payer
                            + "2*"                                 //NM102: 2=Non person
                            + Sout(carrier.CarrierName, 35) + "*"  //NM103: Name Last.
                            + "****"                               //NM104-07 not used
                            + "PI*"                                //NM108: PI=PayorID
                            + Sout(carrier.ElectID, 80, 2) + "~"); //NM109: PayorID. Validated to be at least length of 2.
            HLcount++;
            //2000B HL: Information Receiver------------------------------------------------------------------------
            seg++;
            strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID.  Here, it's always 2.
                            + "1*"                           //HL02: Heirarchical parent id number.  1 in this simple message.
                            + "21*"                          //HL03: Heirarchical level code. 21=Information receiver
                            + "1~");                         //HL04: Heirarchical child code. 1=child HL present
            seg++;
            //2100B NM1: Information Receiver Name
            strb.AppendLine("NM1*1P*"                                   //NM101: 1P=Provider
                            + (billProv.IsNotPerson?"2":"1") + "*"      //NM102: 1=person,2=non-person
                            + Sout(billProv.LName, 35) + "*"            //NM103: Last name
                            + Sout(billProv.FName, 25) + "*"            //NM104: First name
                            + Sout(billProv.MI, 25, 1) + "*"            //NM105: Middle name
                            + "*"                                       //NM106: not used
                            + "*"                                       //NM107: Name suffix. not used
                            + "XX*"                                     //NM108: ID code qualifier. 24=EIN. 34=SSN, XX=NPI
                            + Sout(billProv.NationalProvID, 80) + "~"); //NM109: ID code. NPI validated
            //2100B REF: Information Receiver ID
            if (IsEmdeonDental(clearinghouseClin) && IsDentiCalCarrier(carrier))
            {
                string        ref4aSegment            = "";
                Clearinghouse clearinghouseDentiCalHQ = Clearinghouses.GetFirstOrDefault(x => IsDentiCalClearinghouse(x), true);
                if (clearinghouseDentiCalHQ != null)
                {
                    Clearinghouse clearinghouseDentiCalClin = Clearinghouses.OverrideFields(clearinghouseDentiCalHQ, clearinghouseClin.ClinicNum);
                    if (clearinghouseDentiCalClin != null)
                    {
                        ref4aSegment = clearinghouseDentiCalClin.Password;
                    }
                }
                seg++;
                strb.Append("REF*4A*" + ref4aSegment + "~");
            }
            seg++;
            strb.Append("REF*");
            if (billProv.UsingTIN)
            {
                strb.Append("TJ*");                        //REF01: qualifier. TJ=Federal TIN
            }
            else                                           //SSN
            {
                strb.Append("SY*");                        //REF01: qualifier. SY=SSN
            }
            strb.AppendLine(Sout(billProv.SSN, 30) + "~"); //REF02: ID
            //2100B N3: Information Receiver Address
            seg++;
            if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims))
            {
                strb.Append("N3*" + Sout(PrefC.GetString(PrefName.PracticeBillingAddress), 55));             //N301: Address
            }
            else if (clinic == null)
            {
                strb.Append("N3*" + Sout(PrefC.GetString(PrefName.PracticeAddress), 55));             //N301: Address
            }
            else
            {
                strb.Append("N3*" + Sout(clinic.Address, 55));             //N301: Address
            }
            if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims))
            {
                if (PrefC.GetString(PrefName.PracticeBillingAddress2) == "")
                {
                    strb.AppendLine("~");
                }
                else
                {
                    //N302: Address2. Optional.
                    strb.AppendLine("*" + Sout(PrefC.GetString(PrefName.PracticeBillingAddress2), 55) + "~");
                }
            }
            else if (clinic == null)
            {
                if (PrefC.GetString(PrefName.PracticeAddress2) == "")
                {
                    strb.AppendLine("~");
                }
                else
                {
                    //N302: Address2. Optional.
                    strb.AppendLine("*" + Sout(PrefC.GetString(PrefName.PracticeAddress2), 55) + "~");
                }
            }
            else
            {
                if (clinic.Address2 == "")
                {
                    strb.AppendLine("~");
                }
                else
                {
                    //N302: Address2. Optional.
                    strb.AppendLine("*" + Sout(clinic.Address2, 55) + "~");
                }
            }
            //2100B N4: Information Receiver City/State/Zip
            seg++;
            if (PrefC.GetBool(PrefName.UseBillingAddressOnClaims))
            {
                strb.AppendLine("N4*" + Sout(PrefC.GetString(PrefName.PracticeBillingCity), 30) + "*"             //N401: City
                                + Sout(PrefC.GetString(PrefName.PracticeBillingST), 2) + "*"                      //N402: State
                                + Sout(PrefC.GetString(PrefName.PracticeBillingZip).Replace("-", ""), 15) + "~"); //N403: Zip
            }
            else if (clinic == null)
            {
                strb.AppendLine("N4*" + Sout(PrefC.GetString(PrefName.PracticeCity), 30) + "*"             //N401: City
                                + Sout(PrefC.GetString(PrefName.PracticeST), 2) + "*"                      //N402: State
                                + Sout(PrefC.GetString(PrefName.PracticeZip).Replace("-", ""), 15) + "~"); //N403: Zip
            }
            else
            {
                strb.AppendLine("N4*" + Sout(clinic.City, 30) + "*"             //N401: City
                                + Sout(clinic.State, 2) + "*"                   //N402: State
                                + Sout(clinic.Zip.Replace("-", ""), 15) + "~"); //N403: Zip
            }
            //2100B PRV: Information Receiver Provider Info
            seg++;
            //PRV*PE*ZZ*1223G0001X~
            strb.AppendLine("PRV*PE*"                                    //PRV01: Provider Code. PE=Performing.  There are many other choices.
                            + "ZZ*"                                      //PRV02: ZZ=Mutually defined = health care provider taxonomy code
                            + X12Generator.GetTaxonomy(billProv) + "~"); //PRV03: Specialty code
            HLcount++;
            //2000C HL: Subscriber-----------------------------------------------------------------------------------
            seg++;
            strb.AppendLine("HL*" + HLcount.ToString() + "*"    //HL01: Heirarchical ID.  Here, it's always 3.
                            + "2*"                              //HL02: Heirarchical parent id number.  2 in this simple message.
                            + "22*"                             //HL03: Heirarchical level code. 22=Subscriber
                            + (isSubscriberRequest?"0~":"1~")); //HL04: Heirarchical child code. 0=no child HL present (no dependent) else 1
            //2000C TRN: Subscriber Trace Number
            seg++;
            strb.AppendLine("TRN*1*"                     //TRN01: Trace Type Code.  1=Current Transaction Trace Numbers
                            + "1*"                       //TRN02: Trace Number.  We don't really have a good primary key yet.  Keep it simple. Use 1.
                            + "1" + billProv.SSN + "~"); //TRN03: Entity Identifier. First digit is 1=EIN.  Next 9 digits are EIN.  Length validated.
            //2100C NM1: Subscriber Name
            seg++;
            strb.AppendLine("NM1*IL*"                                                //NM101: IL=Insured or Subscriber
                            + "1*"                                                   //NM102: 1=Person
                            + Sout(subscriber.LName, 35) + "*"                       //NM103: LName
                            + Sout(subscriber.FName, 25) + "*"                       //NM104: FName
                            + Sout(subscriber.MiddleI, 25) + "*"                     //NM105: MiddleName
                            + "*"                                                    //NM106: not used
                            + "*"                                                    //NM107: suffix. Not present in Open Dental yet.
                            + "MI*"                                                  //NM108: MI=MemberID
                            + Sout(insSub.SubscriberID.Replace("-", ""), 80) + "~"); //NM109: Subscriber ID. Validated to be L>2.
            //2100C REF: Subscriber Additional Information.  Without this, old plans seem to be frequently returned.
            seg++;
            strb.AppendLine("REF*6P*"                            //REF01: 6P=GroupNumber
                            + Sout(insPlan.GroupNum, 30) + "~"); //REF02: Supplemental ID. Validated.
            //2100C DMG: Subscriber Demographic Information
            seg++;
            strb.AppendLine("DMG*D8*"                                           //DMG01: Date Time Period Qualifier.  D8=CCYYMMDD
                            + subscriber.Birthdate.ToString("yyyyMMdd") + "~"); //DMG02: Subscriber birthdate.  Validated
            //DMG03: Gender code.  Situational.  F or M.  Since this was left out in the example,
            //and since we don't want to send the wrong gender, we will not send this element.
            //2100C DTP: Subscriber Date.  Deduced through trial and error that this is required by EHG even though not by X12 specs.
            seg++;
            strb.AppendLine("DTP*307*"                                    //DTP01: Qualifier.  307=Eligibility
                            + "D8*"                                       //DTP02: Format Qualifier.
                            + DateTime.Today.ToString("yyyyMMdd") + "~"); //DTP03: Date
            //2000D HL: Dependent Level Hierarchical Level
            if (isSubscriberRequest)
            {
                //2110C EQ: Subscriber Eligibility or Benefit Enquiry Information
                //X12 documentation seems to say that we can loop this 99 times to request very specific benefits.
                //ClaimConnect wants to see either an EQ*30 for "an eligibility request", or an EQ*35 for "a general benefits request".
                //The director of vendor implementation at ClaimConnect has informed us that we should send an EQ*35 to get the full set of benefits.
                seg++;
                strb.AppendLine("EQ*35~"); //Dental Care
            }
            else                           //Dependent based request.
            {
                HLcount++;
                seg++;
                strb.AppendLine("HL*" + HLcount.ToString() + "*" //HL01: Heirarchical ID.
                                + (HLcount - 1).ToString() + "*" //HL02: Heirarchical parent id number.
                                + "23*"                          //HL03: Heirarchical level code. 23=Dependent
                                + "0~");                         //HL04: Heirarchical child code. 0=no child HL present (no dependent)
                //2000D TRN: Dependent Trace Number
                seg++;
                strb.AppendLine("TRN*1*"                     //TRN01: Trace Type Code.  1=Current Transaction Trace Numbers
                                + "1*"                       //TRN02: Trace Number.  We don't really have a good primary key yet.  Keep it simple. Use 1.
                                + "1" + billProv.SSN + "~"); //TRN03: Entity Identifier. First digit is 1=EIN.  Next 9 digits are EIN.  Length validated.
                //2100D NM1: Dependent Name
                seg++;
                strb.AppendLine("NM1*03*"                                 //NM101: 03=Dependent
                                + "1*"                                    //NM102: 1=Person
                                + Sout(patForRequest.LName, 35) + "*"     //NM103: Name Last or Organization Name
                                + Sout(patForRequest.FName, 25) + "*"     //NM104: Name First
                                + Sout(patForRequest.MiddleI, 25) + "~"); //NM105: Name Middle
                //2100D REF: Dependent Additional Identification
                seg++;
                strb.AppendLine("REF*6P*"                            //REF01: 6P=GroupNumber
                                + Sout(insPlan.GroupNum, 30) + "~"); //REF02: Supplemental ID. Validated.
                //2100D DMG: Dependent Demographic Information
                seg++;
                strb.AppendLine("DMG*D8*"                                              //DMG01: Date Time Period Qualifier.  D8=CCYYMMDD
                                + patForRequest.Birthdate.ToString("yyyyMMdd") + "~"); //DMG02: Dependent birthdate.  Validated
                //DMG03: Gender code.  Situational.  F or M.  Since this was left out in the example,
                //and since we don't want to send the wrong gender, we will not send this element.
                //2100D DTP: DEPENDENT Date.  Deduced through trial and error that this is required by EHG even though not by X12 specs.
                seg++;
                strb.AppendLine("DTP*307*"                                    //DTP01: Qualifier.  307=Eligibility
                                + "D8*"                                       //DTP02: Format Qualifier.
                                + DateTime.Today.ToString("yyyyMMdd") + "~"); //DTP03: Date
                seg++;
                strb.AppendLine("EQ*35~");                                    //Dental Care
            }
            //Transaction Trailer
            seg++;
            strb.AppendLine("SE*"
                            + seg.ToString() + "*" //SE01: Total segments, including ST & SE
                            + transactionNum.ToString().PadLeft(4, '0') + "~");
            //End of transaction--------------------------------------------------------------------------------------
            //Functional Group Trailer
            strb.AppendLine("GE*" + transactionNum.ToString() + "*"       //GE01: Number of transaction sets included
                            + groupControlNumber + "~");                  //GE02: Group Control number. Must be identical to GS06
            //Interchange Control Trailer
            strb.AppendLine("IEA*1*"                                      //IEA01: number of functional groups
                            + batchNum.ToString().PadLeft(9, '0') + "~"); //IEA02: Interchange control number
            return(strb.ToString());

            /*
             * return @"
             * ISA*00*          *00*          *30*AA0989922      *30*330989922      *030519*1608*U*00401*000012145*1*T*:~
             * GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~
             * ST*270*0001~
             * BHT*0022*13*ASX012145WEB*20030519*1608~
             * HL*1**20*1~
             * NM1*PR*2*Metlife*****PI*65978~
             * HL*2*1*21*1~
             * NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~
             * REF*TJ*200384584~
             * N3*JUNIT ROAD~
             * N4*CHICAGO*IL*60602~
             * PRV*PE*ZZ*1223G0001X~
             * HL*3*2*22*0~
             * TRN*1*12145*1AA0989922~
             * NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~
             * DMG*D8*19750323~
             * DTP*307*D8*20030519~
             * EQ*30~
             * SE*17*0001~
             * GE*1*12145~
             * IEA*1*000012145~";
             */

            //return "ISA*00*          *00*          *30*AA0989922      *30*330989922      *030519*1608*U*00401*000012145*1*T*:~GS*HS*AA0989922*330989922*20030519*1608*12145*X*004010X092~ST*270*0001~BHT*0022*13*ASX012145WEB*20030519*1608~HL*1**20*1~NM1*PR*2*Metlife*****PI*65978~HL*2*1*21*1~NM1*1P*1*PROVLAST*PROVFIRST****XX*1234567893~REF*TJ*200384584~N3*JUNIT ROAD~N4*CHICAGO*IL*60602~PRV*PE*ZZ*1223G0001X~HL*3*2*22*0~TRN*1*12145*1AA0989922~NM1*IL*1*SUBLASTNAME*SUBFIRSTNAME****MI*123456789~DMG*D8*19750323~DTP*307*D8*20030519~EQ*30~SE*17*0001~GE*1*12145~IEA*1*000012145~";
        }
Ejemplo n.º 28
0
 ///<summary>Get an instance of OpenDentBusiness.localhost.Service1 (referred to as 'Customer Updates Web Service'.
 ///Also sets IWebProxy and ICredentials if specified for this customer.  Service1 is ready to use on return.</summary>
 public static localhost.Service1 GetWebServiceInstance()
 {
     localhost.Service1 ws = new localhost.Service1();          //Points to the debug localhost instance by default.
     if (!ODBuild.IsDebug())
     {
         ws.Url     = PrefC.GetString(PrefName.UpdateServerAddress);
         ws.Timeout = (int)TimeSpan.FromMinutes(20).TotalMilliseconds;
     }
     if (PrefC.GetString(PrefName.UpdateWebProxyAddress) != "")
     {
         IWebProxy    proxy = new WebProxy(PrefC.GetString(PrefName.UpdateWebProxyAddress));
         ICredentials cred  = new NetworkCredential(PrefC.GetString(PrefName.UpdateWebProxyUserName), PrefC.GetString(PrefName.UpdateWebProxyPassword));
         proxy.Credentials = cred;
         ws.Proxy          = proxy;
     }
     return(ws);
 }
Ejemplo n.º 29
0
        ///<summary>Only called from Chart for now.  No validation is performed here.  Validate before calling.  There are many validtion checks, including the NPI must be exactly 10 digits.</summary>
        public static string BuildNewCropClickThroughXml(Provider prov, Employee emp, Patient pat)
        {
            string   deaNumDefault = ProviderClinics.GetDEANum(prov.ProvNum);
            NCScript ncScript      = new NCScript();

            ncScript.Credentials                = new CredentialsType();
            ncScript.Credentials.partnerName    = NewCrop.NewCropPartnerName;
            ncScript.Credentials.name           = NewCrop.NewCropAccountName;
            ncScript.Credentials.password       = NewCrop.NewCropAccountPasssword;
            ncScript.Credentials.productName    = NewCrop.NewCropProductName;
            ncScript.Credentials.productVersion = NewCrop.NewCropProductVersion;
            ncScript.UserRole = new UserRoleType();
            bool isMidlevel = false;

            if (emp == null)           //Provider
            {
                if (prov.IsSecondary)  //Mid-level provider
                {
                    isMidlevel = true;
                    //Secondary (HYG) providers go accross to NewCrop as midlevel providers for now to satisfy the Ohio prescriber requirements.
                    //HYG providers are not normally able to click through to NewCrop because they do not have an NPI number and an NPI is required.
                    //In the future, instead of using the IsSecondary flag as as workaround, we should instead create a new field on the provider table
                    //or perhaps the userod table to allow the user to select the type of provider.
                    ncScript.UserRole.user = UserType.MidlevelPrescriber;
                    ncScript.UserRole.role = RoleType.midlevelPrescriber;
                }
                else                  //Fully licensed provider
                {
                    ncScript.UserRole.user = UserType.LicensedPrescriber;
                    ncScript.UserRole.role = RoleType.doctor;
                }
            }
            else              //Employee
            {
                ncScript.UserRole.user = UserType.Staff;
                ncScript.UserRole.role = RoleType.nurse;
            }
            ncScript.Destination = new DestinationType();
            ncScript.Destination.requestedPage = RequestedPageType.compose;                                //This is the tab that the user will want 90% of the time.
            string practiceTitle    = Tidy(PrefC.GetString(PrefName.PracticeTitle), 50);                   //May be blank.
            string practicePhone    = PrefC.GetString(PrefName.PracticePhone);                             //Validated to be 10 digits within the chart.
            string practiceFax      = PrefC.GetString(PrefName.PracticeFax);                               //Validated to be 10 digits within the chart.
            string practiceAddress  = PrefC.GetString(PrefName.PracticeAddress);                           //Validated to exist in chart.
            string practiceAddress2 = PrefC.GetString(PrefName.PracticeAddress2);                          //May be blank.
            string practiceCity     = PrefC.GetString(PrefName.PracticeCity);                              //Validated to exist in chart.
            string practiceState    = PrefC.GetString(PrefName.PracticeST).ToUpper();                      //Validated to be a US state code in chart.
            string practiceZip      = Regex.Replace(PrefC.GetString(PrefName.PracticeZip), "[^0-9]*", ""); //Zip with all non-numeric characters removed. Validated to be 9 digits in chart.
            string practiceZip4     = practiceZip.Substring(5);                                            //Last 4 digits of zip.

            practiceZip = practiceZip.Substring(0, 5);                                                     //First 5 digits of zip.
            string country = "US";                                                                         //Always United States for now.

            //if(CultureInfo.CurrentCulture.Name.Length>=2) {
            //  country=CultureInfo.CurrentCulture.Name.Substring(CultureInfo.CurrentCulture.Name.Length-2);
            //}
            ncScript.Account = new AccountTypeRx();
            //Each LicensedPrescriberID must be unique within an account. Since we send ProvNum for LicensedPrescriberID, each OD database must have a unique AccountID.
            ncScript.Account.ID                        = PrefC.GetString(PrefName.NewCropAccountId); //Customer account number then a dash then a random alpha-numeric string of 3 characters, followed by 2 digits.
            ncScript.Account.accountName               = practiceTitle;                              //May be blank.
            ncScript.Account.siteID                    = "1";                                        //Always send 1.  For each AccountID/SiteID pair, a separate database will be created in NewCrop.
            ncScript.Account.AccountAddress            = new AddressType();
            ncScript.Account.AccountAddress.address1   = practiceAddress;                            //Validated to exist in chart.
            ncScript.Account.AccountAddress.address2   = practiceAddress2;                           //May be blank.
            ncScript.Account.AccountAddress.city       = practiceCity;                               //Validated to exist in chart.
            ncScript.Account.AccountAddress.state      = practiceState;                              //Validated to be a US state code in chart.
            ncScript.Account.AccountAddress.zip        = practiceZip;                                //Validated to be 9 digits in chart. First 5 digits go in this field.
            ncScript.Account.AccountAddress.zip4       = practiceZip4;                               //Validated to be 9 digits in chart. Last 4 digits go in this field.
            ncScript.Account.AccountAddress.country    = country;                                    //Validated above.
            ncScript.Account.accountPrimaryPhoneNumber = practicePhone;                              //Validated to be 10 digits within the chart.
            ncScript.Account.accountPrimaryFaxNumber   = practiceFax;                                //Validated to be 10 digits within the chart.
            ncScript.Location = new LocationType();
            ProviderClinic provClinic = null;

            if (PrefC.GetBool(PrefName.EasyNoClinics) ||
                (!PrefC.GetBool(PrefName.ElectronicRxClinicUseSelected) && pat.ClinicNum == 0) ||
                (PrefC.GetBool(PrefName.ElectronicRxClinicUseSelected) && Clinics.ClinicNum == 0 && pat.ClinicNum == 0))
            {                                                                  //No clinic.
                ncScript.Location.ID                       = "0";              //Always 0, since clinicnums must be >= 1, will never overlap with a clinic if the office turns clinics on after first use.
                ncScript.Location.locationName             = practiceTitle;    //May be blank.
                ncScript.Location.LocationAddress          = new AddressType();
                ncScript.Location.LocationAddress.address1 = practiceAddress;  //Validated to exist in chart.
                ncScript.Location.LocationAddress.address2 = practiceAddress2; //May be blank.
                ncScript.Location.LocationAddress.city     = practiceCity;     //Validated to exist in chart.
                ncScript.Location.LocationAddress.state    = practiceState;    //Validated to be a US state code in chart.
                ncScript.Location.LocationAddress.zip      = practiceZip;      //Validated to be 9 digits in chart. First 5 digits go in this field.
                ncScript.Location.LocationAddress.zip4     = practiceZip4;     //Validated to be 9 digits in chart. Last 4 digits go in this field.
                ncScript.Location.LocationAddress.country  = country;          //Validated above.
                ncScript.Location.primaryPhoneNumber       = practicePhone;    //Validated to be 10 digits within the chart.
                ncScript.Location.primaryFaxNumber         = practiceFax;      //Validated to be 10 digits within the chart.
                ncScript.Location.pharmacyContactNumber    = practicePhone;    //Validated to be 10 digits within the chart.
            }
            else                                                               //Using clinics.
            {
                Clinic clinic = null;
                if (PrefC.GetBool(PrefName.ElectronicRxClinicUseSelected) && Clinics.ClinicNum != 0)
                {
                    clinic = Clinics.GetClinic(Clinics.ClinicNum);
                }
                else
                {
                    clinic = Clinics.GetClinic(pat.ClinicNum);
                }
                provClinic                                 = ProviderClinics.GetOne(prov.ProvNum, clinic.ClinicNum);
                ncScript.Location.ID                       = clinic.ClinicNum.ToString(); //A positive integer.
                ncScript.Location.locationName             = clinic.Description;          //May be blank.
                ncScript.Location.LocationAddress          = new AddressType();
                ncScript.Location.LocationAddress.address1 = clinic.Address;              //Validated to exist in chart.
                ncScript.Location.LocationAddress.address2 = clinic.Address2;             //May be blank.
                ncScript.Location.LocationAddress.city     = clinic.City;                 //Validated to exist in chart.
                ncScript.Location.LocationAddress.state    = clinic.State.ToUpper();      //Validated to be a US state code in chart.
                string clinicZip  = Regex.Replace(clinic.Zip, "[^0-9]*", "");             //Zip with all non-numeric characters removed. Validated to be 9 digits in chart.
                string clinicZip4 = clinicZip.Substring(5);                               //Last 4 digits of zip.
                clinicZip = clinicZip.Substring(0, 5);                                    //First 5 digits of zip.
                ncScript.Location.LocationAddress.zip     = clinicZip;                    //Validated to be 9 digits in chart. First 5 digits go in this field.
                ncScript.Location.LocationAddress.zip4    = clinicZip4;                   //Validated to be 9 digits in chart. Last 4 digits go in this field.
                ncScript.Location.LocationAddress.country = country;                      //Validated above.
                ncScript.Location.primaryPhoneNumber      = clinic.Phone;                 //Validated to be 10 digits within the chart.
                ncScript.Location.primaryFaxNumber        = clinic.Fax;                   //Validated to be 10 digits within the chart.
                ncScript.Location.pharmacyContactNumber   = clinic.Phone;                 //Validated to be 10 digits within the chart.
            }
            //Each unique provider ID sent to NewCrop will cause a billing charge.
            //Some customer databases have provider duplicates, because they have one provider record per clinic with matching NPIs.
            //We send NPI as the ID to prevent extra NewCrop charges.
            //Conversation with NewCrop:
            //Question: If one of our customers clicks through to NewCrop with 2 different LicensedPrescriber.ID values,
            //          but with the same provider name and NPI, will Open Dental be billed twice or just one time for the NPI used?
            //Answer:   "They would be billed twice. The IDs you send us should always be maintained and unique.
            //          Users are always identified by LicensedPrescriber ID, since their name or credentials could potentially change."
            if (isMidlevel)
            {
                ncScript.MidlevelPrescriber    = new MidlevelPrescriberType();
                ncScript.MidlevelPrescriber.ID = prov.NationalProvID;
                //UPIN is obsolete
                ncScript.MidlevelPrescriber.LicensedPrescriberName = NewCrop.GetPersonNameForProvider(prov);
                if (deaNumDefault.ToLower() == "none")
                {
                    ncScript.MidlevelPrescriber.dea = "NONE";
                }
                else
                {
                    ncScript.MidlevelPrescriber.dea = deaNumDefault;
                }
                if (provClinic != null)
                {
                    ncScript.MidlevelPrescriber.locationDea = provClinic.DEANum;
                }
                ncScript.MidlevelPrescriber.licenseState  = prov.StateWhereLicensed.ToUpper(); //Validated to be a US state code in the chart.
                ncScript.MidlevelPrescriber.licenseNumber = prov.StateLicense;                 //Validated to exist in chart.
                ncScript.MidlevelPrescriber.npi           = prov.NationalProvID;               //Validated to be 10 digits in chart.
            }
            else                                                                               //Licensed presriber
            {
                ncScript.LicensedPrescriber    = new LicensedPrescriberType();
                ncScript.LicensedPrescriber.ID = prov.NationalProvID;
                //UPIN is obsolete
                ncScript.LicensedPrescriber.LicensedPrescriberName = NewCrop.GetPersonNameForProvider(prov);
                if (deaNumDefault.ToLower() == "none")
                {
                    ncScript.LicensedPrescriber.dea = "NONE";
                }
                else
                {
                    ncScript.LicensedPrescriber.dea = deaNumDefault;
                }
                if (provClinic != null)
                {
                    ncScript.LicensedPrescriber.locationDea = provClinic.DEANum;
                }
                ncScript.LicensedPrescriber.licenseState  = prov.StateWhereLicensed.ToUpper(); //Validated to be a US state code in the chart.
                ncScript.LicensedPrescriber.licenseNumber = prov.StateLicense;                 //Validated to exist in chart.
                ncScript.LicensedPrescriber.npi           = prov.NationalProvID;               //Validated to be 10 digits in chart.
                //ncScript.LicensedPrescriber.freeformCredentials=;//This is where DDS and DMD should go, but we don't support this yet. Probably not necessary anyway.
            }
            if (emp != null)
            {
                ncScript.Staff                  = new StaffType();
                ncScript.Staff.ID               = "emp" + emp.EmployeeNum.ToString(); //A positive integer. Returned in the ExternalUserID field when retreiving prescriptions from NewCrop. Also, provider ID is returned in the same field if a provider created the prescription, so that we can create a distintion between employee IDs and provider IDs.
                ncScript.Staff.StaffName        = new PersonNameType();
                ncScript.Staff.StaffName.first  = emp.FName;                          //First name or last name will not be blank. Validated in Chart.
                ncScript.Staff.StaffName.last   = emp.LName;                          //First name or last name will not be blank. Validated in Chart.
                ncScript.Staff.StaffName.middle = emp.MiddleI;                        //May be blank.
            }
            ncScript.Patient                     = new PatientType();
            ncScript.Patient.ID                  = pat.PatNum.ToString(); //A positive integer.
            ncScript.Patient.PatientName         = new PersonNameType();
            ncScript.Patient.PatientName.last    = pat.LName;             //Validated to exist in Patient Edit window.
            ncScript.Patient.PatientName.first   = pat.FName;             //May be blank.
            ncScript.Patient.PatientName.middle  = pat.MiddleI;           //May be blank.
            ncScript.Patient.medicalRecordNumber = pat.PatNum.ToString(); //A positive integer.
            //NewCrop specifically requested that we do not send SSN.
            //ncScript.Patient.socialSecurityNumber=Regex.Replace(pat.SSN,"[^0-9]*","");//Removes all non-numerical characters.
            ncScript.Patient.PatientAddress          = new AddressOptionalType();
            ncScript.Patient.PatientAddress.address1 = pat.Address;         //May be blank.
            ncScript.Patient.PatientAddress.address2 = pat.Address2;        //May be blank.
            ncScript.Patient.PatientAddress.city     = pat.City;            //May be blank.
            ncScript.Patient.PatientAddress.state    = pat.State.ToUpper(); //May be blank. Validated in chart to be blank or to be a valid US state code.
            //For some reason, NewCrop will fail to load if a 9 digit zip code is sent.
            //One customer had all 9 digit zip codes entered for their patients, so we added code here to only send the first 5 digits of the zip.
            //Patient zip is validated in Chart to be blank, or #####, or #####-####, or #########.
            if (pat.Zip == "")
            {
                ncScript.Patient.PatientAddress.zip = "";                      //Blank is allowed.
            }
            else                                                               //5 or 9 digit zip. Formats are #####, or #####-####, or #########.
            {
                ncScript.Patient.PatientAddress.zip = pat.Zip.Substring(0, 5); //First 5 digts only.
            }
            ncScript.Patient.PatientAddress.country = country;                 //Validated above.
            ncScript.Patient.PatientContact         = new ContactType();
            //ncScript.Patient.PatientContact.backOfficeFax=;//We do not have a field to pull this information from.
            //ncScript.Patient.PatientContact.backOfficeTelephone=;//We do not have a field to pull this information from.
            ncScript.Patient.PatientContact.cellularTelephone = pat.WirelessPhone;              //May be blank. Does not need to be 10 digits.
            ncScript.Patient.PatientContact.email             = pat.Email;                      //May be blank, or may also contain multiple email addresses separated by commas.
            //ncScript.Patient.PatientContact.fax=;//We do not have a field to pull this information from.
            ncScript.Patient.PatientContact.homeTelephone = pat.HmPhone;                        //May be blank. Does not need to be 10 digits.
            //ncScript.Patient.PatientContact.pagerTelephone=;//We do not have a field to pull this information from.
            ncScript.Patient.PatientContact.workTelephone = pat.WkPhone;                        //May be blank. Does not need to be 10 digits.
            ncScript.Patient.PatientCharacteristics       = new PatientCharacteristicsType();
            ncScript.Patient.PatientCharacteristics.dob   = pat.Birthdate.ToString("yyyyMMdd"); //DOB must be in CCYYMMDD format.
            if (pat.Gender == PatientGender.Male)
            {
                ncScript.Patient.PatientCharacteristics.gender = GenderType.M;
            }
            else if (pat.Gender == PatientGender.Female)
            {
                ncScript.Patient.PatientCharacteristics.gender = GenderType.F;
            }
            else
            {
                ncScript.Patient.PatientCharacteristics.gender = GenderType.U;
            }
            ncScript.Patient.PatientCharacteristics.genderSpecified = true;
            //NewCrop programmer's comments regarding other fields we are not currently using (these fields are sent back when fetching prescriptions in the Chart):
            //ExternalPrescriptionId = your unique identifier for the prescription, only to be used if you are generating the prescription on your own UI.
            //	This is referenced by NewCrop, and cannot be populated with any other value.
            //EncounterIdentifier = unique ID for the patient visit (e.g. John Doe, 11/11/2013).
            //	This is used by NewCrop for reporting events against a visit, but otherwise does not impact the session.
            //EpisodeIdentifier = unique ID for the patient’s issue (e.g. John Doe’s broken leg) which may include multiple visits.
            //	Currently not used by NewCrop except for being echoed back; it is possible this functionality would be expanded in the future based on its intent as noted.
            //ExternalSource = a codified field noting the origin of the prescription. This may not be used.
            //Serialize
            MemoryStream  memoryStream  = new MemoryStream();
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(NCScript));

            xmlSerializer.Serialize(memoryStream, ncScript);
            byte[] memoryStreamInBytes = memoryStream.ToArray();
            return(Encoding.UTF8.GetString(memoryStreamInBytes, 0, memoryStreamInBytes.Length));
        }
Ejemplo n.º 30
0
 ///<summary>Prior to 17.4 the user had the choice to install the eConnector but leave it disabled.
 ///As of 17.4 installing gives implied conset to also enable the servcie for communicating.</summary>
 public static ListenerServiceType SetEConnectorOn()
 {
     return(WebSerializer.DeserializePrimitiveOrThrow <ListenerServiceType>(
                GetWebServiceMainHQInstance().SetEConnectorType(WebSerializer.SerializePrimitive <string>(PrefC.GetString(PrefName.RegistrationKey)), true)));
 }