Skip to content

Instantly share code, notes, and snippets.

@bobflorian
Last active January 6, 2026 15:04
Show Gist options
  • Select an option

  • Save bobflorian/695e956e7c86e4981c159f892c421de0 to your computer and use it in GitHub Desktop.

Select an option

Save bobflorian/695e956e7c86e4981c159f892c421de0 to your computer and use it in GitHub Desktop.
Registration Category Mapping for Mobile Opt-Out (MobileOut) - ASPET RD Integration

Registration Category Mapping for Mobile Opt-Out ("MobileOut")

Overview

This document describes how to configure the "MobileOut" registration category mapping for ASPET to exclude registrants from the RD (Results Direct) mobile app sync.

Architecture Summary

Registration Company    Poseidon/Zenith      Planion API       RD Sync (Zenith)    Results Direct
    (Showcare)              ↓                    ↓                   ↓                   ↓
        │                   │                    │                   │                   │
        └──── pull ────────►│                    │                   │                   │
                            └──── push ─────────►│                   │                   │
                                                 │                   │                   │
                                           CECNFPEO table            │                   │
                                           (regtype="MobileOut")     │                   │
                                                 │                   │                   │
                                                 └──── query ───────►│                   │
                                                                     └──── sync ───────►│
                                                      ↓
                                               PICKLIST (key=MEMTYP)
                                               - desc = "MobileOut"
                                               - exclude_mobile_app = 1

Key Components

1. Planion (Registration Data Source)

File: /home/bflorian/src/planion/api/psAPIRegConf.pas

  • Receives registration data via PostRegConf API
  • Stores registration type in CECNFPEO.regtype field
  • Uses CheckRegType procedure to look up Picklist mapping

2. Zenith RD Integration

Key Files:

File Purpose
ps_data.py Queries Planstone data, including ps_get_regconf() and get_sql_query()
rd_api.py RD API client with GET/POST/DELETE functions
actions.py Sync orchestration including sync_regconf() and sync_delete()
aspet.py ASPET-specific data transformations
methods.py CLI interface for sync operations

Location: /home/bflorian/src/products/zenith/poseidon/integrations/resultsdirect/

3. Deletion Handling (Already Implemented!)

The sync_delete() function in actions.py (lines 234-291) already handles deletions:

  1. Gets current RD roster via rd_get_rosters(eventId)
  2. Gets Planstone registrants via ps_get_regconf()ps_regconf_to_rd()
  3. Computes diff: rd_extra = set(rd_data.keys()) - set(ps_data.keys())
  4. Deletes extras from RD via rd_delete()

Key insight: If we filter out "MobileOut" registrants in ps_get_regconf(), they won't appear in the Planstone data set, and sync_delete() will automatically remove them from RD.


Implementation Steps

Step 1: Configure Registration Category Mapping

Use the Registration Category Mapping screen (iframe injected into Planion) to create the "MobileOut" entry:

  1. Open the Registration Category Mapping configuration for the ASPET conference
  2. Add a new registration type with:
    • Description: MobileOut
    • Designation: * (user-selected)
    • Mobile App Enabled: unchecked
    • Exclude from Mobile App: checked (see UI Enhancement below)
    • RD Attendee Role: leave blank (not synced to RD)
    • Register in Planstone: checked (allow the registration)

Step 2: Planion Registration API Flow

When the registration company sends data with "MobileOut", it flows through Planion:

File: /home/bflorian/src/planion/api/psAPIRegConf.pas

// The regtype value comes from the incoming JSON
RegType := APostContent.Values['regtype'];  // "MobileOut"
// This gets stored in CECNFPEO.regtype
// CheckRegType looks up the Picklist entry to get designation and flags

No changes needed to Planion if "MobileOut" is passed as the regtype value.

Step 3: Modify RD Sync Query (Code Change Required)

File: /home/bflorian/src/products/zenith/poseidon/integrations/resultsdirect/ps_data.py

The get_sql_query() function (lines 190-229) builds the SQL for ps_get_regconf(). Add filtering for exclude_mobile_app:

Current code (line 226):

desigmap_where = "and rd_attendee_roles is not null" if desigmap else "and cecnfpeo.registered = True"

Updated code:

desigmap_where = "and rd_attendee_roles is not null and COALESCE(picklist.exclude_mobile_app, 0) = 0" if desigmap else "and cecnfpeo.registered = True"

This adds AND COALESCE(picklist.exclude_mobile_app, 0) = 0 to filter out registrants whose registration type has exclude_mobile_app=1.

Step 4: Automatic Deletion via sync_delete()

Once the query change is made, the existing sync_delete() function will automatically handle deletions:

File: /home/bflorian/src/products/zenith/poseidon/integrations/resultsdirect/actions.py (lines 269-291)

# Existing code in sync_delete() - no changes needed
logger.info("checking: registrants")
rd_data = {s["externalKey"]: s for s in rd_get_rosters(eventId) if s["externalKey"] is not None}
rd_regconf = []
for c in conf.split(","):
    ps_regconf = ps_get_regconf(db, account, c, eventId)  # Now excludes MobileOut
    rd_regconf += ps_regconf_to_rd(account, c, eventId, ps_regconf)
ps_data = {}
for c in conf.split(","):
    ps_data.update({s["externalKey"]: s for s in rd_regconf if s["externalKey"] is not None})
rd_extra = set(rd_data.keys()) - set(ps_data.keys())  # MobileOut registrants are now "extra"

# ... deletes rd_extra from RD

UI Enhancement (Required)

The exclude_mobile_app field exists in the Picklist model (planion_picklist.py line 74) but is not currently exposed in the Backstage UI form.

File: /home/bflorian/src/products/zenith/poseidon/views/backstage/config/attendee_types.py

Add to AttendeeTypeForm:

class AttendeeTypeForm(forms.ModelForm):
    # ... existing fields ...
    exclude_mobile_app = forms.BooleanField(
        required=False,
        label="Exclude from Mobile App (Opt-Out)",
        initial=False
    )

    class Meta:
        model = Picklist
        fields = ["desc", "desig", "mobile_app", "exclude_mobile_app", "rd_attendee_roles", "register_memtyp"]

Template: /home/bflorian/src/products/zenith/poseidon/templates/backstage/config/attendee_type_form.html

Add checkbox in Options section (after the "Mobile App Enabled" checkbox):

<!-- Exclude from Mobile App (Opt-Out) -->
<div class="flex items-start">
    <div class="flex h-6 items-center">
        <input type="checkbox"
               name="exclude_mobile_app"
               id="{{ form.exclude_mobile_app.id_for_label }}"
               {% if form.exclude_mobile_app.value %}checked{% endif %}
               class="h-4 w-4 rounded border-gray-300 text-orange-600 focus:ring-orange-500">
    </div>
    <div class="ml-3">
        <label for="{{ form.exclude_mobile_app.id_for_label }}" class="text-sm font-medium text-gray-700">
            Exclude from Mobile App (Opt-Out)
        </label>
        <p class="text-xs text-gray-500">
            Registrants with this type will be excluded from the RD mobile app sync.
            If previously synced, they will be removed on the next sync cycle.
        </p>
    </div>
</div>

Data Flow Diagram

1. POSEIDON/ZENITH pulls registration data from Showcare
   - Receives regtype="MobileOut" for opted-out registrants
                |
                v
2. POSEIDON/ZENITH pushes to PLANION API
   - Planion stores regtype="MobileOut" in CECNFPEO
   - CheckRegType looks up Picklist entry for designation mapping
                |
                v
3. RD SYNC (Zenith) runs (scheduled)
   - Queries CECNFPEO JOIN PICKLIST
   - Filters: WHERE exclude_mobile_app = 0 (include in sync)
   - Registrants with exclude_mobile_app = 1 are NOT in sync payload
   - sync_delete() removes from RD any registrants not in current payload
                |
                v
4. RESULTS DIRECT MOBILE APP
   - Only shows eligible registrants
   - Opted-out users are automatically removed

Testing Checklist

Setup

  • Add exclude_mobile_app field to UI form (attendee_types.py + template)
  • Modify get_sql_query() in ps_data.py to filter on exclude_mobile_app
  • Create "MobileOut" entry via Registration Category Mapping screen with exclude_mobile_app=1

Verification

  • Send test registration with regtype="MobileOut" via Planion API
  • Verify registration is stored in CECNFPEO with correct regtype
  • Run sync_regconf and verify "MobileOut" registrant is NOT sent to RD
  • Run sync_delete and verify previously-synced "MobileOut" registrants are DELETED from RD
  • Change "MobileOut" registrant back to normal type and run sync - verify they are added to RD

CLI Commands for Testing

# View Planstone registrants (should NOT include MobileOut after code change)
python methods.py get_ps_regconf -a ASPET -c AM2026

# View RD roster (may still include MobileOut until sync_delete runs)
python methods.py get_rd_roster -a ASPET -c AM2026

# Run sync with deletion
python methods.py sync_all -a ASPET -c AM2026 -d 1

# Or run just the delete sync
python methods.py sync_delete -a ASPET -c AM2026

Critical Files Summary

File Location Purpose
Planion
psAPIRegConf.pas /home/bflorian/src/planion/api/ Registration API - stores regtype in CECNFPEO
Zenith RD Integration
ps_data.py /home/bflorian/src/products/zenith/poseidon/integrations/resultsdirect/ KEY FILE - get_sql_query() needs exclude_mobile_app filter (line 226)
actions.py /home/bflorian/src/products/zenith/poseidon/integrations/resultsdirect/ sync_delete() handles RD deletions (lines 234-291)
rd_api.py /home/bflorian/src/products/zenith/poseidon/integrations/resultsdirect/ RD API client (GET/POST/DELETE)
aspet.py /home/bflorian/src/products/zenith/poseidon/integrations/resultsdirect/ ASPET-specific data transformations
methods.py /home/bflorian/src/products/zenith/poseidon/integrations/resultsdirect/ CLI for sync operations
Zenith Models
planion_picklist.py /home/bflorian/src/products/zenith/poseidon/models/planion/ Picklist model with exclude_mobile_app field (line 74)
planion_cecnfpeo.py /home/bflorian/src/products/zenith/poseidon/models/planion/ Registration records with regtype field
Zenith UI (optional)
attendee_types.py /home/bflorian/src/products/zenith/poseidon/views/backstage/config/ UI form for Registration Category Mapping
attendee_type_form.html /home/bflorian/src/products/zenith/poseidon/templates/backstage/config/ UI template for the form
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment