# Aether Events — Badges

The Badges module manages event attendee records and their physical badge configurations. It supports multi-source imports, field protection for onsite edits, and multi-tier access control for self-service review.

---

## Data Model & Hierarchy

### Core Objects
- **Event Badge** (`event_badge`): The attendee record containing name, title, affiliations, and tracking flags.
- **Badge Template** (`event_badge_template`): The visual and structural configuration for printing (branding, layout, QR placement).

### Relationships
- **Badge → Event:** Many-to-one.
- **Badge → Template:** Many-to-one (via `event_badge_template_id`).
- **Badge → Person:** Optional link to core Aether Person record for unified profiles.

---

## Critical Design Pattern: Override Fields

### Purpose
The `*_override` fields pattern (established in 2018) protects data from being overwritten during scheduled cron syncs from external systems (iMIS, Novi, etc.). This ensures that staff corrections or attendee self-updates persist across multiple sync cycles.

### How It Works
1.  **Import:** External systems populate **REGULAR** fields only.
2.  **Display Logic:** The UI displays the `*_override` field if it has a value; otherwise, it falls back to the regular field.
3.  **HTML Rendering:** Certain display fields (Name, Title, Affiliations, Location) support HTML markup for rich text formatting (bold, italics, line breaks) on the physical badge.

### Standard Override Pairs

| Regular Field | Override Field | Editable By | HTML? |
|---|---|---|---|
| `full_name` | `full_name_override` | Staff, Attendee | ✅ |
| `professional_title` | `professional_title_override` | Staff, Attendee | ✅ |
| `affiliations` | `affiliations_override` | Staff, Attendee | ✅ |
| `location` | `location_override` | Staff, Attendee | ✅ |
| `email` | `email_override` | Staff Only | No |
| `badge_type` | `badge_type_override` | Staff Only | No |

---

## External System Integration

Aether acts as a **Pull-Only** consumer for registration data. It does not push changes back to external systems, maintaining them as the source of truth for base registration while Aether handles the "Onsite Truth."

### Supported Sources
- **iMIS**, **Novi AMS**, **Impexium** (Associations)
- **Zoom**, **Cvent** (Registrations)
- **Confex** (Abstracts/Presenters)
- **Custom CSV/Excel**

---

## Access Control & Permissions

| Level | Access |
|---|---|
| **Authenticated** | View own badge, limited self-edit (overrides only). |
| **Trusted** | Search all badges, view all, reprint existing badges. |
| **Administrator** | Full CRUD, bulk operations, override any field. |
| **Manager** | All Admin + Event/Template configuration. |

### Attendee Self-Service (`/review`)
Attendees can access their own record via a passcode-gated link (typically `?passcode=...`). This allows them to verify their info and provide preferred name/title overrides before printing.

---

## Search & Filter Capabilities

- **Fulltext Search:** Matches against a consolidated `default_qry_str` (Name, email, IDs).
- **Multi-Word Logic:** Queries like "Scott Idem" are split and treated as `LIKE %Scott% AND LIKE %Idem%`.
- **QR Scan Search:** Scanning an attendee's QR code (from a confirmation email or old badge) immediately jumps to their record.
- **Advanced Filters (Trusted + Edit Mode):** Badge Type, Printed Status, Affiliations, Sort Order.

### Visibility Filter (Trusted + Edit Mode)

Three-option select controlling which records are shown:

| Option | Who can set it | Effect |
| --- | --- | --- |
| **Default** | Any | Hides hidden and disabled badges |
| **Show Hidden** | Trusted | Shows hidden badges alongside normal ones |
| **Show Disabled + Hidden** | Manager only | Shows all records regardless of enable/hide flags |

### Result Limit Stepper (Edit Mode)

Controls the maximum number of results returned. Only visible in edit mode.

| Access Level | Range | Step |
| --- | --- | --- |
| Below Trusted | Fixed 25 | — |
| Trusted | 25 – 250 | 25 |
| Manager+ | 25 – 2550 | 25 up to 250, then 100 |

### Badge Type Filter — Known Limitation

The badge type dropdown in the search form uses a **hardcoded list**, not the template's `badge_type_list`. This means the codes shown in the filter may not match the codes used by the current event's template. This is a known gap — the fix requires passing the template object into the search component. Until resolved, staff can still search by name/email and filter results manually.

---

## Print Tracking

Aether tracks the lifecycle of every physical badge to prevent unauthorized reprints and monitor kiosk activity.

| Field | Purpose |
|---|---|
| `print_count` | Increments on every "Print Badge" action. |
| `print_first_datetime` | Timestamp of the very first print. |
| `print_last_datetime` | Timestamp of the most recent print. |

> **Operational Note:** Reprints triggered via the Edit Mode shortcut do not increment the count; only the formal "Print Badge" workflow does.

---

## Route Map (Badges)

| URL | Purpose |
|---|---|
| `/events/[id]/badges` | Main search and attendee list. |
| `/events/[id]/badges/templates` | Badge template management. |
| `/events/[id]/badges/[id]/print` | The actual print-ready render page. |
| `/events/[id]/badges/[id]/review` | Attendee-facing self-service form. |

---

## Related Documentation
👉 **[MODULE__AE_Events_Badge_Templates.md](./MODULE__AE_Events_Badge_Templates.md)** (Technical reference for layouts)
👉 **[GUIDE__AE_Events_Badges_Onsite.md](./GUIDE__AE_Events_Badges_Onsite.md)** (Hardware & station setup)
👉 **[GUIDE__AE_Events_Onsite_Runbook.md](./GUIDE__AE_Events_Onsite_Runbook.md)** (Onsite operational checklists)
