Hey there,
It's Sean again with another installment of the template development walkthrough. Last time we covered the list schema for the Employee Training Scheduling and Materials template, one of the new Application Templates for Windows SharePoint Services 3.0. In this series I'm showing you how we built one of these templates from the ground up, and today we're going to author all of the training site's workflows using SharePoint Designer. With that done, you'll have built the whole back-end of the template, so in a future installment we'll get our hands dirty with SharePoint's views and forms.
Open up a fresh installation of the training site in SPD and you'll see the folder list pictured on the right - with the three workflows you'll be creating today in the Workflow Designer. They'll provide some of the rich behavior that you wouldn't see in a static web app, and you won't need to write any code to get it done. Let's get started!
Automatic Reminders
People are forgetful. Computers aren't. So when an instructor comes to your training site to create a course, why should they have to remember when it is? That's where you can come in with this workflow, which we'll set on the Courses list:
From here you'll want to create 3 steps which will logically separate our workflow into sets of related actions. Click Add workflow step to move on to the next step, and in each case if you don't see the specific action listed, click the Actions button > More Actions... to see the full list. Additionally I'm using [brackets] to refer to what you need to do in each placeholder.
Also, fx just means the data binding button. You get the same dialog whenever you push Add Lookup to Body in the e-mail builder.
So before you start, first create two variables (click Variables... > Add... to make them), one called "Reminder Time" (Date/Time) and one called "Subject" (String). You'll need them once you get to the individual steps:
Make sense? We're sending two reminders to anyone who adds a new item to the Courses list (i.e. an instructor creating a course) - one right when they make it as a confirmation, and another 24 hours before the course is scheduled. And the first step was just to keep the variable assignment separate, there's nothing wrong with doing it in the other steps right before they are used.
We'll want to do a similar reminder for students, but we can do it at the same time that we enforce seating policy (each item in Courses has an Available Seats and Total Seats) since it only really makes sense to send reminders if you actually make it into a course.
Processing Student Registrations
If you try to add a new course by browsing to Courses > New..., you'll see this line in the new form:
And you'll also notice that there's no line for Available Seats or Filled Seats, even though we added those fields to the Courses schema in part one. I'll teach you the trick to hide form items next time, what's important here now is that 0 will be our sentinel value in the workflow to come.
Let's go through this one a bit faster by using some shorthand.
Start with a new workflow called "Attendee registration," attached to Registrations and triggered when an item is created. Create 7 variables before you begin, 4 of type String (Subject, Confirmation Body, Reminder Body, Reminder Body 2), 2 Date/Time (Reminder Time, Reminder Time 2), and 1 Number (New Filled Seats). From there build out the steps:
Yikes, I know. But thankfully that's about as bad as it gets. Here's a brief explanation - a student will register for a course, but they won't get in right away (technically, they get in but they may be kicked out immediately if the seating logic fails). After setting all the variables we check if Total Seats is 0 (unlimited) or greater than Filled Seats (i.e. is there room in the course?). If not, we abort prematurely (delete/stop step two), otherwise we do the math and add 1 to the Filled Seats, send reminders, etc. The last step is the archival in the mirror list Past Registrations, something that will become more evident in part three when we build up the front end.
A Dirty Workflow Secret
That's all well and good, but what happens when someone wants to unregister from the course? We need to subtract 1 from the number of Filled Seats, then delete their registration from Registrations, but here's a problem - workflow cannot be triggered to run before an item is deleted. So here's how we'll fake it - since workflow can run when an item is changed, we'll set up another sentinel value for our workflow to be interested in. DELETE seems pretty self explanatory, right?
(Note that this workaround has some serious implications - we'll need to hide item deletion in Registrations and block all edits to our field so the user never trips the sentinel. Don't worry, I'll explain in due time...)
Our last workflow, "Attendee unregistration" (for lack of a better word), attached to Registrations, triggered when an item is changed. One variable before you start: a String called Log Message. Not even really necessary, just for posterity:
And there you have it, dynamic behavior that takes a long time to spell out in a blog post, but goes a long way towards the richness and robustness of your SharePoint app. It's taken us a few key design decisions to get here, and so in part three we'll learn what consequences that holds for the front end system, which is driven by SharePoint views and forms. I'll see you then!
Cheers,Sean
Pat/Simon,
I have a series of articles that cover what is missing in the template (they compliment this series and fill in the missing pieces).
This one specifically: http://www.sharepointblogs.com/dez/archive/2007/09/19/employee-training-and-scheduling-template-a-couple-fixes-part-2.aspx
Covers how to change the XSL for the "my courses" webpart to remove the user from the correct course.
Hope it helps,
- Dink
Frist44 and Jimmy,
I'm also interested in the question about course dates changing and related workflow issues. Any information out there?
Eric
Is there a way to integrate this with MySites? The idea is that after a learner completes X number of courses and tests, that he would be "certified". Or is there a better way to track certification?
Thanks,
Deepak
I find that this does not work:
"Unregister from course"
Conditions > Compare Registrations field - If Title equals "DELETE"
Actions > Delete Item - Delete item in Registrations (Current Item)
Actions > Build Dynamic String - Store ... in Variable: Log Message
Actions > Stop Workflow - Stop the workflow and log Variable: Log Message
Appears to be a need to minus 1 from the available seats
When attempting to complete step 2 and 3 of the instructor reminder workflow:
(Second step: name it "Send confirmation"
No conditions
Actions > Send an Email - Email [...]
To: Workflow Lookup... :: Current Item, Instructor)
"Instructor" is not an option from the drop down once I select "Current Item". (However, Created by and Modified by ARE options). Not sure how to fix this-- I've deleted and recreated the column a couple of times....
I need to send out a reminder 5 days in advance, so I set my reminder time variable to start time - 5 days.
I know this is working because I had the system email me the variable values and I received the email with the values.
When I do the compare statement create date < reminder time variable, pause until reminder time variable then send email, the date and time comes and goes and the email is never sent.
What would cause this to happen? Something is not triggering.
I would like to ask you whether is possible to send an outlook invitation, not e-mail with text?
Unfortunately no, not with the pre-installed actions. You'll need to write some custom code to achieve that.
Could you write such code, I need this to our internall WSS site... I would be grateful!
How do I create a unregistration confirmation email?