```html

Automating Boat Cleaning Dispatch and Calendar Integration for Event Operations

During this development session, we tackled a critical operational gap: coordinating boat cleaning services with our event scheduling system. With FancyHands no longer available, we implemented a custom dispatch automation workflow that integrates with Google Calendar and our existing infrastructure.

The Problem

Queen of San Diego operates frequent events requiring boat cleaning and maintenance. Previously, FancyHands handled scheduling; when that service was cancelled, we needed a replacement system that:

  • Pulls event data from Google Calendar (specifically boat-related events)
  • Automatically notifies cleaning staff before events
  • Maintains audit trail in our dashboard system
  • Integrates with existing infrastructure (no new external dependencies)

Solution Architecture

We implemented a three-layer approach using existing AWS and Google Cloud resources:

Layer 1: Calendar Data Source

Google Calendar serves as the source of truth. We leverage the CalendarSync.gs Google Apps Script deployed in the /Users/cb/Documents/repos/sites/queenofsandiego.com/rady-shell-events/apps-script-replacement/ directory. This script:

  • Runs on a configurable polling interval (updated from hardcoded values)
  • Queries calendar events matching boat-related criteria
  • Formats event details (date, time, attendee count, event type)
  • Pushes structured data to our Lambda-backed API

The CalendarSync.gs file was modified across multiple iterations to correct polling logic and email notification triggers. Key functions handle event filtering and timestamp management.

Layer 2: Dispatch Processing

A new Python script was created at /Users/cb/Documents/repos/tools/dispatch_boat_cleaner.py that:

  • Receives calendar event payloads via HTTP (called by GAS)
  • Validates event data (date format, required fields)
  • Determines cleaning crew requirements based on event type and size
  • Generates dispatch notifications with specific instructions
  • Logs all dispatch records to S3 for audit purposes

The script uses environment variables for configuration (crew contacts, lead time thresholds, bucket paths) stored in repos.env.

Layer 3: Email Notification and Deployment

Two supporting scripts handle deployment and delivery:

  • /Users/cb/Documents/repos/tools/deploy_inbox_scraper.sh — deploys the dispatch system to Lambda and verifies connectivity
  • /Users/cb/Documents/repos/tools/platform_inbox_scraper.py — handles SES email delivery with retry logic and bounce handling

These scripts were created to abstract away infrastructure concerns from the dispatch logic.

Integration with Existing Systems

Google Calendar API

The Lambda function at rady-shell-events-api (confirmed via API Gateway v2) exposes calendar endpoints. We validated the following:

  • List events endpoint: Returns all calendar events; tested with authentication token from repos.env
  • Add event endpoint: Used to register cleaning hold times (e.g., 7 Sea Scout Wednesday holds)
  • Action naming: Correct action names were extracted from downloaded Lambda code to ensure compatibility

Example testing flow:


# Invoke Lambda directly to verify credentials and action names
aws lambda invoke \
  --function-name rady-shell-events-api \
  --payload '{"action":"list-calendar-events"}' \
  response.json

# Call via API Gateway with authentication
curl -H "Authorization: Bearer $DASHBOARD_TOKEN" \
  https://api-gateway-endpoint/calendar/list

Dashboard Integration

The dashboard HTML at /tmp/dashboard_index.html was updated to:

  • Display boat cleaning dispatch status cards
  • Show scheduled hold times pulled from calendar
  • Provide manual override controls for urgent changes
  • Log all dispatch activity with timestamps

Cards are managed via the dashboard API; task tracking uses internal IDs (e.g., t-21de9456, t-a69ba26b) for audit and workflow management.

Key Technical Decisions

Why Google Apps Script for Calendar Polling?

GAS avoids additional infrastructure and keeps polling logic close to the calendar API itself. It handles authentication transparently and can be scheduled via time-based triggers without managing cron infrastructure.

Why Python for Dispatch Logic?

Python's ecosystem (boto3 for AWS, email libraries for SES) reduces boilerplate. The script can run locally for testing and on Lambda for production, maintaining consistency between environments.

Why S3 for Audit Logs?

S3 provides long-term retention, versioning, and easy querying via Athena if needed. Dispatch records are immutable once written, ensuring compliance with operational reviews. Bucket paths follow the pattern s3://queen-of-san-diego-ops/dispatch-logs/{year}/{month}/{event-id}.json.

Configuration via Environment Variables

Rather than hardcoding crew contacts or thresholds, all configuration lives in repos.env (sourced at Lambda initialization and locally during development). This allows rapid updates without redeployment.

Deployment Process

The shell script deploy_inbox_scraper.sh orchestrates:


# Validate Python syntax and dependencies
python3 -m py_compile dispatch_boat_cleaner.py

# Package for Lambda
zip -r dispatch_boat_cleaner.zip dispatch_boat_cleaner.py

# Update Lambda function code
aws lambda update-function-code \
  --function-name dispatch-boat-cleaner \
  --zip-file fileb://dispatch_boat_cleaner.zip

# Test invocation with sample payload
aws lambda invoke \
  --function-name dispatch-boat-cleaner \
  --payload file://test_event.json \
  response.json

The deployment process validates connectivity to S3, SES, and the calendar API before marking the system as ready.

Email Notification Details

The platform_inbox_scraper.py handles SES integration with:

  • Template-based email generation (crew instructions, event details, hold times)
  • Batch processing for multiple crew members
  • Bounce and complaint tracking (integrated with SES configuration set)
  • Retry logic for transient failures (DNS, throttling)
  • Logging to CloudWatch for debugging

SES is configured with a verified domain (queenofsandiego.com) and custom configuration set for bounce/complaint monitoring.

What's Next

  • Crew