diff --git a/README.md b/README.md index 666407e..9743d01 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,86 @@

IMFestival SMS Dashboard

-### What is this repository? +A web-based SMS notification system for managing festival attendees and delivering workshop reminders via [Clickatell](https://www.clickatell.com/). -This repository holds the SMS notification system for IMFestival, featuring a web dashboard along with containerization files (`Dockerfile` and `docker-compose.yml`) for easy deployment. +![alt text](./dashboard.jpg "Title") -## How to use the dashboard -The dashboard will allow the upload of a CSV file that contains the user's name, email, workshop name and times. +## Architecture -You can use the dashboard to schedule messages for delivery to selected users at specific times. Message content can be configured directly within the dashboard and supports the placeholders {name} for the recipient's name, {workshop} for the workshop name, and {workshop_time} for the workshop time. +Three Docker services work together: -## Considerations -The character limit needs to check against the longest workshop name to ensure the limit isn't misrespresented. +| Service | Tech | Role | +|---------|------|------| +| `db` | MariaDB 11 | Persistent storage for attendees, templates, schedules, and delivery logs | +| `web` | PHP 8.3 + Apache | Dashboard UI and REST API | +| `worker` | Python 3 + Flask | SMS dispatch service; polls for due scheduled rules every 60 s | -### Python Dependencies -- numpy -- dateutil -- pandas +## Features + +- **CSV import** — upload an attendee export from splash; the importer auto-detects common column names for first name, last name, email, and mobile number +- **Workshop sessions** — attendees are linked to named sessions with a start time, enabling per-workshop targeting +- **SMS templates** — reusable message bodies (≤ 160 chars) with `{name}`, `{workshop}`, and `{workshop_time}` placeholders +- **Scheduled texts** — rules fire relative to a workshop start time (e.g. *30 minutes before*) or at a specific datetime +- **Send now** — dispatch immediately to all attendees or a single workshop group +- **Delivery log** — per-recipient status tracking (`sent` / `failed`) +- **Sandbox mode** — tag sends as tests so they are excluded from sent stats or cost calculations without disabling the API +- **Admin panel** — configure the Clickatell API key, cost-per-SMS, and sender ID through the UI + +## Getting started + +### Prerequisites + +- Docker and Docker Compose + +### 1. Create a `.env` file + +Create a `.env` file in the project root. All three services read from it. + +```env +# MariaDB +MYSQL_ROOT_PASSWORD=changeme +MYSQL_DATABASE=imf_sms +MYSQL_USER=imf_user +MYSQL_PASSWORD=changeme +MYSQL_HOST=db + +# Optional — defaults to Europe/London +TZ=Europe/London +``` + +### 2. Start the stack + +```bash +docker compose up --build +``` + +The dashboard will be available at **http://localhost:8000**. + +### 3. Configure Clickatell + +Open **Admin** in the dashboard and enter your Clickatell API key. You can also set a cost-per-SMS and a default sender ID here. + +### 4. Import attendees + +Go to **Attendees** and upload a CSV export from your event management tool. The required columns are `first_name` (or `First Name`), `last_name`, and `mobile_number` (or `Custom: Mobile number`). `email` and workshop session columns are optional but recommended. + +## CSV column mapping + +The importer accepts comma- or tab-separated files and recognises these column names (case-insensitive): + +| Field | Accepted column names | +|-------|-----------------------| +| First name | `first name`, `first_name`, `firstname`, `first` | +| Last name | `last name`, `last_name`, `lastname`, `last` | +| Mobile | `custom: mobile number`, `mobile_number`, `mobile number`, `mobile`, `phone`, `telephone`, `cell` | +| Email | `email` | +| Workshop | `custom: please pick one workshop…` (and similar variants) | + +## SMS placeholders + +| Placeholder | Replaced with | +|-------------|---------------| +| `{name}` | Recipient's first name | +| `{workshop}` | Workshop name | +| `{workshop_time}` | Workshop start time | + +The character counter in the template editor calculates length against the longest possible substitution so the 160-character limit is never misrepresented.