ποΈ System Architecture
Four main layers β click any card for more details
π Tag Status Flow
Every QR tag passes through these statuses
π QR Tag URL Format
All tags share the same URL pattern β unique code per QR
π₯ User Roles
β‘ Tag Activation Flow β 10 Steps
Complete journey from QR scan to successful activation
π― Smart Action Buttons
Shown on the public page after a tag is activated β visitor can choose any action
π Public Frontend Pages
All pages accessible without login β main visitor-facing interface
/public/ or root level. No authentication required. These are the pages a visitor sees after scanning a QR code.π‘οΈ Admin Panel Modules
All admin pages under /admin/ β requires admin authentication
π Tags Management
π₯ User Management
π Analytics & Communications
π€ User Dashboard Pages
Accessible only to activated users (OTP-based session login)
/user/.ποΈ Database Schema
15 core tables β MySQL. PK = Primary Key, FK = Foreign Key, UK = Unique Key
| Column | Type | Notes |
|---|---|---|
| id PK | INT AUTO_INCREMENT | Primary identifier |
| tag_code UK | VARCHAR(20) | Unique code e.g. CAR1001 |
| status | ENUM | available / assigned / activated / blocked / expired |
| assigned_user_id FK | INT NULL | β users.id |
| tag_type | VARCHAR(30) | vehicle / contact / emergency / visitor |
| batch_name | VARCHAR(50) | Bulk generation batch label |
| qr_image | VARCHAR(255) | Path to QR image file |
| created_at | TIMESTAMP | Auto-set on insert |
| Column | Type | Notes |
|---|---|---|
| id PK | INT AUTO_INCREMENT | |
| mobile UK | VARCHAR(15) | Used for OTP login |
| full_name | VARCHAR(100) | |
| whatsapp_number | VARCHAR(15) | Can differ from mobile |
| status | ENUM | active / blocked |
| created_at | TIMESTAMP |
| Column | Type | Notes |
|---|---|---|
| id PK | INT AUTO_INCREMENT | |
| user_id FK | INT | β users.id |
| tag_id FK | INT | β tags.id |
| vehicle_number | VARCHAR(20) | For vehicle tags |
| masked_call_enabled | TINYINT(1) | Toggle ON/OFF |
| whatsapp_enabled | TINYINT(1) | Toggle ON/OFF |
| sms_enabled | TINYINT(1) | Toggle ON/OFF |
| callback_enabled | TINYINT(1) | Toggle ON/OFF |
| support_enabled | TINYINT(1) | Toggle ON/OFF |
| location_enabled | TINYINT(1) | Toggle ON/OFF |
| Column | Type | Notes |
|---|---|---|
| id PK | INT AUTO_INCREMENT | |
| tag_id FK | INT | β tags.id |
| user_id FK | INT | β users.id |
| otp_verified | TINYINT(1) | 1 = verified, 0 = skipped |
| ip_address | VARCHAR(45) | IPv4 or IPv6 |
| activation_source | VARCHAR(50) | web / android / ios |
| activated_at | TIMESTAMP |
| Column | Type | Notes |
|---|---|---|
| id PK | INT AUTO_INCREMENT | |
| tag_id FK | INT | β tags.id |
| device_type | VARCHAR(30) | mobile / desktop / tablet |
| latitude | DECIMAL(10,7) | GPS coordinate |
| longitude | DECIMAL(10,7) | GPS coordinate |
| ip_address | VARCHAR(45) | |
| scan_time | TIMESTAMP | Auto-set |
| Column | Type | Notes |
|---|---|---|
| id PK | INT AUTO_INCREMENT | |
| tag_id FK | INT | β tags.id |
| action_type | VARCHAR(50) | whatsapp_click / pdf_download / callback / call / location |
| visitor_mobile | VARCHAR(15) | Optional β if provided by visitor |
| status | VARCHAR(20) | success / failed / pending |
| created_at | TIMESTAMP |
| Column | Type | Notes |
|---|---|---|
| id PK | INT AUTO_INCREMENT | |
| tag_id FK | INT | β tags.id |
| visitor_name | VARCHAR(100) | |
| visitor_mobile | VARCHAR(15) | |
| status | ENUM | new / contacted / closed |
| created_at | TIMESTAMP |
| Column | Type | Notes |
|---|---|---|
| id PK | INT AUTO_INCREMENT | |
| email UK | VARCHAR(100) | Login email |
| password | VARCHAR(255) | bcrypt hashed |
| role | ENUM | super_admin / support_agent |
| is_active | TINYINT(1) | 1 = active |
| Column | Type | Notes |
|---|---|---|
| plans.id PK | INT | |
| plans.name | VARCHAR(50) | Basic / Standard / Premium |
| plans.max_tags | INT | Max tags per user |
| plans.validity_days | INT | 365 / 730 etc. |
| subscriptions.user_id FK | INT | β users.id |
| subscriptions.plan_id FK | INT | β plans.id |
| subscriptions.expires_at | DATE | Expiry date |
| subscriptions.payment_status | ENUM | paid / pending / free |
| Column | Type | Notes |
|---|---|---|
| id PK | INT AUTO_INCREMENT | |
| setting_key UK | VARCHAR(100) | e.g. smtp_host, sms_api_key |
| setting_value | TEXT | Stored as text, cast in PHP |
| updated_at | TIMESTAMP | Last modified |
π Build Phases
Start with Phase 1 (MVP) β working product in shortest time
π Folder Structure
Complete project directory layout
βββ π admin/
β βββ π tags/ # list.php, bulk-generate.php, assign.php
β βββ π users/ # list.php, view.php, subscriptions.php
β βββ π analytics/ # index.php, scan-logs.php
β βββ π communications/ # callbacks.php, tickets.php
β βββ π settings/ # index.php (SMTP, SMS, WA API keys)
βββ π user/
β βββ dashboard.php
β βββ profile.php
β βββ settings.php # feature toggles
β βββ scan-logs.php
β βββ action-logs.php
β βββ pdf-etag.php
β βββ callbacks.php
β βββ support.php
βββ π public/
β βββ activate.php # multi-step activation wizard
β βββ action.php # smart action buttons page
β βββ callback.php # visitor callback form
β βββ location.php # GPS share page
βββ π api/
β βββ send-otp.php
β βββ verify-otp.php
β βββ activate-tag.php
β βββ save-callback.php
β βββ save-location.php
β βββ log-action.php
β βββ generate-pdf.php
β βββ bulk-generate-tags.php
βββ π includes/
β βββ db.php # DB connection (PDO)
β βββ config.php # global constants
β βββ auth.php # session / role checks
β βββ functions.php # helper functions
β βββ header.php
β βββ footer.php
βββ π assets/ # CSS, JS, images
βββ π uploads/
β βββ π qr/ # generated QR images
β βββ π pdf/ # generated PDFs
β βββ π users/ # user profile photos
βββ tag.php # root: /tag/{code} β routes to public/activate or public/action