0 Draft Preschool Tuition Shared by Steve Lipinski, First Church of God of Columbia City 5 years ago 8.6 Administration / Finance, General, Operations Intermediate What An approach for managing Preschool Tuition and handling payments within Rock. Why We have a preschool at our church. Pre-Rock, this was all managed manually - rosters, parents, tuition and payments, etc. This also meant we could really only accept cash and check (some ACH with much hand-holding), and the management of those transactions, tuition totals, balances, students, etc. was also done manually. Once on Rock, we were able to easily manage our student class rosters as a Preschool Class Group Type, and with Dataviews and Transformations, we now had lists/groups to communicate with parents, etc. However - we were still missing the ability to manage tuition and, maybe more importantly, accept online payments towards tuition. I investigated using Fundraising Groups for this, but ran into a few hiccups. One of the main things was simply that the word 'Fundraising' ended up all over the place, in blocks, payment fields, etc. It was going to take some trickery to change a lot of the wording. Plus, it seemed like it was going to cause a disconnect with our current Roster approach without some more restructuring. Instead of using Fundraising Groups, I decided to do sorta what Fundraising Groups seem to do beneath the surface, but with our existing Group Types. How Overview One first needs a basic understanding of Entities, TransactionDetails, and GroupMembers. My rudimentary explanation of these, relevant to this recipe: An Entity is simply a type of data that's stored in Rock. Things like People, Groups, etc. are all entities. A Transaction is an Entity which consists of one or more sub-transactions, the TransactionDetail Entity. A GroupMember is another Entity that represents the membership of a specific Person in a specific Group. Thanks to things that were apparently implemented for Fundraising Groups, a TransactionDetail can be associated with another Entity by setting the EntityType and EntityId fields. For our purposes, linking a GroupMember to a TransactionDetail. You don't have to fully grasp how that works, but here is an example to help, using a notation of EntityType:ID so you can see the linkages: A Group exists that represents a preschool class, called 3-Step Group:1113. A child, named Suzie Sweetwater Person:5523, is added to that 3-Step class. Behind the scenes, Rock creates a group membership record linking Suzie Sweetwater to 3-Step GroupMember:11342. Mr. Sweetwater makes a check payment of $100 for Suzie's tuition Transaction:104->TransactionDetail:223. A staff member links that payment as a Tuition Payment for Suzie. To link, the TransactionDetail:223 record is updated with EntityType=GroupMember and EntityTypeId=11342. (This is the GroupMember ID and is the magic sauce that makes it possible to associate this payment towards Suzie's tuition balance) The above example assumes a manual payment processing (check, cash). It's important to note that if Mr. Sweetwater instead made the payment online, logged into our Rock-based website, the link between that Transaction and Suzie's tuition can happen automagically. Group Type First thing needed is to create a Group Type specific to the preschool classes. In our case, these also serve as Rosters for each preschool class. We use a Group Member Attribute on the Group Type to track the total tuition due for each student. (In our case, different students may have different tuition because of discounts, etc. - discounts are a definite area for future enhancement, but this is already probably complicated enough, so we'll save that for a future recipe...) Go to Admin | General | Group Types and create a Group Type for the preschool classes. There are lots of options here, and you may even want to inherit from some other Group Type that you use (like Classes), etc. Our Group Type is called Stepping Stones Classes since our preschool is named Stepping Stones. Setup any Roles or other settings on the Group Type that fit your situation. We have Roles of 'Currently Enrolled' and 'Teacher'. Add a Member Attribute (NOT Group or Group Type attribute!) and configure it as: Name: Tuition Total Key: TuitionTotal Field Type: Currency Required: Yes Show in Grid: Yes Enable History: Yes It will look like this when done: Save the new attribute, save the Group Type, then open it back up and modify the security on your new attribute to allow Edit rights to any security roles that need to be able to set or change this attribute on groups of this type. Class and Parents Groups Now need to create at least one group to represent a class and one group for all the preschool parents. I have created a Class Group called Chefs (get it?, Chefs, Recipes, :) ). I also created a General Group to hold the Parents, and be sure to set Security Role: Yes for the parents group. Here is our section of the Group Viewer Tree: Do note that we rely on this tree structure for our Data View, which is next. If you use a different group tree structure, that is fine, but you'll need to adjust the Data View filter accordingly. Feel free to add a child or two to this Group and set a tuition amount - it'll help ensure things are working later on. Parents Data View To make it easier on the External-facing website, we create a DV to find all the preschool students. We then set that DV to perform a transformation to Parents. This gives us a dynamic list of all the parents of all the preschool students. Go to Tools | Data Views and create a Data View for the preschool students. Place the DV wherever it fits for your organization. We have Categories for each Ministry, so it goes under our preschool ministry category. Configure it as: Name: Preschool Parents Applies To: Person Post-filter Transformation: Parents Set Filter Type: In Group(s) (Advanced); Select Group(s). In our case, I set the Roster parent Group and checked Include Child Group(s). This allows us to add more classes and not have to modify this DV. It will look similar to this when done: Save the Data View Parents Group Sync Go back and Edit the Group for the Parents and set it to Data Sync from the Data View that was just created. While editing the group, double-check that Security Role: Yes is checked. Front End Page You can now create the front-end (public facing) page(s) that parents of the preschool students can use to view and pay tuition. Not going to go into too much detail on how to create Pages and add Blocks for fear of this Recipe getting too long. What I did was create a Page on our External site with a Route of /Tuition. Then to ensure only parents of preschool students see this page, set the Page Security to Allow View permissions to the Security Role 'GROUPS - Preschool Parents' (or whatever you called it) and 'WEB - Administration', and Deny View on 'All Users'. Note - the order of these is important, 'All Users' must be last. Security settings similar to: This page will serve both as a family summary showing all the students in preschool, with their class (group) names and their tuition overview for each. There is a 'Make payment' button that when they click on goes to the same page itself but using a StudentId page parameter will now display a transaction block where the parents can make a payment towards that student's tuition. The existence of the StudentId parameter is used as the "toggle" of what this page displays. Once the page is created, add two Blocks to the Feature Zone. An HTML Content Block then a Transaction Entry Block, as follows: Edit the Student Tuition Information HTML Content Block. You can use the following as a starting point, and modify to your heart's desire: <!-- This is the Group Type Id for the preschool classes group type - this will definitely differ on your Rock --> {% assign classGroupTypeId = '51' %} <!-- Check that this is the correct Id for a GroupMember EntityType on your Rock --> {% assign gmEntityType = '90' %} <!-- This must match the key you gave the Class Group Type Attribute --> {% assign tuitionAttribute = 'TuitionTotal' %} {% assign student = 'Global' | PageParameter:'StudentId' %} {% if student and student != empty %} {% groupmember id:'{{student}}'%} <h3>Tuition Summary for {{ groupmember.Person.FullName }}</h3> <hr/> {% assign total = groupmember | Attribute:tuitionAttribute | AsDecimal %} {% assign paid = 0 %} {% financialtransactiondetail where:'EntityId == "{{ student }}" && EntityTypeId == {{ gmEntityType }}' %} {% for ftd in financialtransactiondetailItems %} {% assign paid = paid | Plus:ftd.Amount %} {% endfor %} {% endfinancialtransactiondetail %} {% assign due = total | Minus:paid %} {% endgroupmember %} Total Tuition: {{ total | FormatAsCurrency }}<br/> Paid to Date: {{ paid | FormatAsCurrency }}<br/> Outstanding Balance: {{ due | FormatAsCurrency }}<br/> <hr/> <h3>Tuition Payment for {{ groupmember.Person.FullName }}</h3> {% else %} <h3>Tuition Overview for the {{ CurrentPerson.PrimaryFamily.Name }}</h3> <hr/> {% assign children = CurrentPerson | Children %} {% for child in children %} {% assign groupMembers = child | Groups:classGroupTypeId %} <div class="family-tuition-overview container-fluid"> {% for groupMember in groupMembers %} {% assign paid = 0 %} {% assign total = groupMember | Attribute:tuitionAttribute | AsDecimal %} {% financialtransactiondetail where:'EntityId == "{{ groupMember.Id }}" && EntityTypeId == {{ gmEntityType }}' %} {% for ftd in financialtransactiondetailItems %} {% assign paid = paid | Plus:ftd.Amount %} {% endfor %} {% endfinancialtransactiondetail %} <div class="row student-tuition" style="margin-top: 25px;"> <div class="col-xs-12 col-sm-3 col-md-2 xs-text-center"> <img src="{{ 'Global' | Attribute:'PublicApplicationRoot' }}{{ groupMember.Person.PhotoUrl }}&maxwidth=200&maxheight=200" style="width: 100%; border-radius: 100px;"/> </div> <div class="col-xs-12 col-sm-3 col-md-2 xs-text-center"> <b>{{ groupMember.Person.FullName }}</b><br/><small>{{ groupMember.Group.Name }}</small> </div> <div class="col-xs-12 col-sm-4 col-md-4 xs-text-center"> Tuition Balance: <u>{{ total | Minus:paid | FormatAsCurrency }}</u><br/> <small>{{ paid | FormatAsCurrency }} of {{ total | FormatAsCurrency }} paid to date</small> </div> <div class="col-xs-12 col-sm-2 col-md-4 xs-text-center"> <br/> <a class="btn btn-default btn-md {% if paid >= total %}disabled{% endif %}" href="/Tuition?StudentId={{ groupMember.Id}}">Make Payment</a> </div> </div> {% endfor %} </div> {% endfor %} {% endif %} The above will give you a block that looks like this by default: And this when you click on the Make Payment button: Next, need to edit the Transaction Entry Block properties. Basic Settings as fit for your organization, with the following highlights that we use: Batch Name Prefix: Tuition Payments Account Header Template: Amount: Accounts: Select only one (as fit for your organization) Additional Accounts: Don't Allow Prompt for Phone: No Prompt for Email: Yes Payment Comment: Tuition Payment Enable Anonymous Giving: No Panel Title: Payment Contribution Info Title: Payment Information Personal Info Title: Payee Information Payment Info Title: Payment Information Success Title: Payment Submitted Save Account Title: Make Paying Even Easier (plus some modifications to the Header and Footer verbiage...) And, for Advanced Settings, we use some Lava+CSS to hide the transaction block when a Student is not selected. (If this was not done, the parent could post a transaction without it associating with a student - which we don't want). Plus, we want to set the linkage between the Transaction/TransactionDetail and the Student: CSS Class: tuitionPaymentEntry Pre-HTML: <style> {% assign student = 'Global' | PageParameter:'StudentId' %} {% if student and student != empty %} .tuitionPaymentEntry { display: block; } {% else %} .tuitionPaymentEntry { display: none; } {% endif %} </style> Allow Account Options in URL: No Transaction Type: Tuition Payment (as fit for your organization) Transaction Entity Type: Group Member Entity Id Param: StudentId Enable Initial Back Button: Yes Save the Block Properties. Now, when viewing the /Tuition page, you should not see the Transaction Entry block when viewing the Family overview. Once you click on the 'Make Payment' button for a student, the Transaction Entry block should appear under the Student Tuition info: Download File