Start a new topic

Make Phone/Email Primary

Hi,

We are trying to add API code to determine if an incoming phone or email should be marked Primary or not depending on the status of the constituents current phones or emails.

We have upgraded to RE 7.95 and this upgrade changed how phones are stored so we are having some confusion.  In order to familiarize ourselves with the new phone fields we have written some code to view the Phone Type in a MsgBox.  This way we can be sure that we are accessing the correct fields.  However, we are still having some problems as there as still fields marked PreferredAddress.Phones (which isn't where phones are stored anymore so it's confusing).

Here is the code we've started with which is returning a "blank" even though our constituent has a Preferred Email and a Home phone.

Dim oPhones as CConstitPhones

Dim oPhone as IBBPhone

For each oPhone in oRec.PreferredAddress.Phones

MsgBox ("Here is the current phone code: " & oRec.Fields(Blackbaud.PIA.RE7.BBREAPI.EPhonesFields.Phone_fld_PhoneType))

Next oPhone

Any help would be greatly appreciated!

Thanks,

Lisa Folger

 

W


In order to maintain backwards compatibility, IOM is still referencing the Blackbaud libraries for 7.93. This means that you will not see the Phones property that now lives on the CRecord type. You can however still access it using reflection. Here is a little sample code to get you started:

Dim method As System.Reflection.MethodInfo = oRec.GetType.GetMethod("get_Phones")
Dim phones = method.Invoke(oRec, Nothing)

Dim iPhoneCount As Integer = phones.GetType.GetMethod("Count").Invoke(phones, Nothing)
For i As Integer = 1 To iPhoneCount
Dim phone = phones.GetType.GetMethod("Item").Invoke(phones, New Object() {i})

That will get you the phone object and from there you need to get the Fields property and invoke it with your field number.

The field numbers for this phone object are not the same as Blackbaud.PIA.RE7.BBREAPI.EPhonesFields. For example, the primary flag is 11 and type is 2.
Thanks for the help Nic. I will play around with this and hopefully get it to work.
Hi Nic,

Here is my code based on your post above. I'm just trying to see what's in the fields so I'm sure that I have the correct fields etc. However, I get an error in the code:
'phone is not declared. It may be inaccessible due to its protection level'

Here is the code I'm using:

Public Overrides Sub AfterConstituentOpen(ByVal oRec As CRecord, ByVal Cancel As ImportOM.API.iCancel)
MyBase.BeforeConstituentSave(oRec, Cancel)
Dim method As System.Reflection.MethodInfo = oRec.GetType().GetMethod ("get_Phones")
Dim phones = method.Invoke(oRec, Nothing)

Dim iPhoneCount As Integer = phones.GetType().GetMethod("Count").Invoke(phones, Nothing)
For i As Integer = 1 To iPhoneCount
Dim phone = phones.GetType().GetMethod("Item").Invoke(phones, New Object() {1})
Next i

For Each phone In phones
MsgBox ("Phone type: " & oRec.Fields(Blackbaud.PIA.RE7.BBREAPI.ECONSTITPHONEFIELDS.CONSTIT_PHONES_fld_IS_PRIMARY))
Next phone
End sub

Any ideas?

thanks for any help you can shed on this.

Lisa
Lisa,

You would need to use that first for loop to check each phone and you are attempting to read a phone field on oRec instead of the phone.
Nic,

When I move the code to the first For loop and change it to read phone.Fields (Blackbaud.PIA.RE7.BBREAPI.EPhonesFields.CONSTIT_PHONES_fld_PHONETYPE)
I get the error (at import time) :

Line 1: Error in custom code AfterConstituentOpen: Public member 'Fields' on type 'CConstitPhoneClass' not found.

When I try to use phone (rather than oRec) I don't get any selections when I type phone. - like it doesn't recognize it as an object. Here's my code as it stands now:

Public Overrides Sub AfterConstituentOpen(ByVal oRec As CRecord, ByVal Cancel As ImportOM.API.iCancel)
MyBase.BeforeConstituentSave(oRec, Cancel)
Dim method As System.Reflection.MethodInfo = oRec.GetType().GetMethod ("get_Phones")
Dim phones = method.Invoke(oRec, Nothing)
Dim iPhoneCount As Integer = phones.GetType().GetMethod("Count").Invoke(phones, Nothing)
For i As Integer = 1 To iPhoneCount
Dim phone = phones.GetType.GetMethod("Item").Invoke(phones, New Object() {i})
MsgBox ("Phone type: " & phone.Fields(Blackbaud.PIA.RE7.BBREAPI.ECONSTIT_ADDRESS_PHONEFields.CONSTIT_ADDRESS_PHONES_fld_PHONETYPE))
Next i
End sub
Lisa,

There is a get_Fields and a set_Fields. They accept an integer parameter and below is the translation for that parameter.

Phone_fld_ID = 1
Phone_fld_PhoneType = 2
Phone_fld_Num = 3
Phone_fld_DoNotCall = 8
Phone_fld_IsPrimary = 11
Phone_fld_Inactive = 13
Phone_fld_Indicator = 16
Phone_fld_Comments = 19
Thanks Nic.

get_fields and set_fields are custom functions? is this true? Or are they a custom method?

If so (either), how are they invoked? 

Those are methods off the CConstitPhoneClass type. You would invoke them the same way the get_Phones method is off of oRec.

Dim method As System.Reflection.MethodInfo = oRec.GetType().GetMethod ("get_Phones")
Dim phones = method.Invoke(oRec, Nothing)
Thanks Nic. We tried that and got the following error:

Source row 1 produced Excel error row 2: Error in custom code AfterConstituentOpen: Ambiguous match found. Line:0

Here is our code ( we simply want to msgbox the phone/email type )

Public Overrides Sub AfterConstituentOpen(ByVal oRec As CRecord, ByVal Cancel As ImportOM.API.iCancel)
MyBase.AfterConstituentOpen(oRec, Cancel)
Dim method As System.Reflection.MethodInfo = oRec.GetType().GetMethod ("get_Phones")
Dim phones = method.Invoke(oRec, Nothing)

Dim fmethod As system.reflection.methodinfo = oRec.GetType().GetMethod ("get_Fields")
Dim fields = fmethod.Invoke(oRec, Nothing)


Dim iPhoneCount As Integer = phones.GetType().GetMethod("Count").Invoke(phones, Nothing)
For i As Integer = 1 To iPhoneCount
Dim phone = phones.GetType.GetMethod("Item").Invoke(phones, New Object() {i})
Dim field = fields.GetType.GetMethod("Item").Invoke(fields, New Object() {i})
field = fields(2)
MsgBox ("Phone type: " & field)
Next i
End sub

Lisa
The fields property exists off of the phone object, so that is the "get_Fields" method you want to retrieve. From there you can invoke the method, passing in the phone and the field number you want to return. I've adjusted your code below.

Public Overrides Sub AfterConstituentOpen(ByVal oRec As CRecord, ByVal Cancel As ImportOM.API.iCancel)
MyBase.AfterConstituentOpen(oRec, Cancel)
Dim method As System.Reflection.MethodInfo = oRec.GetType().GetMethod ("get_Phones")
Dim phones = method.Invoke(oRec, Nothing)

Dim iPhoneCount As Integer = phones.GetType().GetMethod("Count").Invoke(phones, Nothing)
For i As Integer = 1 To iPhoneCount
Dim phone = phones.GetType.GetMethod("Item").Invoke(phones, New Object() {i})
Dim phoneType = phone.GetType.GetMethod("get_Fields").Invoke(phone, New Object() {2})
MsgBox ("Phone type: " & phoneType)
Next i
End sub
Thanks Nic. We'll give that a try.
All code is in place, but we are still getting the "ambiguous match" error. After some research, my (very novice) guess is that we are trying to use the same fields and return two different things at the same time. We want the phonetype to count so we make sure we get through all of them, but then we actually want the phonetype itself. I commented out part of the code that tries to get the phonetype, and the error disappears, so I think I'm on the right track - but all of my other (again, very novice) guesses, are not helping to get past this.
The issues is that get_Fields has two signatures and the GetMethod call doesn't know which one you want. I've updated the code to specify that you want the get_Fields method that accepts an integer parameter.

Public Overrides Sub AfterConstituentOpen(ByVal oRec As CRecord, ByVal Cancel As ImportOM.API.iCancel)
MyBase.AfterConstituentOpen(oRec, Cancel)
Dim method As System.Reflection.MethodInfo = oRec.GetType().GetMethod ("get_Phones")
Dim phones = method.Invoke(oRec, Nothing)

Dim iPhoneCount As Integer = phones.GetType().GetMethod("Count").Invoke(phones, Nothing)
For i As Integer = 1 To iPhoneCount
Dim phone = phones.GetType.GetMethod("Item").Invoke(phones, New Object() {i})
Dim phoneType = phone.GetType.GetMethod("get_Fields",New Type() {GetType(Integer)}).Invoke(phone, New Object() {2})
MsgBox ("Phone type: " & phoneType)
Next i
End sub
Login to post a comment