///<summary>Inserts the SmsToMobile to the database and creates a commlog if necessary.</summary> private static void HandleSentSms(List <SmsToMobile> listSmsToMobiles, bool makeCommLog, Userod user) { //No need to check RemotingRole; no call to db. foreach (SmsToMobile smsToMobile in listSmsToMobiles) { smsToMobile.SmsStatus = SmsDeliveryStatus.Pending; smsToMobile.DateTimeSent = DateTime.Now; if (smsToMobile.PatNum != 0 && makeCommLog) //Patient specified and calling code won't make commlog, make it here. { long userNum = 0; if (user != null) { userNum = user.UserNum; } Commlogs.Insert(new Commlog() { CommDateTime = smsToMobile.DateTimeSent, Mode_ = CommItemMode.Text, Note = "Text message sent: " + smsToMobile.MsgText, PatNum = smsToMobile.PatNum, CommType = Commlogs.GetTypeAuto(CommItemTypeAuto.TEXT), SentOrReceived = CommSentOrReceived.Sent, UserNum = userNum }); } } InsertMany(listSmsToMobiles); }
private static void MakeCommlog(Patient pat, string phoneNumber, int statusCode) { string commText = ""; //Status code meanings: // -100: Patient had no phone number // -200: Patient can't text and had no email // 2XX: Successfully sent message // 422: Message has already been sent for patient // Anything else: Failure of some sort. switch (statusCode / 100) //Get general http status codes e.g. -100=-1, 203=2 { case -1: //Failure, no phone number commText = Lans.g("Podium", "Podium review invitation request failed because there was no phone number. Error code:") + " " + statusCode; break; case -2: //Failure, no email commText = Lans.g("Podium", "Podium review invitation request failed because the patient doesn't accept texts " + "and there was no email address. Error code:") + " " + statusCode; break; case 2: //Success https://httpstatusdogs.com/200-ok commText = Lans.g("Podium", "Podium review invitation request successfully sent."); break; case 4: //Client side communication failure https://httpstatusdogs.com/400-bad-request if (statusCode == 422) //422 is Unprocessable Entity, which is sent in this case when a phone number has received an invite already. { commText = Lans.g("Podium", "The request failed because an identical request was previously sent."); } else { commText = Lans.g("Podium", "The request failed to reach Podium with error code:") + " " + statusCode; } break; case 5: //Server side internal failure. https://httpstatusdogs.com/500-internal-server-error commText = Lans.g("Podium", "The request was rejected by the Podium server with error code:") + " " + statusCode; break; default: //General Failure commText = Lans.g("Podium", "The request failed to send with error code:") + " " + statusCode; break; } if (!string.IsNullOrEmpty(commText)) { commText += "\r\n"; } commText += Lans.g("Podium", "The information sent in the request was") + ": \r\n" + Lans.g("Podium", "First name") + ": \"" + pat.FName + "\", " + Lans.g("Podium", "Last name") + ": \"" + pat.LName + "\", " + Lans.g("Podium", "Email") + ": \"" + pat.Email + "\""; if (phoneNumber != "") //If "successful". { commText += ", " + Lans.g("Podium", "Phone number") + ": \"" + phoneNumber + "\""; } else { string wirelessPhone = new string(pat.WirelessPhone.Where(x => char.IsDigit(x)).ToArray()); string homePhone = new string(pat.HmPhone.Where(x => char.IsDigit(x)).ToArray()); List <string> phonesTried = new List <string> { wirelessPhone, homePhone }.FindAll(x => x != ""); string phoneNumbersTried = ", " + Lans.g("Podium", "No valid phone number found."); if (pat.TxtMsgOk == YN.No || (pat.TxtMsgOk == YN.Unknown && PrefC.GetBool(PrefName.TextMsgOkStatusTreatAsNo))) //Used email { phoneNumbersTried = ""; } else if (phonesTried.Count > 0) { phoneNumbersTried = ", " + Lans.g("Podium", "Phone numbers tried") + ": " + string.Join(", ", phonesTried); } commText += phoneNumbersTried; } long programNum = Programs.GetProgramNum(ProgramName.Podium); Commlog commlogCur = new Commlog(); commlogCur.CommDateTime = DateTime.Now; commlogCur.DateTimeEnd = DateTime.Now; commlogCur.PatNum = pat.PatNum; commlogCur.UserNum = 0; //run from server, no valid CurUser commlogCur.CommSource = CommItemSource.ProgramLink; commlogCur.ProgramNum = programNum; commlogCur.CommType = Commlogs.GetTypeAuto(CommItemTypeAuto.MISC); commlogCur.Note = commText; commlogCur.Mode_ = CommItemMode.Text; commlogCur.SentOrReceived = CommSentOrReceived.Sent; Commlogs.Insert(commlogCur); }
///<summary>Attempts to find exact match for patient. If found, creates commlog, associates Patnum, and inserts into DB. ///Otherwise, it simply inserts SmsFromMobiles into the DB. ClinicNum should have already been set before calling this function.</summary> public static void ProcessInboundSms(List <SmsFromMobile> listMessages) { if (listMessages == null || listMessages.Count == 0) { return; } List <SmsBlockPhone> listBlockedPhones = SmsBlockPhones.GetDeepCopy(); for (int i = 0; i < listMessages.Count; i++) { SmsFromMobile sms = listMessages[i]; if (listBlockedPhones.Any(x => TelephoneNumbers.AreNumbersEqual(x.BlockWirelessNumber, sms.MobilePhoneNumber))) { continue; //The office has blocked this number. } sms.DateTimeReceived = DateTime.Now; SmsPhone smsPhone = SmsPhones.GetByPhone(sms.SmsPhoneNumber); string countryCode = CultureInfo.CurrentCulture.Name.Substring(CultureInfo.CurrentCulture.Name.Length - 2); if (smsPhone != null) { sms.ClinicNum = smsPhone.ClinicNum; countryCode = smsPhone.CountryCode; } //First try the clinic that belongs to this phone. List <long> listClinicNums = new List <long>(); if (sms.ClinicNum != 0) { listClinicNums.Add(sms.ClinicNum); } List <long[]> listPatNums = FindPatNums(sms.MobilePhoneNumber, countryCode, listClinicNums); if (listPatNums.Count == 0 && listClinicNums.Count > 0) //Could not find that patient in this clinic so try again for all clinics. { listPatNums = FindPatNums(sms.MobilePhoneNumber, countryCode); } sms.MatchCount = listPatNums.Count; //Item1=PatNum; Item2=Guarantor if (listPatNums.Count == 0 || listPatNums.Select(x => x[1]).Distinct().ToList().Count != 1) { //We could not find definitive match, either 0 matches found, or more than one match found with different garantors Insert(sms); continue; } if (listPatNums.Count == 1) { sms.PatNum = listPatNums[0][0]; //PatNum } else { sms.PatNum = listPatNums[0][1]; //GuarantorNum; more than one match, but all have the same garantor. } Commlog comm = new Commlog() { CommDateTime = sms.DateTimeReceived, Mode_ = CommItemMode.Text, Note = sms.MsgText, PatNum = sms.PatNum, CommType = Commlogs.GetTypeAuto(CommItemTypeAuto.TEXT), SentOrReceived = CommSentOrReceived.Received }; sms.CommlogNum = Commlogs.Insert(comm); Insert(sms); } UpdateSmsNotification(); }
///<summary>Attempts to find exact match for patient. If found, creates commlog, associates Patnum, and inserts into DB. ///Otherwise, it simply inserts SmsFromMobiles into the DB. ClinicNum should have already been set before calling this function.</summary> public static void ProcessInboundSms(List <SmsFromMobile> listMessages) { if (listMessages == null || listMessages.Count == 0) { return; } List <SmsBlockPhone> listBlockedPhones = SmsBlockPhones.GetDeepCopy(); for (int i = 0; i < listMessages.Count; i++) { SmsFromMobile sms = listMessages[i]; if (listBlockedPhones.Any(x => TelephoneNumbers.AreNumbersEqual(x.BlockWirelessNumber, sms.MobilePhoneNumber))) { continue; //The office has blocked this number. } sms.DateTimeReceived = DateTime.Now; string countryCode = CultureInfo.CurrentCulture.Name.Substring(CultureInfo.CurrentCulture.Name.Length - 2); if (sms.SmsPhoneNumber != SmsPhones.SHORTCODE) { SmsPhone smsPhone = SmsPhones.GetByPhone(sms.SmsPhoneNumber); if (smsPhone != null) { sms.ClinicNum = smsPhone.ClinicNum; countryCode = smsPhone.CountryCode; } } if (!PrefC.HasClinicsEnabled) { //We want customer side records of this message to list SmsPhones.SHORTCODE as the number on which the message was sent. This ensures we do //not record this communication on a different valid SmsPhone/VLN that it didn't truly take place on. However, on the HQ side, we want //records of this communication to be listed as having taken place on the actual Short Code number. In the case of a Short Code, //sms.SmsPhoneNumber will read "SHORTCODE", which won't be found in the customer's SmsPhone table. As a result, the code to use the //customer's SmsPhone.ClinicNum and Country code cannot be used. Since this code was intended to handle the case where the customer had //turned clinics on->off, we will specifically check if the customer has disabled clinics and only then change the sms.ClinicNum. //Otherwise, trust HQ sent the correct ClinicNum. Since we expect to only use Short Codes in the US/Canada, we will trust the server we //are processing inbound sms will have the correct country code, which will be used here. sms.ClinicNum = 0; } //First try the clinic that belongs to this phone. List <long> listClinicNums = new List <long>(); if (sms.ClinicNum != 0) { listClinicNums.Add(sms.ClinicNum); } List <long[]> listPatNums = FindPatNums(sms.MobilePhoneNumber, countryCode, listClinicNums); if (listPatNums.Count == 0 && listClinicNums.Count > 0) //Could not find that patient in this clinic so try again for all clinics. { listPatNums = FindPatNums(sms.MobilePhoneNumber, countryCode); } sms.MatchCount = listPatNums.Count; //Item1=PatNum; Item2=Guarantor if (listPatNums.Count == 0 || listPatNums.Select(x => x[1]).Distinct().ToList().Count != 1) { //We could not find definitive match, either 0 matches found, or more than one match found with different garantors Insert(sms); //Alert ODMobile where applicable. PushNotificationUtils.ODM_NewTextMessage(sms); continue; } if (listPatNums.Count == 1) { sms.PatNum = listPatNums[0][0]; //PatNum } else { sms.PatNum = listPatNums[0][1]; //GuarantorNum; more than one match, but all have the same garantor. } Commlog comm = new Commlog() { CommDateTime = sms.DateTimeReceived, Mode_ = CommItemMode.Text, Note = sms.MsgText, PatNum = sms.PatNum, CommType = Commlogs.GetTypeAuto(CommItemTypeAuto.TEXT), SentOrReceived = CommSentOrReceived.Received }; sms.CommlogNum = Commlogs.Insert(comm); Insert(sms); //Alert ODMobile where applicable. PushNotificationUtils.ODM_NewTextMessage(sms, sms.PatNum); } //We used to update the SmsNotification indicator via a queries and a signal here. Now managed by the eConnector. }