Program Event Framework
A robust set of content types and syncer modules that build interactive tools to help members find and book activities.
“Program Event Framework” refers to the entire ecosystem of content and modules in YMCA Website Services that work together to build Activity Finder, Group Schedules, and more.
Content Types
These provide the containers for PEF content in Drupal:
Syncers
These provide integrations to pull content from external systems into the content types:
Displays
These display the content for users to discover:
- Activity Finder
- Group Schedules
Data model
The network of data structures in PEF can be confusing. Here’s how it all works
---
title: PEF Relationships
---
erDiagram
program {
entityRefTerm field_program_color
paragraph field_content
paragraph field_header_content
paragraph field_sidebar_content
textFormattedLong field_program_description
entityRefMedia field_program_icon
entityRefMedia field_program_image
layout layout_builder__layout
meta field_meta_tags
bool field_use_layout_builder
}
program_subcategory {
paragraph field_bottom_content
entityRefTerm field_category_color
paragraph field_content
paragraph field_sidebar_content
textFormattedLong field_category_description
paragraph field_header_content
entityRefMedia field_category_image
layout layout_builder__layout
meta field_meta_tags
entityRefProgram field_category_program
bool field_use_layout_builder
}
program_subcategory }|--|| program : field_category_program
activity {
textFormattedLong field_activity_description
entityRefProgSub field_activity_category
}
activity }o--|| program_subcategory : field_activity_category
class {
entityRefActivity field_class_activity
paragraph field_bottom_content
paragraph field_content
textFormattedLong field_class_description
paragraph field_header_content
meta field_meta_tags
paragraph field_sidebar_content
}
class }o--|| activity : field_class_activity
session {
listText field_activity_type
entityRefClass field_session_class
textFormattedLong field_session_description
dateRange field_session_exclusions
listText field_session_gender
numberInt field_availability
bool field_session_in_mbrsh
textPlain field_session_instructor
entityRefLoc field_session_location
numberInt field_session_max_age
listText field_session_max_grade
numberDec field_session_mbr_price
numberInt field_session_min_age
listText field_session_min_grade
numberDec field_session_nmbr_price
bool field_session_online
entityRef field_session_plocation
numberInt field_productid
link field_session_reg_link
textPlain field_session_room
paragraph field_session_time
numberInt field_wait_list_availability
}
session }|--|| class : field_session_class
session ||--o{ session_time_paragraph : field_session_type
session_time_paragraph {
dateRange field_session_time_date
listText field_session_time_days
textPlain field_session_time_override
}
branch {
}
camp {
}
facility {
}
session }o--|| branch : field_session_location
session }o--|| camp : field_session_location
session }o--|| facility : field_session_location
session }o--|| facility : field_session_plocation
More information on how this data gets out into each display will be coming soon.
1 - PEF Schedules
The “PEF Schedules” module allows Ys to create and manage schedules with a simple, calendar-based view.
YCloudYUSA/y_pef_schedule
The Y PEF Schedule module provides a calendar functionality for scheduling events.
It includes a Vue.js component, fullcalendar-app
, to display and interact with the calendar.
Installation
- Download and install the module in your Drupal project.
- Enable the module by navigating to
Admin > Extend
in your Drupal admin interface. - Go to the
/admin/openy/branch-schedules
and select a branch.
Usage
After choosing a brunch, you can view the calendar, the main features of the calendar:
- View events in weekly or daily format
- Viewing the main information of the event (clicking on the event)
- Creating a new event (content type session)
- Update of existing events
- Downloading the schedule in PDF format
- Filtering results by categories
Issues or things worth knowing (TUDUS):
- After creating a series of events, it is created, but only one event is displayed in the calendar, the page must be refreshed to see the correct data
- The color is fixed to the session and not to the category
- PDF format is A3
Retrieving Events
The module provides controllers to handle AJAX requests for fetching events. Use the following route in your JavaScript code:
axios.get('/fullcalendar-api/get-event-data-date-range/{location}/{start}/{end}/{category}')
.then(response => {
const events = response.data;
// Process the received events as needed
})
.catch(error => {
console.error('Error fetching events:', error);
});
Replace {location}, {start}, {end}, and {category} with the appropriate values.
Creating Events
The fullcalendar-app component allows users to create events interactively. When a date is clicked, a modal form is displayed for users to enter event details such as title, category, time, and date.
To customize the form or extend the functionality, refer to the Vue.js component documentation and customize the handleDateClick and createEvent methods in the fullcalendar-app component.
Requirements
- Drupal 9|10
- Open Y Repeat
- Vue.js 3
- Axios
- FullCalendar
2 - Traction Rec Integration
Instructions for configuring and importing data from Traction Rec into the Program Event Framework
Via
Traction Rec Integration (ycloudyusa/openy_traction_rec
)
This module provides YMCA Website Services integration with the
Traction Rec CRM.
Installation
Require this module:
composer require ycloudyusa/openy_traction_rec
Then enable the necessary modules and submodules:
drush en openy_traction_rec openy_traction_rec_import openy_tr_activity_finder
Usage
The main module itself provides only API that helps fetch data from TractionRec. More specific functionality is provided in submodules:
YMCA Website Services Traction Rec: PEF import
provides PEF migrations.YMCA Website Services Traction Rec: Activity Finder
extends YMCA Website Services Activity Finder with the new fields and logic.
Configuration
Create a Connected App in Salesforce
- Create a new private key and X509 certificate, customizing the
subj
options in the command to suit your organization. (See
the manual for openssl-req to understand the options here.)openssl req -x509 -noenc -sha256 -days 365 \
-keyout traction_rec.key \
-out traction_rec.crt \
-subj "/C=US/ST=Illinois/L=Chicago/O=My YMCA/OU=Org/emailAddress=youremail@example.com"
- The email address in the certificate does not need to match the email on the Connected App.
- The certificate must be renewed yearly (or after the set number of
--days
). We recommend you set a reminder in order to prevent unwanted failures.
- In Salesforce > Setup > App Manager, create a New Connected App.
- Set a Name and Email.
- The Contact Email is not used for authentication.
- Check Enable OAuth Settings
- Set the callback url as the base URL of your site
- Check Use digital signatures and upload the X509 certificate (
.crt
) created above. - Ensure the app has the following Selected OAuth Scopes
- Full access (full)
- Manage user data via APIs (api)
- Manage user data via Web browsers (web)
- Perform requests at any time (refresh_token, offline_access)
- Check these options:
- Require Proof Key for Code Exchange (PKCE) Extension for Supported Authorization Flows
- Issue JSON Web Token (JWT)-based access tokens for named users
- Uncheck all other options in the OAuth section.
- Save the Connected App
- Once the app is saved, you will need to get the Consumer Details:
- In the “My Connected App” screen that appears once you save (or via Setup > App Manager), click Manage Consumer Details.
- Save the Consumer Key and Consumer Secret for the next step.
- Connect your new Connected App to a User. The attached User’s email will be the one used to authenticate the app.
- If necessary, create a user via Setup > Users > New User
- Assign the User to a Profile or Permission Set that has the
necessary permissions.
- Go to Setup > Connected Apps > Manage Connected Apps and choose your new app. Assign the profile or permission set that contains your new user.
- In the Connect App Detail, click Edit Policies, then under OAuth Policies > Permitted Users choose Admin approved users are pre-authorized, then Save.
Review all of these steps carefully. Missing any of them can result in an inability to query the API.
Salesforce permissions
The Salesforce integration role/permission set should have read access to all fields in the following objects:
- Course
- Course Option
- Course Session
- Course Session Option
- Location
- Product and Discount
- Program
- Program Category
- Program Category Tag
It should also have the following Systems Permissions:
- Apex REST Services
- View Restriction and Scoping Rules
- Update Consent Preferences Using REST API
- Go to Admin > Configuration > System > Keys (
/admin/config/system/keys
) and create a new key to store the private key created above.- Add key
- Add a Key name and Description
- Choose Key Type: “TractionRec JWT Private Key”
- Choose the Key provider depending on your configuration. See
Managing Keys for details.
- Configure the chosen provider then Save the key.
- Go to Admin > YMCA Website Services > Integrations > Traction Rec > Traction Rec auth settings (
/admin/openy/integrations/traction-rec/auth
) to configure the keys & secrets provided by Traction Rec.- Add the Consumer key and Consumer Secret from Manage Consumer Details in Salesforce.
- Add the User connected to the Connected App.
- This is the email of the User, not the Contact email.
- Enter a Login URL.
- This will most likely be
https://login.salesforce.com
- Set the Services base URL and REST API Base URL as per their descriptions.
- Ensure the REST API Base URL responds to
curl -I
with a 200
response. If you use a URL like *.lightning.force.com
instead of *.my.salesforce.com
it may result in a redirect, which will cause fetches to fail.
- Set the Community URL based on the publicly accessible registration links.
- This may be something like
https://my-ymca.my.site.com
- The URL can be found in Salesforce under Setup > Digital Experiences > All Sites.
- Choose the key as configured above.
Usage
See
modules/openy_traction_rec_import/README.md
Data Model
This module assumes a Traction Rec “standard” data model in its queries. Any deviations from this model will require overriding the queries in src/TractionRec.php
.
This model contains a subset of the fields in Traction Rec that are relevant to our usage. All entities have more fields than listed.
Field types are taken from Salesforce’s Setup > Object Manager > {Entity} > Fields & Relationships.
- Number field options are:
number(length_decimal places)
erDiagram
Program_Category__c {
id Id
text(80) Name
}
Program__c {
id Id
text(80) Name
checkbox Available__c
textArea(255) Description__c
}
Program_Category_Tag__c {
id Id
autoNumber Name
lookup(Program) Program__c
lookup(Program_Category) Program_Category_c
}
Course__c {
id Id
text(80) Name
checkbox Available__c
text(128) Code__c
longTextArea(640) Description__c
lookup(Program) Program__c
richTextArea Rich_Description__c
}
Course_Session__c {
id Id
text(80) Name
checkbox Available__C
text(128) Code__c
lookup(Course) Course__c
longTextArea(640) Description__c
number(18_0) Num_Option_Entitlements__c
lookup(ProductAndDiscount) Product__C
richTextArea Rich_Description__c
sum Total_Option_Capacity__c
formula(number) Total_Option_Capacity_Remaining__C
sum Total_Option_Registrants__c
count Total_Options_Available__c
}
Course_Option__c {
id Id
text(80) Name
number(3_1) Age_Max__c
number(3_1) Age_Min__c
checkbox Available__c
number(18_0) Capacity__c
picklist(multiSelect) Day_of_Week__c
date End_Date__c
text(8) End_Time__c
text(128) Instructor__c
lookup(ProductAndDiscount) Product__c
number(18_0) Registration_Total_c
longTextArea(3500) Setup_Notes__c
number(3_0) Setup_Time_Required___c
date Start_Date__c
text(8) Start_Time__c
longTextArea(3500) Tear_Down_Notes__c
number(3_0) Tear_Down_Time_Required__C
}
Course_Session_Option__c {
id Id
autoNumber Name
lookup(CourseOption) Course_Option__c
masterDetail(CourseSession) Course_Session__c
checkbox Option_Available__c
number(18_0) Option_Capacity__c
number(18_0) Option_Registration_Total__c
}
Program_Category__c ||--|{ Program_Category_Tag__c : ""
Program__c ||--|{ Program_Category_Tag__c : ""
Program__c ||--|{ Course__c : ""
Course__c ||--|{ Course_Session__c : ""
Course_Session__c ||--|{ Course_Session_Option__c : ""
Course_Option__c ||--|{ Course_Session_Option__c : ""
Import
The module allows you to synchronize classes and programs from the
Traction Rec CRM to the YMCA Website Services Program Event Framework (PEF).
It uses Migrate API to import data fetched from Traction Rec and provides Drush commands and a configuration UI.
The import process consists of 2 drush
commands:
openy-tr:fetch-all
this command fetches required data from Traction Rec and saves it to JSON files.
openy-tr:import
the command migrates fetched JSON files to YMCA Website Services and creates sessions, classes, activities, categories and programs.
You can run the commands manually for one-time import or add both to cron jobs.
Other available drush
commands:
openy-tr:rollback
- Rolls back all imported nodes.
openy-tr:reset-lock
- Resets import lock.
openy-tr:clean-up
- Removes imported JSON files from the filesystem.