5 replies [Last post]
Dewi Morgan's picture
Joined: 02/18/2009
Juice: 19
Was this information Helpful?

Newbie here.

I'm working on setting up a site where managers can book their employees/minions onto courses.

Some simple requirements:

1) Courses can be held several times, each with a limited capacity.

2) managers pay for those courses (using a payment system not supported by Ubercart).

3) managers can book different people onto different courses in a single transaction: "I'll send Al and Bob on the French course, and Bob and Chris on German..."

4) managers can see a usage history of the minions("Oh wait, Al's already taken French...")

5) Minions don't need Drupal logins, but do need contact details (name, address, etc) taken.

6) Managers need to be Drupal users.

I've got about five days to do this whole site from scratch, so I'm leery of rolling my own, hence turning to Drupal and Ubercart.

I've been searching the forums for something like this manager/minion system, searching for "booking", "affiliate", "partner", etc, but not seen anything that looks likely to be usable for this out of the box.

Can anyone suggest modules that might help build it?

From point 1 ("Courses can be held several times, each with a limited capacity"), I'm thinking that course dates would be product variations, IF product variations can be limited on a per-variation basis?

From point 2 ("a payment system not supported by Ubercart") - how much work does a payment plugin for Ubercart take to write?

Viewing their employees' course histories is the biggie, though, I think. Any suggestions towards that one would be helpful, as I have no idea even where to start.

Ryan's picture
Joined: 08/07/2007
Juice: 15506
Re: Course booking of employees by managers

Don't have time for an in depth post, but you might benefit from my analysis of gregoryheller's post.

Dewi Morgan's picture
Joined: 02/18/2009
Juice: 19
Re: Re: Course booking of employees by managers

Thanks, appreciate the tip Smiling

My eyes particularly lit up at your line "I also disassociated purchasing registration from the user account, so you could register other people for DIWD through a single account."

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

Configuring UberCart as a Course Sales System

UC_node_checkout seems to be basically undocumented: http://drupal.org/node/339060 is all I can find. And it's a read sod to get your head around.

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

Looks like, to use it, you need to:

  1. Enable the following modules, at: admin/build/modules
    • All UberCart core modules.
    • Token
    • Payment
    • Node Checkout
    • ProtX Gateway (not written yet, at the time of writing), or some other payment gateway.
    • Date (& Date AIP, Date Popup, Date TimeZone)
    • CCK (& Content, Multigroup (see below), Content Permissions(?), Fieldgroup, Number, Text, email, Option Widgets)
    • Views (& Views UI)
    • Node Hierarchy
  2. Maybe also enable:
    • Reports (handy for debugging, and customers like reports)
    • Roles (to grant buyers the ability to see their course history)
    • Taxes (if we want to display these)
    • Stock (if we'll be using this to monitor booking levels - don't think we will.)
    • credit card (if required by the payment gateway).
    • Payment method pack (handy payment methods for testing at least).
    • Test Gateway (handy payment methods for testing at least).
    • Ajax (makes forms nicer: enable all possible submodules, except maybe comment)
  3. Basic config:
    • admin/store/settings/products/edit - Set the "buy now" text to "Book now". No optional quantity field. Disable add to cart in teasers.
    • admin/store/settings/products/edit/fields - Remove "Add to cart" and "SKU".
    • admin/store/settings/payment/edit - disable payment deletion.
    • admin/store/settings/payment/edit/methods - set to whatever payment method you want.
    • admin/store/settings/payment/edit/gateways - configure as relevant.
    • admin/store/settings/orders/edit - prevent users seeing invoices.
    • admin/store/settings/orders/edit/panes - [I need to look into this one more deeply.]
    • admin/store/settings/node-checkout/settings - leave all checkboxes checked.
    • admin/store/settings/countries/edit - import the UK. Disable the US and canada.
    • admin/store/settings/checkout/edit - disable anon checkout. Login new users.
    • admin/store/settings/checkout/edit/fields - "City" -> "Postal Town", "State/Province" -> "County", "Postal Code" -> "Post Code"
    • admin/store/settings/store/edit - set name/owner, email address, phone, fax, etc. Has to be done after importing the "UK" country.
    • admin/store/settings/store/edit/display - footer message none.
    • admin/store/settings/store/edit/format - Currency: GBP; currency sign £; defaults kg, cm; date format d/m/Y.
  4. 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 in sites\all\modules\cck\modules\content_multigroup (hopefully this will soon become a standard part of CCK).
  5. We want a course hierarchy, so create a node type "course_category" (can be parent and child, menu items optional but default to yes, default children view: nodehierarchy_children_list).
  6. Create a node using that type, of type "Courses". Add it to the root menu as a menu option, adn set it as the default root node of the course_category type.
  7. 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 (can be child, not parent, default parent is the main course node, optional menu items, default to published, not promoted, allow attachments), at: admin/content/types/add
  8. Add a "course_dates" multigroup, at: admin/content/node-type/course-product/fields
  9. 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)
    [Note: due to a bug with how Date handles MultiGroup, you need to do the From and To as two separate Date fields, not a single field. I called the second one "course_end".]
  10. 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)
  11. 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, can't be parent or child, never a menu item).
  12. 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");
  13. 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: name, email, address, DoB, NI#... (unfortunately, http://drupal.org/project/cck_address is Drupal 5 only, but a textfield may suffice).
  14. 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).

  15. 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 node view 'selected_course_date', at: admin/build/views
  16. Add fields to display: a node:title field, and the date field's "From" value, from course_product (BUG: the current display of these is "Content - value"), and the "To" value, and the product:sellPrice.
  17. 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, course product node validator). Since you have the arguments, you don't need any filters.
  18. Add a "Page" display for this View, and give it the path "booking".
  19. Select that page view in the "View" field at: admin/store/settings/node-checkout/course_booking
  20. For testing, create two course hierarchy elements, "languages" and its child, "french".
  21. Although products will be automatically added by the backend in future, for testing we now create a course_product node, "course_french_101", which will represent our first Course, French 101. Place it under "French" in the hierarchy. 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
  22. Give it a number of date ranges
  23. 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. Be aware of any bookings in the user's cart that may affect the number of available places.
  24. 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
  25. Set all forms to be ajax'd at: admin/settings/ajax
  26. NOT DONE YET: charge the customer.
  27. NOT DONE YET: check the places available again just before checkout.
  28. NOT DONE YET: decrement the places available on successful checkout.
  29. NOT DONE YET: set status to fully booked if places available hits 0.
  30. NOT DONE YET: warn if overbook occured (if decrement took it below 0).
  31. NOT DONE YET: some way of letting people see a history of who they've booked, onto what courses.
  32. NOT DONE YET: some way of highlighting "related courses". If they are booking French 101, maybe they're interested in French 102? Or German 101? Or Woodworking, because that's held on the same week, so they could do both at the same time. But not Metalworking, because even though it's on the same week, it's on a different campus...

POSSIBLY: view should point to booking node instead? Booking node should be an instance of product, with a date, user, and price?

Am I barking up the wrong tree with multigroups?

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. MUCH of the above is probably wrong... but which bits?

I'm deeply regretting using Drupal for this, now, rather than rolling the site from scratch in PHP. Too late to change direction now, though.

Dewi Morgan's picture
Joined: 02/18/2009
Juice: 19
Some possibly related threads:
mliu's picture
Joined: 02/23/2009
Juice: 65
Some feedback ...

course_product - These I believe should be created as a Ubercart product class by creating store-product-classes path. I read other places that by just going there and naming your new product class as course_product it will convert also.

Then using CCK add the date range (like you have already done).

The reason is that when you create the view as the selector used in step 15, it actually will fail in the steps further down since it accepts on UBERCART products and not the normal nodes. The ubercart Products are just custom content types.

For spaces available, perhaps a better way is to use the stock level field in the ubercart config for the product.

Step 17 - How do you plan to integrate or enter into this view to pass the nodeid/date? I have noticed that once one chooses the appropriate product, the next page it passes that id as a name/value url pair (....?productid=3434). If might be better since you know which exact product you are interested in to write a perhaps a custom view to skip the view selector but to jump to form registration directly but passing in the url name value pair.

I suppose for a french class as opposed to an english class, you need separate products right? If that is the case ... you might want to consider Drupal's taxonomy or classification system. It lets you classify nodes the way you want. But there is also Ubercats product catalog which also lets you classify products into different catalogs.

These are just thoughts ...