docs: update README with comprehensive deposit system documentation

- Add new '💰 Deposit System' section with full business logic
- Document 24-hour late cancellation rule
- Explain optional forgive_no_show boolean for admin forgiveness
- Explain optional enforce_deposits boolean for admin booking override
- Document no-show accumulation (2+ in 6 months = 3 deposits)
- Document deposit reduction on payment
- Add API examples and implementation files reference
- Update payment_type enum to include all types (deposit, full, tip, balance, partial)
- Add deposit examples showing different scenarios
- Update Simplified Deposits status line with current behavior
- Remove outdated 48h notice reference
This commit is contained in:
2026-03-07 17:41:03 +00:00
parent c275265794
commit 2623b62573
+145 -4
View File
@@ -319,7 +319,7 @@ docker compose exec backend sh
| Image Metadata Stripping | ✅ | ❌ | EXIF/GPS stripped on upload via `imaging` library |
| Profile Pictures | ✅ | ✅ | Upload to separate bucket, cropper, circular display, CalDAV sync |
| Auto-Booking Status | ✅ | ✅ | Auto-transition: confirmed → in_progress → completed based on time |
| Simplified Deposits | ✅ | ⚠️ | `deposits_required` INT on users table (3 default), 48h notice, reduces on payment |
|| Simplified Deposits | ✅ | ⚠️ | **24h late cancellation rule**: < 24h = no-show (+3 deposits, optional forgiveness), ≥ 24h = normal cancellation. Admin can bypass checks. Reduces by 1 per payment on completed booking.
| Contact Page | ✅ | ✅ | Dynamic data from first admin user via `/api/contact` endpoint |
| Email Verification | ✅ | ❌ | Verification codes, generate/check endpoints |
| Calendar Export | ✅ | ⚠️ | ICS download endpoint, Add to Calendar button (backend complete) |
@@ -373,6 +373,147 @@ All three flows integrate with the **holiday/exceptional hours** system to preve
---
## 💰 Deposit System
### Overview
The deposit system is a **simplified user-level tracking mechanism** that enforces a 3-deposit requirement before new bookings are allowed. It's designed to reduce booking abandonment and protect against chronic no-shows.
**Key Concepts**:
- `deposits_required`: Integer (0-3) on users table tracking outstanding deposit obligations
- `deposit_required`: Boolean on bookings table, snapshotted at creation time
- `deposit_amount`: Calculated as 20% of booking total for display
- `deposit_paid`: True when pre-start payments cover the deposit amount
### Cancellation Rules (Late = < 24 Hours)
| Scenario | Time Until Start | Forgiveness | Result Status | Penalty | User Blocked? |
|----------|------------------|-------------|---------------|---------|---------------|
| **Late cancellation (normal)** | < 24h | No/Omitted | `no_show` | +3 deposits (resets to 3, not +=) | Yes* |
| **Late cancellation (forgiven)** | < 24h | Yes | `client_cancelled` | None | No |
| **Normal cancellation** | ≥ 24h | Any | `client_cancelled` | None | No |
| **Pending cancellation** | Any | Any | Deleted | None | No |
*Assuming `deposits_required` > 0 after penalty
### API: User Cancellation
**Endpoint**: `PUT /api/bookings/{id}/cancel`
**Request**:
```json
{
"reason": "no_show",
"forgive_no_show": true // Optional: true = forgive penalty, false/omitted = enforce penalty
}
```
**Behavior**:
- `< 24h` without forgiveness → `status = no_show`, `deposits_required = 3`
- `< 24h` with forgiveness → `status = client_cancelled`, no penalty
- `≥ 24h``status = client_cancelled`, no penalty (always)
### Admin Booking Creation with Deposit Control
**Endpoint**: `POST /api/admin/bookings`
**Request**:
```json
{
"user_id": "USR123",
"start_time": "2026-03-10T10:00:00Z",
"service_ids": ["SVC1"],
"enforce_deposits": false // Optional: true (default) = enforce checks, false = bypass checks
}
```
**Behavior**:
- `enforce_deposits = true` (default): Apply one-active-booking limit if `deposits_required > 0`
- `enforce_deposits = false`: Bypass all deposit checks, allow multiple active bookings
**Use Cases**:
- `true`: Standard workflow, ensure users clear deposits before booking again
- `false`: Emergency/special cases where admin needs to override deposit restrictions
### No-Show Accumulation
**Rule**: 2+ unforgiven no-shows in rolling 6 months → `deposits_required = 3`
**Trigger**: Automatic via `ApplyDepositsIfNeeded()` when:
1. User has status = `no_show` (without forgiveness flag)
2. Booking occurred within last 6 months
3. Not yet marked as "forgiven" in `forgiven_no_shows` table
4. Count ≥ 2
**Consequence**: User blocked from new bookings (one-active-booking limit enforced)
### Deposit Reduction
**Rule**: When booking transitions to `completed` with ≥ 1 payment → `deposits_required -= 1`
**Logic**:
- Minimum: 0 (never negative)
- Reduction happens once per booking (not per payment)
- User must complete bookings with payments to clear all 3 deposits
### Deposit Fields in Booking API Response
```json
{
"id": "BK123",
"deposit_required": true, // Snapshot: was deposit required at booking time?
"deposit_amount": 24.50, // 20% of total_amount
"deposit_paid": false, // Sum of pre-start payments >= deposit_amount?
"deposit_deadline": "2026-03-09T10:00:00Z", // start_time - 24 hours
"total_amount": 122.50,
"amount_paid": 0.00,
"amount_due": 122.50
}
```
### Implementation Files
| File | Changes | Details |
|------|---------|----------|
| `backend/handlers/bookings/bookings.go` | Cancellation logic | 24h threshold, optional `forgive_no_show` boolean |
| `backend/handlers/bookings/manage.go` | Admin booking creation | Optional `enforce_deposits` boolean, deposit checks |
| `backend/handlers/bookings/manage.go` | Removed function | `ForgiveNoShowsForUser()` (now per-cancellation) |
### Database Schema
| Table | Column | Type | Purpose |
|-------|--------|------|----------|
| `users` | `deposits_required` | INT | Outstanding deposit count (0-3) |
| `bookings` | `deposit_required` | BOOLEAN | Snapshot of requirement at booking time |
| `payments` | `payment_type` | ENUM | Includes `deposit`, `full`, `tip`, `balance`, `partial` |
| `forgiven_no_shows` | `booking_id` | CHAR(12) | Tracks forgiven no-shows for 6-month accumulation |
### Deposit Examples
**Example 1: New User Books**
```
User: deposits_required = 0
→ Booking: deposit_required = false
→ Response: deposit_amount shown, but deposit_paid always false
```
**Example 2: User with Deposits Late Cancels**
```
User: deposits_required = 1
Cancels < 24h without forgiveness
→ Result: deposits_required = 3 (reset, not incremented)
→ User blocked from new bookings
```
**Example 3: Admin Overrides Deposits**
```
Admin creates booking with enforce_deposits = false
User has deposits_required = 2 + active booking
→ Result: Booking created successfully
→ Deposit check bypassed
```
---
## 🔍 Helpful Greps
### All Three Booking Flows
@@ -498,9 +639,9 @@ grep -rn "console\.log" frontend/src/ --include="*.svelte" --include="*.ts"
|------|--------|
| `account_role` | `user`, `admin` |
| `account_type` | `standard`, `vip`, `guest` |
| `booking_status` | `pending`, `confirmed`, `in_progress`, `completed`, `client_cancelled`, `we_cancelled`, `re-schedule`, `no_show`, `no_deposit` |
| `payment_type` | `deposit`, `full`, `refund` |
| `payment_method` | `cash`, `card`, `bank_transfer`, `square` |
|| `booking_status` | `pending`, `confirmed`, `in_progress`, `completed`, `client_cancelled`, `we_cancelled`, `re-schedule`, `no_show`, `no_deposit` |
|| `payment_type` | `deposit`, `full`, `tip`, `balance`, `partial` |
|| `payment_method` | `online_square`, `in_person_card`, `cash`, `giftcard`, `discount` |
| `payment_status` | `pending`, `completed`, `failed`, `refunded` |
| `admin_notification_reason` | `pending_booking`, `cancelled_booking`, `rescheduled_booking`, `1_week_no_pay`, `1_month_no_pay`, `affiliate_claim`, `late_cancellation`, `no_deposit`, `deposit_paid` |