JADA Proposals DynamoDB System: Market Analytics and Charter Conversion Tracking
What Was Done
Built ~/icloud-jada-ops/tools/proposals.py — a proposal ledger backed by the
jada-proposals DynamoDB table (us-east-1, profile queenofsandiego).
Backfilled 5 active proposals (Brandon, Savannah, Elena, Mick, Karlie B) using a one-time
backfill_proposals.py script.
The system tracks the full proposal lifecycle from DRAFT through ACCEPTED/DECLINED/EXPIRED
and provides market analytics segmented by month, occasion, and platform.
DynamoDB Schema
Table: jada-proposals, region: us-east-1
- PK:
proposal_id(String) — format:YYYYMMDD-{name_slug} - GSI:
by-dateoncharter_date(ISO string) — enables range queries by date - Status enum:
DRAFT | SENT | ACCEPTED | DECLINED | EXPIRED
Computed fields stored at write time (not re-derived at read time):
net_to_jada— listed price × (1 − platform fee): GMB=0.10, Boatsetter=0.15, Sailo=0.10, Direct/Referral=0.0guest_total— what the renter actually pays (listed × 1.10 for GMB's 10% buyer fee)per_person_at_quoted— guest_total ÷ headcountper_person_at_max— guest_total ÷ 28 (fill-the-boat incentive metric)season— derived from charter_date: peak (Jul–Sep), shoulder (Apr–Jun, Oct), off (Nov–Mar)day_of_week— 0=Mon through 6=Sun
CLI Commands
python3 tools/proposals.py save '{"proposal_id":"20260807-karlie","client_name":"Karlie B","platform":"GMB","listed_price":2190,...}'
python3 tools/proposals.py list
python3 tools/proposals.py convert 20260807-karlie 18 2190
python3 tools/proposals.py decline 20260704-brandon
python3 tools/proposals.py stats
GMB Fee Math (Baked In)
GetMyBoat has an asymmetric fee structure that both sides of the transaction pay:
- Host (JADA) payout = listed_price × 0.885 (GMB keeps 11.5%)
- Renter pays = listed_price × 1.1388 (GMB adds 13.88% buyer fee)
- Standard 2hr base: $2,190 listed → renter pays $2,494.63 → JADA nets $1,938
This math is pre-computed in build_record() and stored in DDB so analytics queries
don't need to re-derive it. The $2,190 listed price was chosen specifically to keep
renter cost under the $2,500 psychological ceiling.
Market Analytics
The stats() command segments the proposal pipeline by:
- Month — volume and conversion rate by calendar month
- Occasion type — bachelor/bachelorette, birthday, corporate, memorial, general
- Platform — GMB, Boatsetter, Sailo, Direct, Referral
- Per-person yield range for accepted charters (metric for pricing efficiency)
Intended use: detect FOMO opportunities (multiple proposals for same date slot), identify high-converting occasions, and benchmark per-person yield across platforms.
Active Proposals (as of 2026-06-26)
- Brandon — Jul 4, 4hr, 14 guests, GMB, $4,800 listed (July 4 premium). Status: SENT. Competing with Mick for same afternoon slot.
- Savannah — Aug 8, 2hr, 21 guests, GMB, $2,150 listed. Status: SENT.
- Elena — Sep 19, 2hr, 30 guests, GMB, $2,150 listed. Status: SENT. Flagged: 30 guests is at USCG capacity limit.
- Mick — Jul 4, 3hr, group size TBD, referral. Status: DRAFT. Competing with Brandon.
- Karlie B — Aug 7, 2hr, 18 guests, GMB, $2,190 listed. Status: SENT.
Key Decisions
- DDB over Google Sheets — no OAuth re-auth needed (plain AWS profile), DDB handles concurrent writes safely
- Computed fields stored at write time — analytics queries are simple scans, no in-flight math
- Platform fee table embedded in proposals.py, not pulled from a config file — single source for this rarely-changing data
What's Next
- Add webhook from GetMyBoat booking confirmation → auto-mark proposal ACCEPTED in DDB
- Add
fomo_checkcommand: scan for multiple SENT proposals on same date - Wire
stats()output into the monthly Sheraton report