Files
mooresunnydaze/docs/stripe-reservation-system.md
T

206 lines
5.8 KiB
Markdown

# Moore Sunny Daze — Reservation System with Stripe
## Architecture Overview
```
Guest Browser → Landing Page → Check Availability → Book → Stripe Checkout → Confirmation
Admin Dashboard (Tim)
```
## Components
### 1. Public Booking Flow
```
Landing Page (mooresunnydaze.com)
→ "Check Availability" button
→ Availability calendar (fetches from API)
→ Select dates → guest count → price quote
→ Guest details form (name, email, phone, # guests, pet?)
→ Stripe Checkout (embedded or redirect)
→ Confirmation page + email
```
### 2. Backend API (FastAPI on Core/app1)
| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/api/availability` | GET | Get booked dates for a month |
| `/api/quote` | POST | Calculate price for selected dates |
| `/api/booking` | POST | Create booking (pending payment) |
| `/api/booking/{id}/confirm` | POST | Confirm after Stripe payment |
| `/api/booking/{id}` | GET | View booking details |
| `/api/guest/{email}` | GET | Lookup returning guest |
### 3. Database Schema (SQLite)
```sql
-- Guests
CREATE TABLE guests (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
phone TEXT,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Bookings
CREATE TABLE bookings (
id TEXT PRIMARY KEY,
guest_id TEXT REFERENCES guests(id),
check_in DATE NOT NULL,
check_out DATE NOT NULL,
guests_count INTEGER NOT NULL,
nightly_rate REAL NOT NULL,
cleaning_fee REAL DEFAULT 150,
total REAL NOT NULL,
status TEXT DEFAULT 'pending', -- pending, confirmed, cancelled, completed
stripe_session_id TEXT,
stripe_payment_intent TEXT,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Blocked Dates
CREATE TABLE blocked_dates (
date DATE PRIMARY KEY,
reason TEXT -- 'booking_XYZ', 'maintenance', 'owner'
);
-- Rate Rules
CREATE TABLE rate_rules (
id TEXT PRIMARY KEY,
name TEXT,
start_date DATE,
end_date DATE,
nightly_rate REAL,
min_nights INTEGER DEFAULT 3
);
```
## Stripe Integration
### Setup
1. Tim creates Stripe account (stripe.com)
2. Connects business bank account
3. We get API keys from Stripe Dashboard
4. Store in `.env` on server
### Payment Flow
```python
# 1. Create Stripe Checkout Session
session = stripe.checkout.Session.create(
payment_method_types=['card'],
line_items=[{
'price_data': {
'currency': 'usd',
'product_data': {
'name': f'Moore Sunny Daze — {nights} nights',
'description': f'{check_in} to {check_out}, {guests} guests'
},
'unit_amount': int(total * 100), # cents
},
'quantity': 1
}],
mode='payment',
success_url='https://mooresunnydaze.com/booking/confirmed?session_id={CHECKOUT_SESSION_ID}',
cancel_url='https://mooresunnydaze.com/booking/cancelled',
customer_email=guest_email,
metadata={
'booking_id': booking_id,
'property': 'moore-sunny-daze'
}
)
# 2. Redirect to session.url
# 3. Stripe webhook → mark booking confirmed
```
### Webhook Handling
```python
@app.post("/stripe-webhook")
async def stripe_webhook(request: Request):
payload = await request.body()
sig = request.headers.get('stripe-signature')
event = stripe.Webhook.construct_event(payload, sig, WEBHOOK_SECRET)
if event['type'] == 'checkout.session.completed':
session = event['data']['object']
booking_id = session['metadata']['booking_id']
mark_booking_confirmed(booking_id)
send_confirmation_email(booking_id)
add_blocked_dates(booking_id)
return {"status": "ok"}
```
## Deployment
### Server
- Deploy on Core (152.53.33.195) as systemd service
- Port: 8910 (internal)
- Caddy reverse proxy: `mooresunnydaze.com/api/* → localhost:8910`
### Filesystem
```
/opt/mooresunnydaze/
├── server.py # FastAPI app
├── db.sqlite # SQLite database
├── .env # STRIPE_SECRET_KEY, etc
├── requirements.txt # fastapi, uvicorn, stripe, aiosqlite
└── templates/ # Email templates
```
### systemd Service
```ini
# /etc/systemd/system/mooresunnydaze.service
[Unit]
Description=Moore Sunny Daze Booking API
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/mooresunnydaze
ExecStart=/opt/mooresunnydaze/venv/bin/uvicorn server:app --host 127.0.0.1 --port 8910
Restart=always
[Install]
WantedBy=multi-user.target
```
## Admin Features
1. **Calendar view** — booked/available/blocked dates
2. **Booking management** — confirm, cancel, view details
3. **Guest directory** — past guests, contact info, stay history
4. **Rate management** — seasonal pricing, minimum stays
5. **Block dates** — maintenance, owner use
6. **Revenue reports** — monthly/annual totals
7. **Email templates** — confirmation, pre-arrival, post-stay
## Pricing Integration
Tim's property is currently listed at ~$295/night (peak season, from Airbnb). We'd implement:
- **Base rate:** $295/night peak, $225/night off-peak
- **Cleaning fee:** $150 flat
- **Pet fee:** $50 (if applicable)
- **Minimum stay:** 3 nights
- **Holiday premium:** +20% for major holidays
## Comparison: Direct vs VRBO
| | VRBO (current) | Direct (our system) |
|---|---|---|
| 3-night stay @ $295 | $885 + VRBO fee (~$130) | $885 (no fee) |
| Guest pays | ~$1,015 | $885 |
| Owner receives | ~$885 - VRBO 5% host fee | $885 - Stripe 2.9% |
| Owner net | ~$840 | ~$859 |
| **Savings to guest** | — | **$130 (13%)** |
| **Savings to owner** | — | **~$19/stay + guest relationship** |
## Next Steps
1. ✅ Design complete
2. Set up Stripe account for Tim
3. Build FastAPI backend
4. Deploy on Core
5. Wire up booking widget on landing page
6. Test end-to-end booking flow
7. Go live