SMS plug-in questions

This forum is for programmers who have questions about the source code.
Post Reply
Mifa
Posts: 141
Joined: Wed Nov 21, 2007 6:52 pm
Location: Saint-Bruno, QC, Canada
Contact:

SMS plug-in questions

Post by Mifa » Sun Feb 15, 2015 10:31 am

First, I would like to activate the send SMS button everywhere in the program and not reinvent the wheel. I see in the code that this is tied to the callfire bridge being activated. If I activate the bridge but do not provide any reference to a Callfire dll, program key etc. in the bridge window the buttons turn active. Then, the only place I need to "change" (i.e. with a plugin) in order to bypass Callfire is the method SendText in FormTextMessEdit.cs. Is this correct?

The SMS solution I'm testing requires a record to be inserted in a new table (called messageout) that I have already created. The SMS gateway monitors this table and sends the SMS as soon as it finds it (I've manually added records into the table and it works just fine). Before getting into building the actual plugin, I want to test my (simple) code. I have commented (see below) and replaced the callfire related code in SendText, here is how it goes:

Code: Select all

/* MF remove start
            string key=ProgramProperties.GetPropVal(ProgramName.CallFire,"Key From CallFire");
			string msg=wirelessPhone+","+message.Replace(",","");//ph#,msg Commas in msg cause error.
			try {
				CallFireService.SMSService callFire=new CallFireService.SMSService();
				callFire.sendSMSCampaign(
					key,
					new string[] { msg },
					"Open Dental");
			}
			catch(Exception ex) {
				MsgBox.Show(this,"Error sending text message.\r\n\r\n"+ex.Message);
				return false;
			}
MF remove end */
// MF add start
            string dialPhone = "+1" + wirelessPhone; // +1XXXXXXXXXX format
            MsgBox.Show(this, "Wireless rev:" + dialPhone);
            string msg = message + " Clinique dentaire B. Fabre XXX-XXX-XXXX";
            MsgBox.Show(this, "Wireless rev:" + dialPhone + "\n" + msg);
            string command = "INSERT INTO messageout (MessageTo,MessageText"
                + ") VALUES("
                + dialPhone
                + ","
                + msg
                + ")";
            Db.NonQ(command, false);
            msg = dialPhone + " - " + message;
// MF add end
When I compile, I get an error message saying that "Error 6 'OpenDentBusiness.Db' does not contain a definition for 'NonQ' C:\Users\Michel\Desktop\opendental14.3\OpenDental\Forms\FormTxtMsgEdit.cs 78 16 OpenDental", I've checked in several places where NonQ is used, but cannot find my mistake. I've tried using Db, DataCore, only one argument for the call, nothing works. Can you help me please?

Thanks.

Mifa

jwhitney
Posts: 33
Joined: Tue Jul 01, 2014 9:52 am

Re: SMS plug-in questions

Post by jwhitney » Mon Feb 16, 2015 6:32 am

The short answer to your compiler issue is that you are calling an internal function that lives in OpenDentBusiness from a namespace other than OpenDentBusiness (in this case, the OpenDental namespace).
In order to understand recursion you must first understand recursion.

Josh Whitney
Open Dental Software
1-503-363-5432
http://www.opendental.com

Mifa
Posts: 141
Joined: Wed Nov 21, 2007 6:52 pm
Location: Saint-Bruno, QC, Canada
Contact:

Re: SMS plug-in questions

Post by Mifa » Mon Feb 16, 2015 7:17 am

Thanks! In fact, DataCore is working from the OpenDental namespace. I'm fixing the other bugs in my code. Now, what about the first part of my question? regarding enabling the Callfire bridge so that the "send text" buttons in OD become clickable and only changing SendText, would that work?

Mifa
Posts: 141
Joined: Wed Nov 21, 2007 6:52 pm
Location: Saint-Bruno, QC, Canada
Contact:

Re: SMS plug-in questions

Post by Mifa » Mon Feb 16, 2015 8:21 am

OK, I've answered the first part of my question as well. Enabling the callfire bridge (even though we don't have it) makes the "send text" buttons usable and they work fine with our SMS gateway setup. SendText gets called. It works, but it's not really fancy.

New question, that may well be a feature request for non-US OD users and US users that would like to use another SMS gateway: would it be possible to have an "enable SMS" toggle somewhere in the setup to activate or not the send text buttons. This new test would replace the !Programs.IsEnabled(ProgramName.CallFire) test everywhere except in SendText where it is required (i.e. when you actually use their API, the code I commented in my post above), and move the plugin hook from the beginning of this method like this:

Code: Select all

	    if(Programs.IsEnabled(ProgramName.CallFire)) {
                       .... callfire related code
			}
            else if "SMS service is enabled "
                        {
                                if(Plugins.HookMethod(this,"FormTxtMsgEdit.SendText_Start",patNum,wirelessPhone,message,txtMsgOk)) {
				                return false;
			                   }
                                 else
                                          {
				               MsgBox.Show(this,"SMS service enabled but cannot find a valid SMS Gateway");
				               return false;
			                  }
			}
           else
                        {
				MsgBox.Show(this,"No SMS service enabled");
				return false;
			}


Mifa
Posts: 141
Joined: Wed Nov 21, 2007 6:52 pm
Location: Saint-Bruno, QC, Canada
Contact:

Re: SMS plug-in questions

Post by Mifa » Wed Mar 04, 2015 12:20 pm

We have a working solution (see post about SMS in Canada in the main forum for details about our setup).

Here is the code I ended up adding to the SendText method of FormTxtMsgEdit.cs. A plugin would have been more elegant.

Code: Select all

using System.Text.RegularExpressions;   // MF added

...

/* MF remove start
            if(message.Length>160) {
				MsgBox.Show(this,"Text length must be less than 160 characters.");
				return false;
			}
			string key=ProgramProperties.GetPropVal(ProgramName.CallFire,"Key From CallFire");
			string msg=wirelessPhone+","+message.Replace(",","");//ph#,msg Commas in msg cause error.
			try {
				CallFireService.SMSService callFire=new CallFireService.SMSService();
				callFire.sendSMSCampaign(
					key,
					new string[] { msg },
					"Open Dental");
			}
			catch(Exception ex) {
				MsgBox.Show(this,"Error sending text message.\r\n\r\n"+ex.Message);
				return false;
			}
			Commlog commlog=new Commlog();
			commlog.CommDateTime=DateTime.Now;
			commlog.DateTStamp=DateTime.Now;
			commlog.CommType=DefC.Short[(int)DefCat.CommLogTypes][0].DefNum;//The first one in the list.  We can enhance later.
			commlog.Mode_=CommItemMode.Text;
			commlog.Note=msg;//phone,note
			commlog.PatNum=patNum;
			commlog.SentOrReceived=CommSentOrReceived.Sent;
			commlog.UserNum=Security.CurUser.UserNum;
			commlog.DateTimeEnd=DateTime.Now;
			Commlogs.Insert(commlog);
			SecurityLogs.MakeLogEntry(Permissions.CommlogEdit,commlog.PatNum,"Insert Text Message");
MF remove end */
// MF add start
            string strippedWirelessPhone = Regex.Replace(wirelessPhone, "[^0-9]", "");
            string dialPhone = "+1" + strippedWirelessPhone;
            string replyPhone = PrefC.GetString(PrefName.PracticePhone).Substring(0, 3) + "-" + PrefC.GetString(PrefName.PracticePhone).Substring(3, 3) + "-" + PrefC.GetString(PrefName.PracticePhone).Substring(6);
            string msg = message + " " + PrefC.GetString(PrefName.PracticeTitle).Substring(0, 26) + " " + replyPhone;
            if (dialPhone.Length != 12)
            {
                MsgBox.Show(this, "Invalid phone number. Expecting 10 digits number.");
            }
            else if (msg.Length > 160)
            {
                MsgBox.Show(this, "Text too long. Max 120 characters.");
            }
            else
            {
                string command = "INSERT INTO messageout (MessageTo,UserId,MessageText"
                + ") VALUES('"
                + dialPhone
                + "','"
                + patNum
                + "','"
                + msg
                + "')";
                if (MsgBox.Show(this, MsgBoxButtons.OKCancel, dialPhone + " - " + msg) == true)
                {
                    DataCore.NonQ(command);
                    msg = dialPhone + " - " + message;
                }
            }
// MF add end
It works with 10 digits phone numbers (US and Canada). It adds the country code (+1) in our case and strips the phone number from any undesired characters to keep only digits. The practice name (truncated to 26 characters in our case) and phone number is automatically appended at the end of the text message. The final message is displayed for confirmation before being sent via the Diafaan gateway and dedicated android cellphone. We use the UserId field of the messageOut and messageLog tables to record patnum for outgoing messages. Et voilà!

draluu
Posts: 15
Joined: Sat Mar 28, 2015 1:23 am

Re: SMS plug-in questions

Post by draluu » Sat Apr 04, 2015 3:32 pm

Mifa,
Instead of using the Diafaan Gateway with a subscription fee, have you considered using the free Android app SMS Gateway which can send and receive SMS from an email using POP3 or an internal web server?
https://play.google.com/store/apps/deta ... eway&hl=en

jaynahar
Posts: 40
Joined: Wed Apr 23, 2014 6:35 am

Re: SMS plug-in questions

Post by jaynahar » Tue Apr 07, 2015 3:00 pm

Another Q on SMS Plugin. I see the change in butOK_Click method from version 13.x to 14.x.
In 13.x, form closed after sending text and now in 14.x it doesn't closes. Its kind of deceptive if SMS was sent or not(in my case).
Please help provide the further info on the comment //Allow the user to try again. A message was already shown to the user inside SendText().


Version 13.x
private void butOK_Click(object sender,EventArgs e) {
if(textMessage.Text=="") {
MsgBox.Show(this,"Please enter a message first.");
return;
}
SendText(PatNum,textWirelessPhone.Text,textMessage.Text,TxtMsgOk);
DialogResult=DialogResult.OK;
}
Version 14.x

private void butOK_Click(object sender,EventArgs e) {
if(textMessage.Text=="") {
MsgBox.Show(this,"Please enter a message first.");
return;
}
if(!SendText(PatNum,textWirelessPhone.Text,textMessage.Text,TxtMsgOk)) {
return;//Allow the user to try again. A message was already shown to the user inside SendText().
}
DialogResult=DialogResult.OK;
}

jwhitney
Posts: 33
Joined: Tue Jul 01, 2014 9:52 am

Re: SMS plug-in questions

Post by jwhitney » Wed Apr 08, 2015 6:10 am

That comment is saying there is no need to display a message box before returning out of the butOK_Click method, because in SendText there are messageboxes displayed before ever returning false. It has nothing to do with the text message being sent, however I see how easily that is to misinterpret. If you ever get returned out of the butOK_Click, your text message wasn't sent.
In order to understand recursion you must first understand recursion.

Josh Whitney
Open Dental Software
1-503-363-5432
http://www.opendental.com

jaynahar
Posts: 40
Joined: Wed Apr 23, 2014 6:35 am

Re: SMS plug-in questions

Post by jaynahar » Thu Apr 09, 2015 11:59 pm

jwhitney wrote:That comment is saying there is no need to display a message box before returning out of the butOK_Click method, because in SendText there are messageboxes displayed before ever returning false. It has nothing to do with the text message being sent, however I see how easily that is to misinterpret. If you ever get returned out of the butOK_Click, your text message wasn't sent.

Hi Josh,

Thanks for the clarification. Wanted to share my side of challenge and see if you have any good solution for it.
Return of "false" after HookMethod call in SendText causes FormTxtMsgEdit not to close, which creates a usability confusion, if SMS was successfully sent via call to HookMethod or not and user keep clicking the Send button, hence multiple SMSs

Code: Select all

			if(Plugins.HookMethod(this,"FormTxtMsgEdit.SendText_Start",patNum,wirelessPhone,message,txtMsgOk)) {
				return false;
			} 

Code: Select all

			if(!SendText(PatNum,textWirelessPhone.Text,textMessage.Text,TxtMsgOk)) {
				return;//Allow the user to try again.  A message was already shown to the user inside SendText().
			}
Please do let me know if there is any good way to close FormTxtMsgEdit after Plugins.HookMethod call.

Thanks

jaynahar
Posts: 40
Joined: Wed Apr 23, 2014 6:35 am

Re: SMS plug-in questions

Post by jaynahar » Tue Apr 14, 2015 4:59 pm

jaynahar wrote:
jwhitney wrote:That comment is saying there is no need to display a message box before returning out of the butOK_Click method, because in SendText there are messageboxes displayed before ever returning false. It has nothing to do with the text message being sent, however I see how easily that is to misinterpret. If you ever get returned out of the butOK_Click, your text message wasn't sent.

Hi Josh,

Thanks for the clarification. Wanted to share my side of challenge and see if you have any good solution for it.
Return of "false" after HookMethod call in SendText causes FormTxtMsgEdit not to close, which creates a usability confusion, if SMS was successfully sent via call to HookMethod or not and user keep clicking the Send button, hence multiple SMSs

Code: Select all

			if(Plugins.HookMethod(this,"FormTxtMsgEdit.SendText_Start",patNum,wirelessPhone,message,txtMsgOk)) {
				return false;
			} 

Code: Select all

			if(!SendText(PatNum,textWirelessPhone.Text,textMessage.Text,TxtMsgOk)) {
				return;//Allow the user to try again.  A message was already shown to the user inside SendText().
			}
Please do let me know if there is any good way to close FormTxtMsgEdit after Plugins.HookMethod call.

Thanks

Hello...Please help look into this SMS issue.

allends
Posts: 235
Joined: Fri Aug 23, 2013 11:29 am

Re: SMS plug-in questions

Post by allends » Wed Apr 15, 2015 7:31 am

The way I understand this issue is that you want this

Code: Select all

  if(Plugins.HookMethod(this,"FormTxtMsgEdit.SendText_Start",patNum,wirelessPhone,message,txtMsgOk)) {
            return false;
            }
to return true.

The best way I can think of to accomplish this for your plug-in would simply be to write a new hook directly below that like this:

Code: Select all

  if(Plugins.HookMethod(this,"FormTxtMsgEdit.SendText_Start2",patNum,wirelessPhone,message,txtMsgOk)) {
            return true;
            }
Allen
Open Dental Software
http://www.opendental.com

jaynahar
Posts: 40
Joined: Wed Apr 23, 2014 6:35 am

Re: SMS plug-in questions

Post by jaynahar » Wed Apr 15, 2015 11:00 am

adearmondsattler wrote:The way I understand this issue is that you want this

Code: Select all

  if(Plugins.HookMethod(this,"FormTxtMsgEdit.SendText_Start",patNum,wirelessPhone,message,txtMsgOk)) {
            return false;
            }
to return true.

The best way I can think of to accomplish this for your plug-in would simply be to write a new hook directly below that like this:

Code: Select all

  if(Plugins.HookMethod(this,"FormTxtMsgEdit.SendText_Start2",patNum,wirelessPhone,message,txtMsgOk)) {
            return true;
            }
Yes, returning true will help. If that breaks other code, than adding another hook method will work.

Thanks for looking into it. Really appreciate your support.

Thanks

jaynahar
Posts: 40
Joined: Wed Apr 23, 2014 6:35 am

Re: SMS plug-in questions

Post by jaynahar » Thu Apr 16, 2015 8:21 am

Hi Allen,

Thanks for the suggestion made by you. Wanted to follow-up to check if there was any resolution on it at OpenDental Side.

Thanks,

allends
Posts: 235
Joined: Fri Aug 23, 2013 11:29 am

Re: SMS plug-in questions

Post by allends » Thu Apr 16, 2015 9:37 am

If you tested that hook and it works then all you need to do is make a hook request in this forum asking for "true" code I wrote. I will add it to our latest beta version so you can use it with the next beta release.
Allen
Open Dental Software
http://www.opendental.com

jaynahar
Posts: 40
Joined: Wed Apr 23, 2014 6:35 am

Re: SMS plug-in questions

Post by jaynahar » Fri Apr 17, 2015 6:53 am

Thanks will do that.

Post Reply