David Turner on June 27th, 2009

Several people have asked for an update on Hannah…

My last post mentioned a drop in the number of seizures she was having and for most of June, Hannah didn’t have any seizures (during the daytime at least).  It was a nice relief for her (and for us).  Recently though she has started having more again, and she continues to experience negative side-effects of the medication.

We’ve decided to move forward with surgery which is scheduled for July 28th. In preparation for this, we’ve had several more visits to Phoenix Children’s Hospital.

Hannah had a comprehensive neuro-psychiatric exam to test things like IQ, behavior, motor skills, etc.  This test is done as a baseline so that when the same testing is administered a few months after surgery, we can tell what (if anything) has changed.

We also met with the surgeon who will be doing the surgery.  Talked a lot about the risks.  Several (like death and injury) are actually higher with uncontrolled seizures than they are with surgery.  Surgery does have a higher risk of infection and stroke though.  The stroke risk surprised me, but evidently, when they place the electrodes directly on the surface of the brain, there is the possibility that they could restrict necessary blood flow.  One of the most encouraging things I heard from the surgeon was that personality is not really affected when resecting only one side of the frontal lobe.  So… Hannah should still be “Hannah” after the surgery :).

It’s obviously a scary time for us.  Please keep Hannah in your prayers.  Thanks.

If your curious to learn more about the type of surgery that will be done, this video is very informative both about surgery and about epilepsy (with uncontrolled seizures).  I also described the procedure a bit in a previous post.

David Turner on June 15th, 2009

Earlier today, I received an email asking what functionality Arena provides when used to drive a church’s public website.  I thought I’d share my response…

Content Management System (CMS)

Arena is a CMS.  It may not be the fanciest and easiest to use CMS out there, but it provides all the functionality for configuring portals, templates, pages, modules, security, content, etc.  And by using templates, you can create an Arena driven site to look anyway you’d like.  The look and functionality of your site is only limited by the creativity of your designer.  You can be as “Web 2.0” and as you’d like using Arena templates.

The biggest advantage of using Arena as your CMS, however, is it’s integration with all the information you already have in the Arena membership system and the modules that have been created to take advantage of that information.

Promotions

The most powerful area of integration with Arena is promotions. Church staff can add promotions in Arena that are categorized, prioritized and approved and will then automatically be displayed on your public website. 

For example Canyon Ridge has configured a promotion display module to display the top three “All Church” promotions at the bottom of their home page…

clip_image002

There are several types of promotion display modules, each of which display your promotions in different ways.  A Flash module is even provided for animating Arena promotions.  An example of the Flash module can be seen on this CCV Stars page.

With promotions, the “web guy” doesn’t have to worry about adding or removing content when appropriate. As soon as a promotion’s date has passed, it is automatically removed from the site. Promotions can also be configured for different ministry areas (Men’s, Women’s Singles, etc.) and the website would show just promotions specific to those areas on their respective web pages.

But There’s More…

In addition to promotions, Arena can also drive the following functionality on your public site:

 

So, if you’re using Arena as your ChMS and not as your CMS, your going to miss out on a lot of built-in integration.

David Turner on May 28th, 2009

For a long time, we’ve been putting our staff anniversaries on our Arena home page each month…

image

I’m ashamed to say that until now, our department admin has been doing this manually each month.  I also noticed that she recently started changing the highlighting each day to indicate which anniversaries in the month had already passed.  Obviously a lot of manual work for what can easily be automated.

Since we’re tracking all this information in Arena, this was a perfect scenario for the HTML from Stored Procedure module.

 

First a stored procedure is needed to generate the HTML…

CREATE PROC [dbo].[cust_ccv_sp_staff_anniversaries]
@HireDateAttrID int,
@PositionAttrID int
AS

DECLARE @MonthName varchar(12)
DECLARE @HtmlMsgPtr binary(16)
DECLARE @TempMessage varchar(8000)

DECLARE @Today datetime
SET @Today = GETDATE()

CREATE TABLE ##StaffHtmlTable ([html] text)

INSERT INTO ##StaffHtmlTable VALUES ('<hr/>')
SELECT @HtmlMsgPtr = TEXTPTR([html])
FROM ##StaffHtmlTable

SET @TempMessage = '<table style="width: 570px; height: 201px; " cellspacing="0" cellpadding="0"><tbody><tr>' +
    '<td class="highlightText" valign="top" align="left">' +
    '<img src="/Arena/Content/HtmlImages/Public/Images/General/icon_birthday.gif" />' +
    '<strong><font color="#808080" size="3">' + DATENAME(month, @Today) + ' Birthdays</font></strong></td>' +
    '<td class="highlightText" valign="top" align="left">' +
    '<img src="/Arena/Content/HtmlImages/Public/Images/General/award.jpg" />' +
    '<strong><font color="#808080" size="3">' + DATENAME(month, @Today) +
    ' Staff Years of Service</font></strong></td></tr><tr><td class="highlightText" valign="top">'
UPDATETEXT ##StaffHtmlTable.[html] @HtmlMsgPtr null 0 @TempMessage

DECLARE @StaffName varchar(100)
DECLARE @AnnivDate datetime
DECLARE @Position varchar(250)

DECLARE BirthDateCursor CURSOR READ_ONLY FOR
SELECT
    nick_name + ' ' + last_name,
    birth_date
FROM core_person
WHERE staff_member = 1
AND birth_date <> '1/1/1900'
AND MONTH(birth_date) = MONTH(@Today)
ORDER BY DAY(birth_Date), last_name, nick_name

OPEN BirthDateCursor

FETCH NEXT FROM BirthDateCursor
INTO    @StaffName,
        @AnnivDate

WHILE (@@FETCH_STATUS <> -1)
BEGIN

    IF (@@FETCH_STATUS = 0)
    BEGIN

        -- Date
        IF DAY(@AnnivDate) < DAY(@Today)
            SET @TempMessage = '<font color="#a9a9a9">'
        ELSE
            SET @TempMessage = '<font color="#000000">'
        SET @TempMessage = @TempMessage + CAST(MONTH(@AnnivDate) as varchar) + '/' + CAST(DAY(@AnnivDate) as varchar)
        IF DAY(@AnnivDate) < 10
            SET @TempMessage = @TempMessage + '&nbsp;&nbsp;'
        ELSE
            SET @TempMessage = @TempMessage + '&nbsp;'

        SET @TempMessage = @TempMessage + '<strong>' + @StaffName + '</strong></font><br/>'
        UPDATETEXT ##StaffHtmlTable.[html] @HtmlMsgPtr null 0 @TempMessage

    END

    FETCH NEXT FROM BirthDateCursor
    INTO    @StaffName,
            @AnnivDate

END

CLOSE BirthDateCursor
DEALLOCATE BirthDateCursor

SET @TempMessage = '</td><td class="highlightText" valign="top">'
UPDATETEXT ##StaffHtmlTable.[html] @HtmlMsgPtr null 0 @TempMessage

DECLARE HireDateCursor CURSOR READ_ONLY FOR
SELECT
    nick_name + ' ' + last_name,
    HD.datetime_value,
    POS.varchar_value
FROM core_person P
INNER JOIN core_person_attribute HD
    ON HD.person_id = P.person_id
    AND HD.attribute_id = @HireDateAttrID
LEFT OUTER JOIN core_person_attribute POS
    ON POS.person_id = P.person_id
    AND POS.attribute_id = @PositionAttrID
WHERE P.staff_member = 1
AND ISNULL(MONTH(HD.datetime_value),0) = MONTH(@Today)
AND ISNULL(YEAR(HD.datetime_value),0) < YEAR(@Today)
ORDER BY ISNULL(DAY(HD.datetime_value),0), last_name, nick_name

OPEN HireDateCursor

FETCH NEXT FROM HireDateCursor
INTO    @StaffName,
        @AnnivDate,
        @Position

WHILE (@@FETCH_STATUS <> -1)
BEGIN

    IF (@@FETCH_STATUS = 0)
    BEGIN

        DECLARE @Years int
        SET @Years = YEAR(@Today) - YEAR(@AnnivDate)

        -- Date
        IF DAY(@AnnivDate) < DAY(@Today)
            SET @TempMessage = '<font color="#a9a9a9">'
        ELSE
            SET @TempMessage = '<font color="#000000">'
        SET @TempMessage = @TempMessage + CAST(MONTH(@AnnivDate) as varchar) + '/' + CAST(DAY(@AnnivDate) as varchar)
        IF DAY(@AnnivDate) < 10
            SET @TempMessage = @TempMessage + '&nbsp;&nbsp;'
        ELSE
            SET @TempMessage = @TempMessage + '&nbsp;'

        SET @TempMessage = @TempMessage + '<strong>' + @StaffName + '</strong>, ' + @Position + ' - <strong>' + CAST(@Years as varchar)
        IF @Years > 1
        BEGIN
            IF @Years >= 5
                SET @TempMessage = @TempMessage + ' Years!'
            ELSE
                SET @TempMessage = @TempMessage + ' Years'
        END
        ELSE
            SET @TempMessage = @TempMessage + ' Year'

        SET @TempMessage = @TempMessage + '</strong></font><br/>'
        UPDATETEXT ##StaffHtmlTable.[html] @HtmlMsgPtr null 0 @TempMessage

    END

    FETCH NEXT FROM HireDateCursor
    INTO    @StaffName,
            @AnnivDate,
            @Position

END

CLOSE HireDateCursor
DEALLOCATE HireDateCursor

SET @TempMessage = '</td></tr></table>'
UPDATETEXT ##StaffHtmlTable.[html] @HtmlMsgPtr null 0 @TempMessage

SELECT [html] FROM ##StaffHtmlTable

DROP TABLE ##StaffHtmlTable

 

This stored procedure expects a couple person attribute IDs for the Hire Date and Position…

image

 

And then a new HTML From Stored Procedure module is added to our Arena homepage. Notice the two person attribute ID values that are passed to the stored procedure in the Parameters setting.

image

 

I love doing these quick little things that help someone save a lot of time. 

(if you want to use the same stored procedure, here’s the two images we use…

 icon_birthday award )

David Turner on May 26th, 2009

It has this week! 

A lot of people are praying for Hannah. Last Wednesday, even my team at work took time out of the morning to walk up the prayer hill and pray. 

For the last several weeks Hannah has been averaging about 10 seizures a day.  That changed this weekend. Here’s a chart that we use to track her seizures.  Notice the last several days…

You need to upgrade your Flash Player



We haven’t changed anything else.  No medication changes, no diet changes, nothing. Just prayer.  After hours without seizures this weekend, My wife and I found ourselves looking at each other and wondering aloud  ”What’s going on here?”

A lot of people are praying for Hannah, and what a powerful “coincidence” that is evident in that chart.  Will the number of her seizures continue to drop? Will God heal her?  I don’t know.  I know that he can, but I also know that there so much more to God’s will than I’ll ever understand.  For now I’ll just continue to pray for her healing, for a break from the barrage of seizures, and for wisdom to know what to do given the options we have available.

David Turner on May 24th, 2009

“Focal Cortical Resection” is a term we’re having to become a little more acquainted with these days.  We met with Hannah’s neurologist on Thursday to discuss her test results and where we go from here.  Looks like surgery is the "best" option available to us.  Her tests indicate that the seizures are originating somewhere in the left frontal lobe.  

The surgery would be a Focal Cortical Resection and would actually involve two different procedures.  During the first procedure, the surgeon will make an incision, remove the bone, pull back the dura and then place a grid of electrodes directly on the surface of the brain.  They will then put the bone back, or maybe just put it in the freezer (not kidding), and stitch her back up.  Then for the next 5-7 days they monitor electrical activity from the grid of electrodes to try and pinpoint further the location of the seizures.  They also send electrical impulses to these electrodes to see what parts of her body responds (moves).

The hope is that the electrodes that indicate where the seizure originates from are not the same electrodes that cause movement.  If they are, the second phase of surgery cannot be done.  The second procedure would be the actual resection to remove as much as possible (the more that is removed the higher the success rate of eliminating seizures).

All the docs (neurologists, surgeons, psychiatrists, etc) are meeting Monday June 1st, to discuss Hannah’s case and then we should be scheduling the surgery.  Will probably be sometime in July, and she’ll be in the hospital for about two weeks.

As you can imagine we’re very conflicted about her treatment.  She is having 10+ seizures a day (and more while she sleeps).  As one medical paper puts it, she needs surgery "…before irreversible deterioration in cognitive or psychosocial functions ensues due to long-standing disabling seizures and chronic antiepileptic drug-related side effects."  On the other hand, the success rate of surgery is 50-60% runs the risk of her losing movement, and more… The frontal lobe controls emotions, reasoning, planning, movement, and parts of speech.  It is also involved in purposeful acts such as creativity, judgment, problem solving, and planning.  That’s a lot of stuff!

If you’re praying for her, keep it up.  Thanks.

David Turner on May 23rd, 2009

Not sure anyone is going to see this post, since I moved and didn’t tell anyone.

Why?

I wanted a new blog.  I wasn’t thrilled by how dated my old blog looked, and I think I’m also going to try and write more often (let’s say… oh… at least once a week).  Figured I’d clean it up first, so I ditched my old BlogEngine.NET blog hosted at GoDaddy, and went with a WordPress blog hosted at Dreamhost (all my friends we’re doing it).

I did update the nameservers for my domain, but because of differences between the WordPress feed and the old feed, and because of some strange things happening in my FeedBurner account, I’m pretty sure I’m writing this post only for me.  But… If I’m wrong, and you see me, say hello.

What’s Different?

I was challenged by my friend and fellow blogger Erik, to include more posts about me (you know real-world stuff) and not just stuff about Arena.  So while I will keep posting things about Arena (and other work stuff), I’ll also try and add some things about what captivates me when I’m not at my day job.

And That Is?

So what captivates me when I’m not at work.  Well… I have a 16 year old son who hasn’t quite got his license yet, but works a lot as a Lifeguard and is big into dirt bikes, so I spend  a great deal of my time driving him around and hanging out with him at the dirt track.  My 10 year old daughter has Refractory Epilepsy so we’re trying to manage her 10+ seizures a day and considering the alternatives for her treatment (surgery).  She still is my best movie partner as we seem to be the only two in the family who really enjoy intense action movies.  My 7 year old son is autistic (high functioning), and is my biggest helper.  Him and I are the two morning people and are often long at work in the yard together before anyone else is even up.  And of course my wife.  She helps me to survive it all.

Wow… that kinda felt like I was filling out an online dating ad (good thing no one is reading it anyway).  Next post is going to be about Arena.

David Turner on February 24th, 2009

In the interest of possibly helping anyone else set up their podcast, here’s how Arena podcasting is configured in our environment (You can click on any of these images to see them full size).

Feed Formats

Before setting up any channels, you’ll need to setup your available feed formats in the Arena Administration area.

PodcastFeedFormats

XSLT

Arena uses an rss.aspx page to convert an XML version of your feed into a standardized RSS feed format.  This gives you control over fine-tuning how the RSS content is generated (You can view both the XML and the XSLT from the Channel overview page).  Here’s a copy of our xslt/rss/default.xslt file.  This XSLT file creates an RSS feed that is also compliant with iTunes requirements…

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">

    <xsl:output method="xml" version="1.0" encoding="utf-8"/>

    <xsl:template match="/">
        <rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
            <xsl:for-each select="/*">
                <channel>
                    <title>
                        <xsl:value-of select="@author"/>: <xsl:value-of select="@title"/> (<xsl:value-of select="format/@title"/>)
                    </title>
                    <link>
                        <xsl:value-of select="@link"/>
                    </link>
                    <language>
                        <xsl:value-of select="@language"/>
                    </language>
                    <copyright>
                        <xsl:value-of select="@copyright"/>
                    </copyright>
                    <description>
                        <xsl:value-of select="description"/>
                    </description>
                    <itunes:subtitle>
                        <xsl:value-of select="@subtitle"/>
                    </itunes:subtitle>
                    <itunes:author>
                        <xsl:value-of select="@author"/>
                    </itunes:author>
                    <itunes:summary>
                        <xsl:value-of select="description"/>
                    </itunes:summary>
                    <itunes:owner>
                        <itunes:name>
                            <xsl:value-of select="@contactname"/>
                        </itunes:name>
                        <itunes:email>
                            <xsl:value-of select="@contactemail"/>
                        </itunes:email>
                    </itunes:owner>
                    <itunes:image>
                        <xsl:attribute name="href">
                            <xsl:value-of select="@imageurl"/>
                        </xsl:attribute>
                    </itunes:image>
                    <xsl:for-each select="category">
                        <xsl:call-template name="categorynode"></xsl:call-template>
                    </xsl:for-each>
                    <xsl:for-each select="items/item">
                        <xsl:call-template name="itemnode"></xsl:call-template>
                    </xsl:for-each>
                </channel>
            </xsl:for-each>
        </rss>
    </xsl:template>

    <xsl:template name="categorynode">
        <itunes:category>
            <xsl:attribute name="text">
                <xsl:value-of select="@text"/>
            </xsl:attribute>
            <xsl:for-each select="category">
                <xsl:call-template name="categorynode"></xsl:call-template>
            </xsl:for-each>
        </itunes:category>
    </xsl:template>

    <xsl:template name="itemnode">
        <item>
            <title>
                <xsl:choose>
                    <xsl:when test="topic">
                        <xsl:choose>
                            <xsl:when test="topic/@title = @title">
                                <xsl:value-of select="@title"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:value-of select="topic/@title"/>: <xsl:value-of select="@title"/>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="@title"/>
                    </xsl:otherwise>
                </xsl:choose>
            </title>
            <pubDate>
                <xsl:value-of select="@publish"/>
            </pubDate>
            <itunes:author>
                <xsl:value-of select="/channel/@author"/>
            </itunes:author>
            <xsl:if test="@imageurl">
                <itunes:image>
                    <xsl:attribute name="href">
                        <xsl:value-of select="@imageurl"/>
                    </xsl:attribute>
                </itunes:image>
            </xsl:if>
            <itunes:summary>
                <xsl:value-of select="description"/>
            </itunes:summary>
            <description>
                <xsl:value-of select="description"/>
            </description>

            <link>
                <xsl:value-of select="@link"/>
            </link>
            <enclosure>
                <xsl:attribute name="url">
                    <xsl:value-of select="enclosure/@url"/>
                </xsl:attribute>
                <xsl:attribute name="length">
                    <xsl:value-of select="enclosure/@duration"/>
                </xsl:attribute>
                <xsl:attribute name="type">
                    <xsl:value-of select="enclosure/@mimetype"/>
                </xsl:attribute>
            </enclosure>
            <itunes:keywords>
                <xsl:value-of select="keywords"/>
            </itunes:keywords>
            <xsl:if test="enclosure/@time">
                <itunes:duration>
                    <xsl:value-of select="enclosure/@time"/>
                </itunes:duration>
            </xsl:if>
        </item>
    </xsl:template>

</xsl:stylesheet>

 

Arena Page Setup

Here’s how our Podcasting administrative pages are setup in Arena

PodcastAdministrationSetup

The first “Podcast Channels” page simply redirects to the second (not sure why, but that’s how it is). 

The second “Podcast Channels” page has the ChannelList module.

The “Channel Details” page has the ChannelDetail and ChannelTabs (Show Filter setting is set to True) modules.

The “Item Details” page has the ItemDetail module.  
Note: I think there’s a bug with the smart page setting on this module.  It’s looking for a page above this one with the ItemList module which does not exist.  Our setting points to the Channel Detail page above it.

The “Topic Details” page has the TopicDetail module.

Note: Similar bug here.  It has a smart page setting that looks for a page above this one with the TopicList module.  Our setting again points to the Channel Detail page above it.

The “Topic Item Detail” page has the ItemDetail module.

Note: Same bug.  Our Item List Page setting points to the Topic Details page above this page.

       

Public Pages

Here’s how the public pages on our website are configured…

PodcastWebsiteSetup

The “Online Message” page in addition to several html modules has the ChannelView module.

Settings Used: Heading = blank, Image Size = 452, Item View Page = “Message” page below this one, SubHeading = blank, Topic View Page = “Series” page below this one, Use Topic View = True.

The “Series” page has the TopicView module.

Settings Used: Heading = blank, Image Size = 452, Item View Detail Page = “Message” page below this one, SubHeading = blank.

The “Message” page has the ItemFlashViewer module.

Settings Used: Email Message = blank, Flash Format = Flash Video, Image Size = blank, Object Height = 260, Object Width = 320.

 

Channel Overview…

Here’s an example of how our contemporary service podcast is setup.

PodcastChannelView

You’ll notice that we use FeedBurner as our external feed so that when people subscribe to the feed they’ll see the FeedBurner url instead of our internal url.  We’ve then configured the Feedburner acount to point back to the actual arena url(http://arena.ccvonline.com/Arena/rss.aspx?c=1&f=1).

 

Details…

PodcastChannelDetails

 

Enclosure Types…

PodcastChannelEnclosures

 

Topic…

PodcastTopicView

 

Item Overview…

PodcastItemView

 

Item Details…

PodcastTopicDetails

You’ll notice that we use various third-party hosting providers to store our actual video and audio content to cut down on bandwidth to our internal servers.  podcasts.ccvonline.com actually points to an Amazon S3 server.

 

Hope that helps, comment for any questions.

David Turner on June 16th, 2008

You may have noticed that when creating an occurrence in Arena, you can associate it with an area….

image

This is useful if you are providing Area specific pages on your web site and you’d like people to see any events that are occurring for that area, or you’d like your area leaders be able to add and edit events specific to their area.

The occurrence list module will display all occurrences specific to an area as long as you have the Area Filter Parameter value set…

image

This value is what the module will look for on the Query string to determine if it should just display occurrences for a specific area.  Because the public Area page has “area” in the query string, placing this module on the page will display all occurrences for the current area.

You can also add a link to an area specific list in the Arena application by using the Tool tab in the Area Detail page.

David Turner on June 13th, 2008

A cool feature on the Area Details page of Arena is the ability to customize the "Tools" tab to include any HTML that you’d like.  When editing the settings of the Area Detail module, any HTML that you include in the Details section will be displayed in the Tools tab.

For example, this the HTML that we’ve entered for our Area Details module…

<div class="heading2">Tools</div>
<div class="normalText" style="padding-left:15px">
    <a href='default.aspx?page=1437&Area=<area_id>'><area_name> Events</a><br/>
    <a href='default.aspx?page=4065&Area=<area_id>'>View <area_name> Families</a><br/>
</div>
<div class="heading2" style="padding-top:20px">Reports</div>
<div class="normalText" style="padding-left:20px">
    <a href='default.aspx?page=3987&title=<area_name_encoded> Members, Attenders and Guest Book Signers&AreaID=<area_id>' target='_blank'><area_name> Members, Attenders and Guest Book Signers</a><br/>
</div>

As you can see in this example there are some codes you can enter that will be replaced with data from the current Area that is being displayed..

<area_id> will be replaced with the area’s ID

<area_name> will be replaced with the area’s name

<area_name_encoded> will be replaced with a URLEncoded version of the area’s name.

We use this functionality to link to area specific occurrences (next post), an Area specific person search page (using the AreaPersonFilter module), and to area specific custom reports.

David Turner on May 5th, 2008

imageThe Metric functionality in Arena is a very powerful tool for viewing changes in data over time (yes, I know, the UI could still use some improvements).  Essentially it allows you to create any number of metrics by specifying a SQL statement that just returns one numeric value.  Arena will then run that statement how ever often you decide, save the result, and chart the values over time. 

You can also set up a metric that isn’t linked to Arena data but instead is hand-entered (i.e. Total Weekend Attendance)

 

Membership Status Metrics

Since you may not have gotten any sample metrics out of the box, here’s a SQL script that will add a few for you…

DECLARE @OrganizationID int
SET @OrganizationID = (SELECT TOP 1 organization_id FROM orgn_organization)

DECLARE @AllUsers int
SET @AllUsers = (SELECT TOP 1 role_id FROM secu_role WHERE role_name = 'All Users')

DECLARE @ParentMetricID int
DECLARE @MetricID int

-- Create Parent Metric
INSERT INTO [Arena].[dbo].[mtrc_metric]
       ([date_created]
       ,[date_modified]
       ,[created_by]
       ,[modified_by]
       ,[parent_metric_id]
       ,[metric_order]
       ,[graph_type]
       ,[title]
       ,[series_caption]
       ,[description]
       ,[source_summary]
       ,[collection_frequency]
       ,[collection_last_date]
       ,[collection_sql_statement]
       ,[organization_id]
       ,[aggregate_type]
       ,[numeric_x_values])
     VALUES
       (GETDATE()
       ,GETDATE()
       ,''
       ,''
       ,NULL
       ,1
       ,-1
       ,'Membership Status'
       ,''
       ,'Metric to show the number of people of each Membership Status over time'
       ,''
       ,0
       ,'1/1/1900'
       ,''
       ,@OrganizationID
       ,'MAX'
       ,0)    

SET @ParentMetricID = SCOPE_IDENTITY()

INSERT INTO [Arena].[dbo].[secu_permission]
       ([date_created]
       ,[date_modified]
       ,[created_by]
       ,[modified_by]
       ,[object_type]
       ,[operation_type]
       ,[subject_type]
       ,[object_key]
       ,[subject_key])
    VALUES
        (GETDATE()
        ,GETDATE()
        ,''
        ,''
        ,6
        ,0
        ,0
        ,@ParentMetricID
        ,@AllUsers )

INSERT INTO [Arena].[dbo].[secu_permission]
       ([date_created]
       ,[date_modified]
       ,[created_by]
       ,[modified_by]
       ,[object_type]
       ,[operation_type]
       ,[subject_type]
       ,[object_key]
       ,[subject_key])
    VALUES
        (GETDATE()
        ,GETDATE()
        ,''
        ,''
        ,6
        ,1
        ,0
        ,@ParentMetricID
        ,@AllUsers )

DECLARE @LookupID int
DECLARE @LookupValue varchar(50)
DECLARE @LookupOrder int

DECLARE MemberStatusCursor CURSOR LOCAL FOR
    SELECT
        lookup_id,
        lookup_value,
        lookup_order
    FROM core_lookup L
    INNER JOIN core_lookup_type LT ON LT.lookup_type_id = L.lookup_type_id
    WHERE LT.guid = '0B4532DB-3188-40F5-B188-E7E6E4448C85'

OPEN MemberStatusCursor

FETCH NEXT FROM MemberStatusCursor
INTO @LookupID, @LookupValue, @LookupOrder

WHILE @@FETCH_STATUS = 0
BEGIN

    INSERT INTO [Arena].[dbo].[mtrc_metric]
           ([date_created]
           ,[date_modified]
           ,[created_by]
           ,[modified_by]
           ,[parent_metric_id]
           ,[metric_order]
           ,[graph_type]
           ,[title]
           ,[series_caption]
           ,[description]
           ,[source_summary]
           ,[collection_frequency]
           ,[collection_last_date]
           ,[collection_sql_statement]
           ,[organization_id]
           ,[aggregate_type]
           ,[numeric_x_values])
        VALUES
           (GETDATE()
           ,GETDATE()
           ,''
           ,''
           ,@ParentMetricID
           ,@LookupOrder
           ,0
           ,'Number of ' + @LookupValue + 's'
           ,@LookupValue + 's'
           ,'Number of people classifed as "' + @LookupValue + '"'
           ,''
           ,2
           ,GETDATE()
           ,'SELECT COUNT(*) AS people_count FROM Arena.dbo.core_person WHERE record_status = 0 AND member_status = ' + CAST(@LookupID as varchar)
           ,@OrganizationID
           ,'MAX'
           ,0)

    SET @MetricID = SCOPE_IDENTITY()

    INSERT INTO [Arena].[dbo].[secu_permission]
           ([date_created]
           ,[date_modified]
           ,[created_by]
           ,[modified_by]
           ,[object_type]
           ,[operation_type]
           ,[subject_type]
           ,[object_key]
           ,[subject_key])
        VALUES
            (GETDATE()
            ,GETDATE()
            ,''
            ,''
            ,6
            ,0
            ,0
            ,@MetricID
            ,@AllUsers )

    INSERT INTO [Arena].[dbo].[secu_permission]
           ([date_created]
           ,[date_modified]
           ,[created_by]
           ,[modified_by]
           ,[object_type]
           ,[operation_type]
           ,[subject_type]
           ,[object_key]
           ,[subject_key])
        VALUES
            (GETDATE()
            ,GETDATE()
            ,''
            ,''
            ,6
            ,1
            ,0
            ,@MetricID
            ,@AllUsers )

    FETCH NEXT FROM MemberStatusCursor
    INTO @LookupID, @LookupValue, @LookupOrder

END

CLOSE MemberStatusCursor
DEALLOCATE MemberStatusCursor

Running this script will create a parent “Membership Status” metric and then a child metric for each Member Status you’ve defined (and grants the “All Users” role view and edit permissions).

Each of the child metrics will chart the number of people of that member status over time.  As long as the ArenaProcessMetrics agent is running, you will see a chart after it’s collected the metrics data twice (two weeks from now).

 

Historical Data

If you don’t want to wait two weeks to see your data and/or you want to see all your historical member status data up to this point, we can use the core_member_status_history table to generate historical membership status data for your metrics…

SET NOCOUNT ON
GO

DECLARE @ParentMetricID int
DECLARE @MinHistoryDate datetime
DECLARE @WorkingDate datetime
DECLARE @Status varchar(15)

SET @ParentMetricID = (SELECT MAX(metric_id) FROM mtrc_metric WHERE title = 'Membership Status' AND parent_metric_id IS NULL)
SET @MinHistoryDate = (SELECT MIN(date_created) FROM core_member_status_history)
SET @WorkingDate = GETDATE()

DELETE mtrc_metric_item
FROM mtrc_metric_item MI
INNER JOIN mtrc_metric M ON M.metric_id = MI.metric_id
WHERE M.parent_metric_id = @ParentMetricID

WHILE @MinHistoryDate IS NOT NULL
AND @WorkingDate > @MinHistoryDate
BEGIN

    SET @Status = CONVERT(varchar(10), @WorkingDate, 101) + '...'
    RAISERROR (@Status, 0, 1) WITH NOWAIT;

    WITH memberStatusTable (person_id, member_status)
    AS
    (
        SELECT
            person_id,
            ISNULL((SELECT TOP 1 member_status
                FROM core_member_status_history
                WHERE person_id = P.person_id
                AND date_created < @WorkingDate
                ORDER BY date_created DESC), p.member_status) AS member_status
        FROM core_person P
        WHERE date_created <= @WorkingDate
    )

    INSERT INTO mtrc_metric_item
    SELECT
         GETDATE()
        ,GETDATE()
        ,''
        ,''
        ,M.metric_id
        ,(SELECT COUNT(*)
            FROM memberStatusTable
            WHERE member_status = L.lookup_id)
        ,@WorkingDate
        ,''
        ,0
    FROM core_lookup L
    INNER JOIN core_lookup_type LT
        ON LT.lookup_type_id = L.lookup_type_id
    INNER JOIN mtrc_metric M
        ON M.title = 'Number of ' + L.lookup_value + 's'
        AND M.parent_metric_id = @ParentMetricID
    WHERE LT.guid = '0B4532DB-3188-40F5-B188-E7E6E4448C85'

    SET @WorkingDate = DATEADD(wk, -1, @WorkingDate)

END

This script will create data for the metrics you created above for as far back as you have data in the core_member_status_history table.