12 replies [Last post]
gregoryheller's picture
Joined: 02/18/2009
Juice: 92
Was this information Helpful?

I am looking to use ubercart for the following purpose:
* a school that offers a variety of in person (and some virtual) classes
* most classes have a set of dates on which they meet
* some classes have more than one "day option" so you could take the class on tuesday OR thursday
* some classes have multiple sessions (they meet 3 times) and there are different day options, so you could take the class that meets for 3 saturdays, or one that meets for 3 thursdays
* some classes have 5 different sessions, and the student needs to register for 3 of them (not 2, not 4, but 3 specific sessions of the class)

* classes cost money
* students contact information is going to be stored in civicrm.

Here are my questions right now:
* can i collect custom civicrm data on checkout for the user/customer (student)
* can i collect information like "how did you hear about this class (product)

* would i use product attributes for the different days that the class meets?
* would i use a product kit for the type of class where a student must choose 3 of the 5 sessions?

* will school admins be able to easily generate "customer" lists that show which students will be attending a particular class?

Ryan's picture
Joined: 08/07/2007
Juice: 15506
Re: Using Ubercart for In Person Course/class registration/sales

Hey Greg, thanks for popping in with the questions. I'm actually excited about the opportunity for Ubercart to handle event sales in the future, and I'm definitely interested in any feedback this project of yours might generate.

I think I'll limit my response to just straight answers to your questions followed by a bit of brainstorming...

1) To gather custom CiviCRM data on checkout, ideally you could do so through a custom checkout pane. I have a small demo contrib up here on Ubercart.org called Lead Tracker that shows how you can store data from a custom checkout pane in the $order->data array during checkout. Your module could then move that data into CiviCRM when the order is completed or something. I personally am moving more and more toward working through CA actions, because it's easier to do things like perform an export on the customer completes checkout trigger.

2) For that, I don't think there's much precedent. If you need it stored per product, you can alter a select list onto the add to cart form and store that data using hook_add_to_cart_data(), but there may be a better way...

3) For choosing the day, I'm not sure how I'd handle it. I think using an attribute would be fine, but you'd want to make sure to use separate SKUs for reports generation. In other words, in my mind, each day the whole class is offered represents a different product, even if we see it as the same class. If you want a product report to show which days are more popular, then you'd want the SKUs to be different based on the day chosen, which you can do through the Adjustments tab. If this is too cumbersome for the site maintainers long term, then you might just consider each "section" of a class having its own product.

4) I don't think I'd use a product kit. If any 3 sessions represent one whole course, I think I'd instead do something like make a textfield attribute and use hook_form_alter() to turn that into something that appears to the user like a widget for selecting days but stores their selections in plaintext. I'm not sure how this would work for all your products, but it's a thought. The product kit would require you to list each day as a separate product, but imo if 3 days are required for purchase, then it's a group of 3 days that are a product. This should also help on reports, too.

5) That's the toughie. You'd need to create a custom report for this, really.

So, one thought re: 2 and 5 is you might have a use case here for UC Node Checkout. The idea behind that module is when someone goes to purchase a product, they get sent to a node add form of your choosing. This is how I handled registrations for the DIWD site, and the module's been improved since then. As of the latest development (in 6--2-beta) for D6, that module allows you to create a View and associate any product in that View with a node type. The latest dev also lets you specify the product's attributes on the node add form. So, the workflow is something like...

1. You create a registration node type that contains common elements for all your classes. Re: #2 above, this might include the "how did you hear about this course" element. I also disassociated purchasing registration from the user account, so you could register other people for DIWD through a single account. To do this I made the title the last name and added a first name field.

2. Someone who wants to register either finds the course they want and clicks "Add to cart" and gets redirected to the node add form or navigates to node/add/registration, chooses the course from the View populated select list, and is redirected to the node add form. When they submit the node form, the product will be added to the cart. They can even update existing products in the cart.

3. They complete checkout.

4. You'd need a custom module that could operate on all the nodes associated with the order. On DIWD, I defined a custom Wf-ng action that would loop through all the products, look for a node_checkout_nid in each product's data array, and update the node if it found one. I had a hidden field on the registration nodes that contained a link to the order, for example. I would populate this field once someone checked out. Administrators could then easily navigate to the associated order w/ someone's registration.

5. You can create a custom View that the site's administrators could use to view lists of who was registered for which course. This is the big win for #5 above...

So... that's like a buffet for thought. Hope it helps.

gregoryheller's picture
Joined: 02/18/2009
Juice: 92
Re: Re: Using Ubercart for In Person Course/class registration/s

Thanks so much for the detailed response. I will be sure to update this post as we work through the various scenarios and arrive upon a solution.

One clarifying question: if i understand the UC Node Checkout solution: when the user checks out, a node is created that would contain certain data about them and the products (classes) they purchased? My view (report for course administrators) would then consist of these nodes?

Ryan's picture
Joined: 08/07/2007
Juice: 15506
Re: Re: Re: Using Ubercart for In Person Course/class registrati

Close. Instead of a node being created on checkout, what's really happening is a node is being created and associated with each product when it's added to the cart. The module doesn't really track what happens to it once you've completed checkout, but it maintains the order product -> node relationship in each order product's data array. You are correct in that the administrator View would consist of these nodes.

Dewi Morgan's picture
Joined: 02/18/2009
Juice: 19
Re: Re: Re: Re: Using Ubercart for In Person Course/class regist

This looks like the solution to my own problem, too, and I'd be interested in sharing any work I do on it, if it'd be of use.

That's assuming my boss doesn't pull me off the job: I have just a week to get this done, at most, so he might opt for a custom system rather than a Drupal one. Does a week sound even vaguely feasible? I'm mostly a Drupal newbie, though I've been playing with it since 4.7; I'm completely an ubercart newbie, but am reasonable with PHP.

Sounds like I need to write maybe three modules to plug into ubercart:
- the "course booking" one, described above, with separation of buyer and student.
- a reporting one, to show course histories.
- a payment processing one.

...probably in that order.

Dewi Morgan's picture
Joined: 02/18/2009
Juice: 19
Findings so far

Here're my findings so far. Would appreciate any help or pokings in the right direction, of course Smiling

"Wf-ng" (meaning, I suspect, Workflow-ng) is a 5.x-only project, so is moot here.

UC_node_checkout seems to be basically undocumented: http://drupal.org/node/339060 is all I can find.

Config page appears to be admin/store/settings/node-checkout.

Looks like, to use it, I need to:

  1. Enable the experimental "multigroups" CCK module (included but disabled in the normal CCK installer), by creating the multigroups.info file, as it says in the multigroups README.txt (hopefully this will soon become a standard part of CCK).
  2. We need to be able to put bookings on specific dates, so the default product nodetype won't do. We also can't do it using Attributes, as their options are defined on a per-Attribute, rather than per-node basis, and we don't want to create a separate attribute for each course. We could use a repeating date CCK field, but we also want to store information about the course capacity, etc. So, we'll create a new nodetype, and add the dates using multigroups. First, create a "course_product" nodetype (default to published, not promoted, allow attachments), at: admin/content/types/add
  3. Add a "course_dates" multigroup, at: admin/content/node-type/course-product/fields
  4. Add a "course_date" date field (default 'From' and 'To' to now, no labels, both fields required, 1 value, granularity y/m/d, no timezone)
  5. Add "course_available_places" integer textfield (required, 1 value, default 0), to store how many places are left available for booking.
    (Ensure that course_date and course_available_places are both indented within the course_dates group, in the "manage fields" display: if not, drag them around and sideways until they are, and click save)
  6. With UC_node_checkout, each booking requires a node to be created, so we create a "Course Booking" node type, at: admin/content/types/add
    (Change the "Title:" name to "Notes:" or somesuch. Blank out the "Body:" title, so they aren't asked for one. Not promoted or published, no attachments).
  7. We want them to be able to assign bookings to specific delegates, so add a "Delegate:" integer field to it using CCK, widget type "select list", at: admin/content/node-type/course-booking/fields
    (Modify that field so that the "allowed values" are filled by PHP code from the database of that user's contacts, at: admin/content/node-type/course-booking/fields/field_delegate)
    For testing I just did:
    return array(43=>"Harry", 42=>"Timmeh", 64=>"Norman");
  8. Create a similar node type, "Course Register", for delegates who have not already been created, and with all the fields required to register a new delegate (unfortunately, http://drupal.org/project/cck_address is Drupal 5 only).
  9. Create a tiny module, 'add_new_delegate', containing just the following code, to add a link to "course booking" to link to "course register", and let them register a new delegate for the course:
    function add_new_delegate_form_alter(&$form, $form_state, $form_id) {
      if ($form_id == 'course_booking_node_form') {
        $form['register_new'] = array('#type' => 'markup', '#value' => '<a href="course-register">Register new delegate</a>','#weight'=>"-4");

    (Ultimately, this should probably be a 'button' type with #ahah to load the new form inline, then use the submit button of that to update the list, from which multiple users should be selectable, blah blah, but the above will work for now).

  10. With UC_node_checkout, when customers create a booking node, you can either add a fixed product type to their cart (not what we want: we want to add their chosen course and date), or you can let them select nodes from a view (not what we want: they have already selected their course and date!) So, we'll show them a view, but only give them that one, already-chosen item that can be selected. Create a view 'selected_course_date', at: admin/build/views
  11. Add two dields to display: a node:title field, and the date field's "From" value, from course_product (the current display of these is "Content - value"), and the "To" value
  12. Add two arguments: a node:nid field, and a date:date field (set to the 'From' value of course_product, with a blank title, 404 if not found, no wildcard, node validator, 'course date' nodetype). Since you have the arguments, you don't need any filters.
  13. Add a "Page" display for this View, and give it the path "booking"
  14. Select that page view in the "View" field at: admin/store/settings/node-checkout/course_booking
  15. Create a course_product node, "course_french_101", which will represent our first Course, French 101. Do this not via an "add" button somewhere under the store management menu, as you might intuitively expect, but rather through "Create Content", at: node/add/course-class
  16. Give it a number of date ranges
  17. NOT DONE YET: add a hook to add a "book now" link by all dates for a course with a "places_available" of 1 or more, that will take the customer to the course_booking page.
  18. Remove/hide the "course booking" and "course register" options (and maybe "course product", if we'll only be creating classes through the back end) from the "create content" menu, at: admin/build/menu-customize/navigation

[Edit: updated. This approach now looks like it might work. VERY little PHP code involved so far: next step is getting checkout to work, then write a ProtX module, since the existing maintainers aren't interested in upgrading.]

Advice, comments, suggestions, pointers MUCH appreciated. I'm feeling very lost and alone in this scary forest of Drupal.

mliu's picture
Joined: 02/23/2009
Juice: 65
After the Product View Select I get send back to create content

Similar Dewi, I did all his detailed steps.

I have the course_product, course_register, course_booking content types.

I created the view to see all courses offered over the dates and associated this VIEW to the ubercart Product plus to the course_register FORM.

So now when I go to register a course:
1. I get the select product drop down correctly containing the courses offered
2. But when I submit it does not take me to the course_register form to fill our the first/last name and other info as it should.

Instead it takes me back to Create Content screen listing all content types for which I can create a node.

Can anyone direct me out of this?

[UPDATED: with solution] -- the problem is that the content types were named with a - in them .... for example course-booking. This causes problem for the node check out since on the URL it shows as course_booking and the somehow it gets confused.


hedac's picture
Joined: 12/14/2007
Juice: 144
Re: Using Ubercart for In Person Course/class registration/sales

some days ago I saw a page. I don't remember how I reached that page... about a site selling events

Just Racing UK - Selling an Event with Drupal, Ubercart, Views, Dates and some glue

mliu's picture
Joined: 02/23/2009
Juice: 65

I have read that many a time and based on that and other research I think using uc_node_checkout is the best way to go.

I am reading up on creating ubercart product classes right now to which I will add a CCK date field or maybe add a product date attribute .... I don't know yet.

Thanks for the reply anyways.

Dewi Morgan's picture
Joined: 02/18/2009
Juice: 19
So I'm not threadjacking...

I've moved my writeup to its own thread, so I don't hijack this thread. I've got a little farther, and written up a little more, but I'm still really, really stuck, with no idea if I'm even going in the right direction, and would love some kind of explanation of what I need to do.

Writeup's here: http://www.ubercart.org/forum/support/9165/course_booking_employees_mana...

It looks like a Drupal 6 course booking system is:
1) something a reasonable number of people need (at a minimum: myself, mliu, Wonder95, and gregoryheller), and
2) really hard to get your head around with node checkout.

It'd be cool if there were proper docs on how to do this. Documenting node_checkout is apparently "really high on [Ryan's] to-do list". Even then, though, there's no guarantee that the docs will cover course bookings, though Sad

zeezhao's picture
Joined: 04/23/2008
Juice: 1075
Re: So I'm not threadjacking...

subscribing. thanks.

gregoryheller's picture
Joined: 02/18/2009
Juice: 92
UPDATE: I have decided to


I have decided to use uc_node_checkout.

I've created the following cck content types:
* course_description (basic cck content type)
* course_session (product class)
* course_registration (uc_node_checkout)

course sessions nodes have a node reference to course description nodes. The course description describes the course and is fairly static, but each term a new course session is created. I used two date fields, a date repeating and a date multi select to deal with various scheduling options.

When a user adds a course session to their cart, they create a course registration where they add some data like "How did you hear about this course?"

This handles 90% of the courses.

The last scenario that i still working on is a course that has 5 meeting days and a user needs to signup for 3.

I am planning on either using a product kit, or creating a second uc_node_checkout course_registration_multi content type that applies to a different course_session_multi content type. The difference would be an added field that asks the user to select the sessions the plan to attend. I would "generalize" the session data so that in the course_session_multi content type there would be 5 date fields called "Meeting 1" "Meeting 2" etc... and on the course_registration_multi there would be a multi select or multiple value field that would correspond allowing the user to select which meetings the user was going to attend. I don't really like this solution because it may be too rigid not allowing for a course that has 10 meeting days that a user needs to select 8 of, for example.

I need to do more research into the product kit.

Another option is to use attributes that are text field attributes where the user must enter the actual meeting days, i could have 3 such attributes, but again, this is rigid, using attributes with pre determined values also does not work for a variety of reasons.

glennnz's picture
Joined: 01/20/2009
Juice: 458
@gregory * will school


* will school admins be able to easily generate "customer" lists that show which students will be attending a particular class?

I've done this for a site I'm working on. PM me and I'll send you the code. It's quite specific for my needs, so would need some tweaking.