Tag Archives: Constituent

Working with RE7.95 and phone configuration rules

In v7.95 of RE7, there were some new config business rules introduced which prevent duplicate phone or emails being added to a record.

phone config

I have not really found this to be consistent though. When I use this inside of a constituent record it does not seem to make the slightest difference which setting. I can have to “Email” phone types but no matter which setting is selected above it saves fine. This does seem to work better with phones (as opposed to emails). Although even when I have the setting as “Do not allow record to be saved” it still prompts to if I want to save it.

When I run this through code however I do get an error… sometimes.

If I have a matching phone type but different phone number it seems to work fine most of the time (although once I got an error message). If I have a matching phone type and phone number I will always get the error as shown below. This does not seem to be affected by the options above though.

duplicate phone error

I am wondering wondering if there is a way of controlling the error. If this were working as expected then it should be possible to permit the record to be saved if the options is “Display warning”.

Here is my test code:

 Public Sub TestSavingDuplicatePhones()
        Dim constit As New CRecord
        constit.Init SessionContext             

        constit.LoadByField uf_Record_CONSTITUENT_ID, "3"
        Dim parent As IBBPhonesParent
        Set parent = constit        

        Dim phone As CConstitPhone
        Dim phones As CConstitPhones
        Dim dataObj As IBBDataObject
        Dim phone2 As CConstitPhone
        Dim dataObj2 As IBBDataObject
        For Each phone In parent.phones
            Set dataObj = phone
            If dataObj.Fields(ECONSTITPHONEFIELDS.CONSTIT_PHONES_fld_PHONETYPE) = "Email" Then
                Set phones = parent.phones
                Set phone = phones.Add
                Set dataObj2 = phone
                dataObj2.Fields(ECONSTITPHONEFIELDS.CONSTIT_PHONES_fld_NUM) = "1234"
                dataObj2.Fields(ECONSTITPHONEFIELDS.CONSTIT_PHONES_fld_PHONETYPE) = "Email"                             

                Exit For
            End If

        Set constit = Nothing   
   End Sub

Working with Phones/Email without addresses in Raiser’s Edge 7.94

Prior to the release of The Raiser’s Edge version 7.94 I was working with all of our products to ensure compatibility with this latest version. If you have not heard (and if you have not heard where have you been hiding), this release of RE removes phones and emails from physical addresses.

When the concept of emails was new, it was possible that you would have an email address tied to your telephone provider or an email address specific to your place of work.  Your phone would either be at home or at work. Having these connnected to your physical address made sense. However it quickly became aparent that with the arrival of mobile phones and of email addresses that were accessible no matter where you were located, phones and emails (and for that matter all types of communication links) should be tied directly to the constituent record and not to a physical address. This is what has happened with the release of RE7.94.

This is a big shift and in terms of developing applications, we have had to allow for both possibilities so that our programs are compatible with users still on 7.93 and below and those that have made the leap over to 7.94.

The good news is that the old way of doing things still works in 7.94. You can still access phones via the CConstitAddress.Phones collection for an address. However you will probably want to access them how they are intended… Free from addresses.

This is done using the new interface IBBPhonesParent. This is implemented by CRecord, CIndividual2 and COrganization2. The collection of phones is a CConstitPhones object which contains the usual methods. You can iterate the collection to give you one CConstitPhone object but here is the problem.

For reasons that I don’t fully understand (I was told due to binary compatibility reasons) there are no properties or methods on the CConstitPhone object. Instead you have to convert this object to an IBBDataObject in order to access the Fields property. This is a real pain but to save myself some trouble I put together two extension methods for the CConstitPhone object which does this for me. (Unfortunately extension properties do not exist so that is why I cannot simply create an exact corresponding Fields properties. Those working with C# will be familiar with this as there is not a Fields property but rather  get_Fields and set_Fields methods)

<System.Runtime.CompilerServices.Extension()> _
Public Function Fields(ByVal phone As CConstitPhone, fieldConstant As ECONSTITPHONEFIELDS) As Object
   Dim dataobject As IBBDataObject = CType(phone, IBBDataObject)
   Return dataobject.Fields(fieldConstant)
End Function
<System.Runtime.CompilerServices.Extension()> _
Public Sub Fields(ByVal phone As CConstitPhone, fieldConstant As ECONSTITPHONEFIELDS, value As Object)
    Dim dataobject As IBBDataObject = CType(phone, IBBDataObject)
    dataobject.Fields(fieldConstant) = value
End Sub

With these extension method you can simply access the Fields methods on a CConstitPhone object in almost the same way as you would with other objects.

So here is an example of creating a new phone on a constituent record using the above extension code.

Dim constit As CRecord = GetConstituent()
Dim phonesParent As IBBPhonesParent
Dim phones As CConstitPhones
Dim phone As CConstitPhone

phonesParent = CType(constit, IBBPhonesParent)
phones = phonesParent.Phones
phone = phones.Add()

constit = Nothing

The Raiser’s Edge Integrated with Gmail… A series of case studies (1)

This is the first in a series of case studies looking at custom integration of Blackbaud products.

Unlike very many of our previous third party integration application the main driving force behind this application, Biographica, was the fact that we could do it. We did not have any particular client knocking on our door asking us link the two products and Google , funnily enough, did not approach us either asking us to develop an integration between The Raiser’s Edge and Gmail.

Continue reading The Raiser’s Edge Integrated with Gmail… A series of case studies (1)

Introducing RETweet Professional for The Raiser’s Edge

At the end of last year we released RETweet for all our newsletter subscribers (sign up to receive future offers and news). It was a great success allowing you to see your constituents’ Twitter feed directly from within The Raiser’s Edge. Now, with the release of RETweet Professional, you can search for any keyword, user or hashtag just as you would in Twitter. RETweet Professional brings you all the features of RETweet but also allows you to find out who is talking about your organisation and your mission. From the feed, RETweet Professional will look up the constituents using a fuzzy search [1], allow you create you own constituent if it cannot find it or you can search in RE using the regular search screen. The application gives you the option of connecting a Twitter user to a constituent and once you have done that you can save their tweet as a notepad. You can also set up a “love” attribute for use within RETWeet Professional. You can assign a value directly from the application and it will save onto the constiteunt record without you having to open it up.

Track the conversation that people are having about your organisation directly from within The Raiser’s Edge. Social media has been brought one step closer to your organisation.

Download RETweet Professional Demo (includes RETweet)


[1] On a technical note we are forced to do a fuzzy search as the only two identifying fields that we retrieve from Twitter are full name and location. We split up both of these fields into first and last name and city, state and country. For the location we attempt to see if the values we have assumed are in the code tables. If they are we know that we have assigned the values correctly. If they do not appear in the code tables then we do not assign the values on creating a constituent. When searching we give each term a weighting. Only constituents that match the last name or the first five characters of the organization name will ever appear in the fuzzy search results. After that each of the other terms’ weighting are added up to determine which results appear in the match. City and the full first name (as opposed to the person’s initial) are given a higher weighting so matches based on those values will appear more prominently.

Raiser’s Edge Integration with REST webservice

I have been working on a new version of RETweet which will be released soon. In that version we are allowing users to create constituents from Twitter users. The amount of information that you get from Twitter about the Tweet and the person that tweeted is very limited. The real name of the Twitter user – and it is not always a real name – is given in one field so it could include the first and last name (this is the most common where it is not a Tweeting business).  To make this more useful the application reaches out to a webservice to determine the gender of the person.

The webservice takes the first name and returns gender information and which countries the name appears in. The web service is biased towards European and Western first names but does claim to cover some countries in Asia too.

This could also easily be integrated as a VBA solution so that when you save and close a constituent record, if the gender is unknown the VBA code reaches out to the webservice and populates the code. Here is some sample code that shows you how this is done. This is done using .NET as it is considerably easier to achieve than in the native VBA environment. It would, however, be easy to make a call to a COM visible assembly from the native VBA client to call this method.


' Determines the gender of the person by looking up useing Thomas Bayer's webservice.
Private Sub SetGender(firstName As String, constit as CRecord) 

   Dim xdoc As XDocument
      'Here we retrieve the XML document from the REST web service
      xdoc = sendXML("http://www.thomas-bayer.com/restnames/name.groovy?name=" & firstName)

      Dim result = xdoc.<restnames>

      'if there is an error then the gender cannot be found
      If result.Descendants("error").Count > 0 Then
      End If

      'This is not an ideal check as a name can be both male and female
      'but for simplicity we assume this is not the case
      If resultresult.<nameinfo>.<male>.FirstOrDefault.Value.ToLower = "true" Then
         constit.Fields(ERECORDSFields.RECORDS_fld_GENDER) = "male"
         constit.Fields(ERECORDSFields.RECORDS_fld_GENDER) = "female"
      End If
         'If there is an error due to the web service we catch it here and don't bother the end user.
      End Try

End Sub

Private Function sendXML(ByVal uri As String) As XDocument

   Dim request As HttpWebRequest
   Dim response As HttpWebResponse
   Dim reader As XmlReader

   request = HttpWebRequest.Create(uri)
   response = request.GetResponse()

   reader = XmlReader.Create(response.GetResponseStream())
   Return XDocument.Load(reader)

End Function


Look out for our new version of RETweet. It will include this and a lot of other new features!

The challenges of developing generic solutions for The Raiser’s Edge

We develop a number of different types of solutions that connect The Raiser’s Edge with third party applications. When this is done for one organisation the hardest challenge is getting the requirements to match the end user’s as closely as possible. However we also develop a lot for third party applications directly. Most recently we released Chimpegration but there have been many others that integrate many different areas of the application. With these clients the important point is not so much as to match one set of requirements exactly but to match as many requirements exactly!

I have yet to come across two organisations that have set up RE the same way. Sometimes the differences are small but sometimes they are very large. One recurring theme is that of phone/email types. The Raiser’s Edge seems to be relatively unique in its setup of these values. Not only are phones and emails stored in the same location but you can store them according to address type too. How does this match up with a third party web application that uses email address as a primary key? They may have one field for home phone, one for mobile and possibly one other. How do you get that tie in with the possibility of any combination of phone and email types? I have seen a whole plethora of regular phone types e.g.

Home 1
Home 2

Those are just the ones I can think of as I write this. And of course each of these could have a number after them.

Then of course there is the proliferation of email (or is it e-mail, etc) addresses.

What techniques do we use to overcome these issues? When we are working with a third party developer directly it is often in their interest to develop the configuration piece. This saves them a lot of development cost. This means that we simply say to them if you want us to update a phone number you need to tell us which type it is. This is then supplied in the file/webservice. Likewise when we supply that piece of data, we also send the phone type too.

Another solution is to build a configuration part to the application. This is what we did with Chimpegration. We allow the end user to map the fields that they want to synchronise so that they specify which fields on MailChimp map to the fields on The Raiser’s Edge.

The last solution is the least desirable. It is possible to simply say that the home phone number should be called “Home” and email address should be called “Email” – end of story. This is clearly the simplest and cheapest but unless you have a lot of sway over the organisations that you are selling to it is unlikely that you are going to get many buyers.

Phone and email types are perhaps the most obvious but what other issues can arise?

Where you are collecting business details, should these be added to an organisation or to a business address on the constituent record? Should you create a new constituent for the organisation? How can you be sure that it does not already exist in the system but under a slightly different name. One solution is to allow the end user to review the matches that have been made but this again adds to the development cost. It could also be prohibitive if the volume of data you are bringing in is large.

What about fields that do not have an obvious place in The Raiser’s Edge. One application that we worked with had an anniversary date. There is no such field in RE. We gave the end user the option to ignore the field, store it has the spouse relationship from date or store it as an attribute.

What happens if one organisation makes a field mandatory? When I work with an organisation directly I will ask them what mandatory fields they have set up on their system. If, as part of the process, I have to create a new constituent then I will ask them to give me a default value for that field. For a generic solution this has to be worked into the application configuration.

You can see much of this in action in Chimpegration where we account for mandatory fields and different combinations of phone types and emails. Check out the synchronisation screencast for a glimpse of this in action.

So all said and done is this type of solution to be avoided? Absolutely not! It is not cheap because of the extra work involved in making the application work for all types of organisations. When people complain about NetCommunity or Patron Edge integrating badly with The Raiser’s Edge hopefully this article will have given you some insight as to the skills required by Blackbaud in getting the integration to work well. (Update 15th Dec 2011: I should clarify that given the difficulty in developing generic solutions I actually believe that Blackbaud have done a good job with these integrations)

If you are a third party application wondering how to integrate with The Raiser’s Edge then speak so us. We are skilled at doing this and have done it a lot. We can either do it for your or we can share the development. When done well it is a great asset to your company and will bring Raiser’s Edge users to your application.

Checking Constituents for a NetCommunity Login

I have been developing some updates for The Mergician. There are some nice additions coming soon including clean up of duplicate attributes and appeals following the merge. However one item that has been added is the request to select a record as the primary constituent if it has a NetCommunity Login associated with it. Continue reading Checking Constituents for a NetCommunity Login

Globally Merge Constituents using The Mergician

If you did not get Zeidman Development’s newsletter (you can sign up here) then you would not have heard about our latest plug-in – The Mergician.  The Mergician allows you to merge constituent records en masse. Currently The Raiser’s Edge allows you to merge two records together. Built off of the same functionality, The Mergician allows you to merge all your duplicates in one process. Continue reading Globally Merge Constituents using The Mergician

Looking up a constituent

Whenever I write a bespoke customisation for a client that needs to look up a constituent based on some biographical information I normally use the functionality available behind the scenes in IDLookup. If you are unfamiliar with IDLookup, it allows users to feed in an Excel or CSV file of names, addresses, aliases, attributes and all sorts of biographical information. Then based on criteria that you define, it will look to see if one or more constituents already exist in The Raiser’s Edge. I use much of the look-up functionality in other projects simply because Blackbaud chose not to make this functionality easily available. There is no back-end interface to their regular constituent look-up screen which is a real shame. The nearest feature is the IBBRecordFinder interface.

Continue reading Looking up a constituent