Skip to the content.

← Back to Plugin Architecture

5.7 Waivers Plugin

Last Updated: February 2026
Status: Production
Plugin: Waivers
Source: plugins/Waivers/
Migration Order: 4

The Waivers plugin provides comprehensive waiver management for gatherings, including waiver type configuration, document upload tracking, exemption attestation, compliance monitoring, decline workflows, and closure tracking.

Purpose

This plugin enables:

Architecture Overview

Plugin Class

WaiversPlugin extends BasePlugin and implements KMPPluginInterface.

Bootstrap registrations:

Configuration settings:

Controllers

Controller Actions Description
GatheringWaiversController index, view, upload, download, preview, delete, decline, needingWaivers, dashboard, calendarData, indexGathering, mobileSelectGathering, mobileUpload, changeWaiverType, changeActivities, gridData Waiver upload, viewing, compliance, and management
WaiverTypesController index, view, add, edit, delete, toggleActive, downloadTemplate, gridData Waiver type CRUD and template management
GatheringActivityWaiversController add, delete, availableWaiverTypes Manage waiver requirements on gathering activities

GatheringWaiversController uses DataverseGridTrait for server-side grid filtering and injects DocumentService, ImageToPdfConversionService, and RetentionPolicyService.

WaiverTypesController uses DataverseGridTrait and injects DocumentService.

Services

Service Purpose
GatheringActivityService Business logic for adding/removing waiver requirements on activities. Returns ServiceResult.
WaiversNavigationProvider Provides navigation items: Waivers Uploaded, Waiver Dashboard, Waiver Types (Config), Gatherings Needing Waivers (Action Items with badge count)
WaiversViewCellProvider Registers view cells for gathering activity views and gathering views, plus mobile menu items

Data Model

WaiverType Entity

Defines types of waivers with retention policies and templates.

Field Type Description
id int Primary key
name string Waiver type name (unique)
description string|null Description
document_id int|null FK to documents table for uploaded template
template_path string|null External URL to template
retention_policy string JSON-encoded retention policy
exemption_reasons string|null JSON array of exemption reason strings
convert_to_pdf bool Whether to convert uploaded images to PDF
is_active bool Whether this type is available for use
created datetime  
modified datetime  
created_by int|null Footprint
modified_by int|null Footprint
deleted datetime|null Soft delete (Trash)

Virtual fields: retention_policy_parsed (array), retention_description (human-readable string), exemption_reasons_parsed (array)

Retention policy JSON structure:

{
  "anchor": "gathering_end_date|upload_date|permanent",
  "duration": { "years": 1, "months": 0, "days": 0 }
}

GatheringWaiver Entity

Represents an uploaded waiver document or an exemption attestation for a gathering.

Field Type Description
id int Primary key
gathering_id int FK to gatherings
waiver_type_id int FK to waiver types
document_id int|null FK to documents (null for exemptions)
is_exemption bool True if this is an exemption, not an upload
exemption_reason string|null Reason waiver wasn’t needed
status string pending, active, or deleted
retention_date date When this waiver can be purged
created_by int Uploader member ID
created datetime  
modified datetime  
declined_at datetime|null When waiver was declined
declined_by int|null Who declined
decline_reason string|null Why declined

Virtual fields: is_expired, is_active, is_declined, can_be_declined (within 30 days, not already declined, not expired/deleted), status_badge_class, status_display

getBranchId(): Returns the branch ID from the gathering’s hosting branch for authorization scoping.

GatheringActivityWaiver Entity

Join table linking gathering activities to required waiver types.

Field Type Description
gathering_activity_id int Composite PK, FK to gathering_activities
waiver_type_id int Composite PK, FK to waiver_types
created datetime  
created_by int|null Footprint
modified_by int|null Footprint
deleted datetime|null Soft delete

GatheringWaiverClosure Entity

Tracks waiver collection closure status for a gathering. Supports two stages.

Field Type Description
id int Primary key
gathering_id int FK to gatherings (unique)
ready_to_close_at datetime|null When marked ready to close
ready_to_close_by int|null Who marked ready
closed_at datetime|null When fully closed
closed_by int|null Who closed
created datetime  
modified datetime  

Methods: isReadyToClose(), isClosed()

Tables

WaiverTypesTable

GatheringWaiversTable

GatheringActivityWaiversTable

GatheringWaiverClosuresTable

Policies

All policies extend BasePolicy which provides super-user bypass via before().

Entity Policies

Policy Custom Methods Notes
GatheringWaiverPolicy canDownload, canPreview, canChangeWaiverType, canViewGatheringWaivers, canNeedingWaivers, canUploadWaivers, canCloseWaivers, canDecline Steward support: canViewGatheringWaivers, canNeedingWaivers, and canUploadWaivers fall back to steward check if standard permission fails. Steward check respects closure status.
WaiverTypePolicy canToggleActive, canDownloadTemplate Standard permission delegation
GatheringActivityWaiverPolicy availableWaiverTypes Standard permission delegation
WaiverPolicy (none — inherits BasePolicy) Empty policy for GatheringWaiver entity aliasing

Table Policies

Policy Custom Methods Notes
GatheringWaiversTablePolicy canNeedingWaivers Falls back to steward check for non-closed gatherings
WaiverTypesTablePolicy (none — inherits BasePolicy) Standard table authorization
GatheringActivityWaiversTablePolicy (none — inherits BasePolicy) Standard table authorization

Controller Policy

Policy Methods
GatheringWaiversControllerPolicy canNeedingWaivers, canUpload, canChangeWaiverType, canChangeActivities, canDashboard, canCalendarData, canMobileSelectGathering, canMobileUpload

Steward-aware methods (canNeedingWaivers, canUpload, canMobileSelectGathering, canMobileUpload) check standard permission first, then fall back to _isAnySteward() which verifies the user is a steward for at least one non-closed gathering.

JavaScript Controllers

Controller File Purpose
waiver-upload-wizard waiver-upload-wizard-controller.js Multi-step upload wizard: select waiver type → upload pages or attest exemption → review & submit. Uses PDF.js for preview.
waiver-upload waiver-upload-controller.js File selection, validation, preview, and upload progress for waiver images. Supports multiple files with mobile camera integration.
camera-capture camera-capture-controller.js Mobile camera capture UI enhancements using HTML5 capture="environment".
waiver-attestation waiver-attestation-controller.js Modal for attesting waiver not needed. Handles reason selection, AJAX submission, and feedback.
waiver-calendar waiver-calendar-controller.js Monthly calendar showing gatherings color-coded by waiver status (red=none, yellow=partial, green=complete, blue=closed).
waiver-template waiver-template-controller.js Toggle between file upload and external URL for waiver type template source.
add-requirement add-requirement-controller.js Dynamic waiver type discovery for gathering activities. Fetches available types excluding already-assigned ones.
retention-policy-input retention-policy-input-controller.js Structured retention policy editor with anchor, years/months/days inputs, and real-time JSON preview.
exemption-reasons exemption-reasons-controller.js Dynamic list editor for exemption reasons on waiver types. Add/remove reasons stored as JSON array.

View Cells

GatheringActivityWaiversCell

GatheringWaiversCell

Mobile Menu Cell

Routes

All routes under /waivers/ prefix using CakePHP fallback routing:

URL Pattern Controller Action
/waivers/gathering-waivers GatheringWaivers index
/waivers/gathering-waivers/view/:id GatheringWaivers view
/waivers/gathering-waivers/upload/:id GatheringWaivers upload
/waivers/gathering-waivers/dashboard GatheringWaivers dashboard
/waivers/gathering-waivers/needing-waivers GatheringWaivers needingWaivers
/waivers/gathering-waivers/mobile-select-gathering GatheringWaivers mobileSelectGathering
/waivers/gathering-waivers/mobile-upload/:id GatheringWaivers mobileUpload
/waivers/waiver-types WaiverTypes index
/waivers/waiver-types/view/:id WaiverTypes view
/waivers/waiver-types/add WaiverTypes add
/waivers/waiver-types/edit/:id WaiverTypes edit
/waivers/gathering-activity-waivers/add GatheringActivityWaivers add
/waivers/gathering-activity-waivers/delete/:activityId/:waiverTypeId GatheringActivityWaivers delete
/waivers/gathering-activity-waivers/available-waiver-types/:activityId GatheringActivityWaivers availableWaiverTypes

Registered under the “Waivers” parent section (order: 600):

Item Section Order Badge
Waiver Dashboard Waivers 5
Waivers Uploaded Waivers 6
Waiver Types Config 100
Gatherings Needing Waivers Action Items 25 Dynamic count via countGatheringsNeedingWaivers()

Migration History

Migration Description
20251021180737 Create waivers_waiver_types
20251021180804 Create waivers_gathering_activity_waivers
20251021180827 Create waivers_gathering_waivers
20251021180858 Create waivers_gathering_waiver_activities
20251022150936 Add document_id to waiver types
20251023162456 Add deleted to gathering_activity_waivers unique index
20251024012044 Remove member_id from gathering_waivers
20251026000000 Add decline fields (declined_at, declined_by, decline_reason) to gathering_waivers
20251106163803 Add exemption_reasons to waiver types
20251106172020 Add exemption fields (is_exemption, exemption_reason) to gathering_waivers
20251221083000 Drop gathering_waiver_activities table
20251223090000 Create waivers_gathering_waiver_closures
20260131001511 Add ready_to_close fields to gathering_waiver_closures

References