Spaces:
Sleeping
Sleeping
Initial Commit
Browse files- .gitignore +53 -0
- README.md +434 -10
- check_slots.py +59 -0
- demo_ai_model.py +194 -0
- diagnose_api.py +66 -0
- diagnose_booking.py +138 -0
- diagnose_payment_update.py +119 -0
- final_system_test.py +190 -0
- parking_model.pkl +3 -0
- requirements.txt +27 -0
- run_tests.py +77 -0
- test_api_raw.py +111 -0
- test_booking_userid.py +73 -0
- test_database.py +285 -0
- test_slot_availability.py +117 -0
- test_system.py +230 -0
.gitignore
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Python
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
*.so
|
| 6 |
+
.Python
|
| 7 |
+
env/
|
| 8 |
+
venv/
|
| 9 |
+
ENV/
|
| 10 |
+
build/
|
| 11 |
+
develop-eggs/
|
| 12 |
+
dist/
|
| 13 |
+
downloads/
|
| 14 |
+
eggs/
|
| 15 |
+
.eggs/
|
| 16 |
+
lib/
|
| 17 |
+
lib64/
|
| 18 |
+
parts/
|
| 19 |
+
sdist/
|
| 20 |
+
var/
|
| 21 |
+
wheels/
|
| 22 |
+
*.egg-info/
|
| 23 |
+
.installed.cfg
|
| 24 |
+
*.egg
|
| 25 |
+
|
| 26 |
+
# Environment variables
|
| 27 |
+
.env
|
| 28 |
+
|
| 29 |
+
# IDE
|
| 30 |
+
.vscode/
|
| 31 |
+
.idea/
|
| 32 |
+
*.swp
|
| 33 |
+
*.swo
|
| 34 |
+
*~
|
| 35 |
+
|
| 36 |
+
# Model files
|
| 37 |
+
#*.pkl
|
| 38 |
+
#*.h5
|
| 39 |
+
#*.model
|
| 40 |
+
|
| 41 |
+
# Logs
|
| 42 |
+
*.log
|
| 43 |
+
logs/
|
| 44 |
+
|
| 45 |
+
# OS
|
| 46 |
+
.DS_Store
|
| 47 |
+
Thumbs.db
|
| 48 |
+
|
| 49 |
+
# Database
|
| 50 |
+
*.db
|
| 51 |
+
*.sqlite3
|
| 52 |
+
|
| 53 |
+
demo_ai_model.py
|
README.md
CHANGED
|
@@ -1,10 +1,434 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Smart Parking System - AI & Payment Module
|
| 2 |
+
|
| 3 |
+
An intelligent parking management system with AI-powered slot recommendations and integrated payment processing in sandbox mode.
|
| 4 |
+
|
| 5 |
+
## 🚀 Features
|
| 6 |
+
|
| 7 |
+
### 1. AI-Powered Slot Recommendation
|
| 8 |
+
- **Basic Classification Model** using Random Forest
|
| 9 |
+
- Considers multiple factors:
|
| 10 |
+
- **Proximity** to user location (Haversine distance calculation)
|
| 11 |
+
- **User feedback** scores (historical ratings)
|
| 12 |
+
- **Slot popularity** (booking frequency and usage patterns)
|
| 13 |
+
- **Real-time availability**
|
| 14 |
+
- **Price factors**
|
| 15 |
+
- Smart ranking algorithm with weighted scoring
|
| 16 |
+
- Continuous learning from user feedback
|
| 17 |
+
|
| 18 |
+
### 2. Payment Integration (Sandbox Mode)
|
| 19 |
+
- **Razorpay** integration in test/sandbox mode
|
| 20 |
+
- Payment order creation
|
| 21 |
+
- Payment link generation
|
| 22 |
+
- Payment verification with signature validation
|
| 23 |
+
- Refund support
|
| 24 |
+
- Payment simulation for development/testing
|
| 25 |
+
- Complete transaction tracking
|
| 26 |
+
|
| 27 |
+
### 3. Database Integration
|
| 28 |
+
- **PHP API Backend** at `https://aadarshsenapati.in/api/api.php`
|
| 29 |
+
- Real-time parking slot data
|
| 30 |
+
- User registration and management
|
| 31 |
+
- Booking system with unique UIDs
|
| 32 |
+
- Payment status tracking
|
| 33 |
+
- Feedback storage and retrieval
|
| 34 |
+
- Complete CRUD operations
|
| 35 |
+
|
| 36 |
+
### 4. Feedback System
|
| 37 |
+
- Collect user ratings (1-5 stars)
|
| 38 |
+
- Track user satisfaction metrics
|
| 39 |
+
- Store feedback in database
|
| 40 |
+
- Use feedback for AI model improvement
|
| 41 |
+
- Automated model retraining with new data
|
| 42 |
+
- Feedback analytics and reporting
|
| 43 |
+
|
| 44 |
+
## 📁 Project Structure
|
| 45 |
+
|
| 46 |
+
```
|
| 47 |
+
CodeStrom/
|
| 48 |
+
├── ai_model/
|
| 49 |
+
│ └── parking_slot_classifier.py # ML model for slot recommendation
|
| 50 |
+
├── backend/
|
| 51 |
+
│ ├── main.py # FastAPI backend API
|
| 52 |
+
│ ├── payment_service.py # Razorpay payment integration
|
| 53 |
+
│ └── database_api.py # Database API client
|
| 54 |
+
├── requirements.txt # Project dependencies
|
| 55 |
+
├── test_system.py # Comprehensive test suite
|
| 56 |
+
├── test_database.py # Database integration tests
|
| 57 |
+
├── .env.example # Environment variables template
|
| 58 |
+
├── .gitignore
|
| 59 |
+
├── render.yaml # Render deployment config
|
| 60 |
+
├── railway.json # Railway deployment config
|
| 61 |
+
└── vercel.json # Vercel deployment config
|
| 62 |
+
```
|
| 63 |
+
|
| 64 |
+
## 🛠️ Installation & Setup
|
| 65 |
+
|
| 66 |
+
### Prerequisites
|
| 67 |
+
- Python 3.11+
|
| 68 |
+
- pip (Python package manager)
|
| 69 |
+
- Razorpay account with test credentials
|
| 70 |
+
|
| 71 |
+
### Step 1: Install Dependencies
|
| 72 |
+
```bash
|
| 73 |
+
# Navigate to project directory
|
| 74 |
+
cd CodeStrom
|
| 75 |
+
|
| 76 |
+
# Install required packages
|
| 77 |
+
pip install -r requirements.txt
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
### Step 2: Configure Environment
|
| 81 |
+
```bash
|
| 82 |
+
# Create .env file from template
|
| 83 |
+
copy .env.example .env
|
| 84 |
+
|
| 85 |
+
# Edit .env and add your Razorpay test credentials
|
| 86 |
+
# RAZORPAY_KEY_ID=rzp_test_RYlqJbc24Sl6jz
|
| 87 |
+
# RAZORPAY_KEY_SECRET=bghQe0L7iort9vmqb6Jlf8Ec
|
| 88 |
+
```
|
| 89 |
+
|
| 90 |
+
### Step 3: Test Database Connection
|
| 91 |
+
```bash
|
| 92 |
+
# Test database API integration
|
| 93 |
+
python test_database.py
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
### Step 4: Test the Complete System
|
| 97 |
+
```bash
|
| 98 |
+
# Run comprehensive test suite
|
| 99 |
+
python test_system.py
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
### Step 5: Start Development Server
|
| 103 |
+
```bash
|
| 104 |
+
# Start FastAPI backend
|
| 105 |
+
uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000
|
| 106 |
+
|
| 107 |
+
# API will be available at: http://localhost:8000
|
| 108 |
+
# Interactive docs at: http://localhost:8000/docs
|
| 109 |
+
# Database test: http://localhost:8000/api/test-database
|
| 110 |
+
```
|
| 111 |
+
|
| 112 |
+
## 🔑 Configuration
|
| 113 |
+
|
| 114 |
+
### Database API
|
| 115 |
+
- **Endpoint:** `https://aadarshsenapati.in/api/api.php`
|
| 116 |
+
- Managed by team member - handles all database operations
|
| 117 |
+
- Supports: Users, Parking Lots, Bookings, Payments, Feedback
|
| 118 |
+
|
| 119 |
+
### Razorpay Test Credentials
|
| 120 |
+
```env
|
| 121 |
+
RAZORPAY_KEY_ID=rzp_test_RYlqJbc24Sl6jz
|
| 122 |
+
RAZORPAY_KEY_SECRET=bghQe0L7iort9vmqb6Jlf8Ec
|
| 123 |
+
```
|
| 124 |
+
|
| 125 |
+
These are **sandbox/test mode** credentials. Use Razorpay test cards for testing:
|
| 126 |
+
- **Card Number:** 4111 1111 1111 1111
|
| 127 |
+
- **CVV:** Any 3 digits
|
| 128 |
+
- **Expiry:** Any future date
|
| 129 |
+
- **OTP:** 123456 (for test mode)
|
| 130 |
+
|
| 131 |
+
## 🚀 Deployment
|
| 132 |
+
|
| 133 |
+
### Option 1: Render
|
| 134 |
+
```yaml
|
| 135 |
+
# render.yaml is already configured
|
| 136 |
+
# Steps:
|
| 137 |
+
1. Create account on render.com
|
| 138 |
+
2. Connect GitHub repository
|
| 139 |
+
3. Create new Web Service
|
| 140 |
+
4. Render will auto-detect render.yaml
|
| 141 |
+
5. Add environment variables (RAZORPAY keys)
|
| 142 |
+
6. Deploy!
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
### Option 2: Railway
|
| 146 |
+
```bash
|
| 147 |
+
# Install Railway CLI
|
| 148 |
+
npm i -g @railway/cli
|
| 149 |
+
|
| 150 |
+
# Login and deploy
|
| 151 |
+
railway login
|
| 152 |
+
railway init
|
| 153 |
+
railway up
|
| 154 |
+
```
|
| 155 |
+
|
| 156 |
+
### Option 3: Vercel (Serverless)
|
| 157 |
+
```bash
|
| 158 |
+
# Install Vercel CLI
|
| 159 |
+
npm i -g vercel
|
| 160 |
+
|
| 161 |
+
# Deploy
|
| 162 |
+
vercel --prod
|
| 163 |
+
```
|
| 164 |
+
|
| 165 |
+
### Post-Deployment
|
| 166 |
+
- Test all API endpoints
|
| 167 |
+
- Verify payment integration
|
| 168 |
+
- Monitor error logs
|
| 169 |
+
- Set up health checks
|
| 170 |
+
|
| 171 |
+
## 📡 API Endpoints
|
| 172 |
+
|
| 173 |
+
### Database & Health
|
| 174 |
+
```bash
|
| 175 |
+
GET / # Health check
|
| 176 |
+
GET /api/test-database # Test database connection
|
| 177 |
+
```
|
| 178 |
+
|
| 179 |
+
### AI Recommendations
|
| 180 |
+
```bash
|
| 181 |
+
POST /api/recommend-slots
|
| 182 |
+
{
|
| 183 |
+
"user_location": {"latitude": 28.6139, "longitude": 77.2090},
|
| 184 |
+
"slots": [], # Optional - if empty, fetches from database
|
| 185 |
+
"top_k": 3
|
| 186 |
+
}
|
| 187 |
+
```
|
| 188 |
+
|
| 189 |
+
### Booking Management
|
| 190 |
+
```bash
|
| 191 |
+
POST /api/payment/create-order
|
| 192 |
+
{
|
| 193 |
+
"booking_id": "custom_id", # Optional
|
| 194 |
+
"slot_id": "1", # Database slot ID or name
|
| 195 |
+
"amount": 100.0,
|
| 196 |
+
"duration_hours": 2,
|
| 197 |
+
"vehicle_number": "DL01AB1234",
|
| 198 |
+
"customer_name": "John Doe",
|
| 199 |
+
"customer_contact": "+919876543210",
|
| 200 |
+
"customer_email": "john@example.com"
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
GET /api/booking/{booking_uid} # Get booking details
|
| 204 |
+
```
|
| 205 |
+
|
| 206 |
+
### Payment Operations
|
| 207 |
+
```bash
|
| 208 |
+
POST /api/payment/create-link # Create payment link
|
| 209 |
+
POST /api/payment/verify # Verify payment signature
|
| 210 |
+
POST /api/payment/simulate # Simulate payment (testing)
|
| 211 |
+
?booking_uid=ABC12345&amount=100
|
| 212 |
+
```
|
| 213 |
+
|
| 214 |
+
### Feedback System
|
| 215 |
+
```bash
|
| 216 |
+
POST /api/feedback
|
| 217 |
+
{
|
| 218 |
+
"booking_id": "ABC12345", # Booking UID from database
|
| 219 |
+
"slot_id": "A1",
|
| 220 |
+
"rating": 4.5,
|
| 221 |
+
"comment": "Great spot!",
|
| 222 |
+
"user_satisfaction": true
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
GET /api/feedback/stats # Get feedback statistics
|
| 226 |
+
```
|
| 227 |
+
|
| 228 |
+
### AI Model Management
|
| 229 |
+
```bash
|
| 230 |
+
POST /api/retrain-model # Retrain model with feedback data
|
| 231 |
+
```
|
| 232 |
+
|
| 233 |
+
## 🤖 AI Model Details
|
| 234 |
+
|
| 235 |
+
### Features Used
|
| 236 |
+
1. **Proximity Score** (0-1): Distance from user to parking slot
|
| 237 |
+
2. **Average Feedback** (0-1): Normalized user ratings
|
| 238 |
+
3. **Popularity Score** (0-1): Historical booking frequency
|
| 239 |
+
4. **Availability** (0-1): Current availability status
|
| 240 |
+
5. **Price Factor** (0-1): Normalized pricing
|
| 241 |
+
|
| 242 |
+
### Algorithm
|
| 243 |
+
- **Random Forest Classifier** (100 estimators)
|
| 244 |
+
- Trained on user satisfaction data
|
| 245 |
+
- Predicts probability of user satisfaction
|
| 246 |
+
- Falls back to weighted scoring if not trained
|
| 247 |
+
|
| 248 |
+
### Continuous Improvement
|
| 249 |
+
- Collects feedback after each booking
|
| 250 |
+
- Retrains model periodically
|
| 251 |
+
- Updates slot rankings based on new data
|
| 252 |
+
|
| 253 |
+
## 💳 Payment Flow
|
| 254 |
+
|
| 255 |
+
1. User books a slot via WhatsApp
|
| 256 |
+
2. Backend creates Razorpay order
|
| 257 |
+
3. Payment link sent to user
|
| 258 |
+
4. User completes payment
|
| 259 |
+
5. Webhook verifies payment
|
| 260 |
+
6. Booking confirmed
|
| 261 |
+
7. Feedback collected after use
|
| 262 |
+
|
| 263 |
+
## 🧪 Testing
|
| 264 |
+
|
| 265 |
+
### Pre-Production Testing
|
| 266 |
+
|
| 267 |
+
#### 1. Run Test Suite
|
| 268 |
+
```bash
|
| 269 |
+
python test_system.py
|
| 270 |
+
```
|
| 271 |
+
This will test:
|
| 272 |
+
- ✅ AI model training and predictions
|
| 273 |
+
- ✅ Payment service (simulated and real)
|
| 274 |
+
- ✅ Full integration flow
|
| 275 |
+
- ✅ Feedback collection
|
| 276 |
+
- ✅ Model retraining
|
| 277 |
+
|
| 278 |
+
#### 2. API Testing with Interactive Docs
|
| 279 |
+
```bash
|
| 280 |
+
# Start server
|
| 281 |
+
uvicorn backend.main:app --reload --port 8000
|
| 282 |
+
|
| 283 |
+
# Open browser to:
|
| 284 |
+
http://localhost:8000/docs
|
| 285 |
+
```
|
| 286 |
+
|
| 287 |
+
Test each endpoint:
|
| 288 |
+
- `/api/recommend-slots` - AI recommendations
|
| 289 |
+
- `/api/payment/create-order` - Create payment
|
| 290 |
+
- `/api/payment/simulate` - Simulate payment
|
| 291 |
+
- `/api/feedback` - Submit feedback
|
| 292 |
+
- `/api/retrain-model` - Retrain AI model
|
| 293 |
+
|
| 294 |
+
#### 3. Manual Testing Scenarios
|
| 295 |
+
|
| 296 |
+
**Scenario 1: Find Best Parking Spot**
|
| 297 |
+
```bash
|
| 298 |
+
curl -X POST "http://localhost:8000/api/recommend-slots" \
|
| 299 |
+
-H "Content-Type: application/json" \
|
| 300 |
+
-d '{
|
| 301 |
+
"user_location": {"latitude": 28.6139, "longitude": 77.2090},
|
| 302 |
+
"slots": [
|
| 303 |
+
{
|
| 304 |
+
"slot_id": "A1",
|
| 305 |
+
"latitude": 28.6145,
|
| 306 |
+
"longitude": 77.2095,
|
| 307 |
+
"avg_feedback": 4.5,
|
| 308 |
+
"popularity_score": 0.8,
|
| 309 |
+
"is_available": true,
|
| 310 |
+
"price_factor": 0.7,
|
| 311 |
+
"price_per_hour": 50.0
|
| 312 |
+
}
|
| 313 |
+
],
|
| 314 |
+
"top_k": 3
|
| 315 |
+
}'
|
| 316 |
+
```
|
| 317 |
+
|
| 318 |
+
**Scenario 2: Create Payment Order**
|
| 319 |
+
```bash
|
| 320 |
+
curl -X POST "http://localhost:8000/api/payment/create-order" \
|
| 321 |
+
-H "Content-Type: application/json" \
|
| 322 |
+
-d '{
|
| 323 |
+
"booking_id": "BKG001",
|
| 324 |
+
"slot_id": "A1",
|
| 325 |
+
"amount": 100.0,
|
| 326 |
+
"duration_hours": 2,
|
| 327 |
+
"vehicle_number": "DL01AB1234",
|
| 328 |
+
"customer_name": "Test User",
|
| 329 |
+
"customer_contact": "+919876543210",
|
| 330 |
+
"customer_email": "test@example.com"
|
| 331 |
+
}'
|
| 332 |
+
```
|
| 333 |
+
|
| 334 |
+
**Scenario 3: Simulate Payment**
|
| 335 |
+
```bash
|
| 336 |
+
curl -X POST "http://localhost:8000/api/payment/simulate?booking_id=BKG001&amount=100"
|
| 337 |
+
```
|
| 338 |
+
|
| 339 |
+
**Scenario 4: Submit Feedback**
|
| 340 |
+
```bash
|
| 341 |
+
curl -X POST "http://localhost:8000/api/feedback" \
|
| 342 |
+
-H "Content-Type: application/json" \
|
| 343 |
+
-d '{
|
| 344 |
+
"booking_id": "BKG001",
|
| 345 |
+
"slot_id": "A1",
|
| 346 |
+
"rating": 5.0,
|
| 347 |
+
"comment": "Great spot!",
|
| 348 |
+
"user_satisfaction": true
|
| 349 |
+
}'
|
| 350 |
+
```
|
| 351 |
+
|
| 352 |
+
### Post-Production Testing
|
| 353 |
+
|
| 354 |
+
#### 1. Health Check
|
| 355 |
+
```bash
|
| 356 |
+
curl http://your-deployed-url.com/
|
| 357 |
+
```
|
| 358 |
+
|
| 359 |
+
#### 2. Load Testing
|
| 360 |
+
```bash
|
| 361 |
+
# Install hey (load testing tool)
|
| 362 |
+
# Run load test
|
| 363 |
+
hey -n 1000 -c 10 http://your-deployed-url.com/api/recommend-slots
|
| 364 |
+
```
|
| 365 |
+
|
| 366 |
+
#### 3. Monitor Performance
|
| 367 |
+
- Response times < 500ms
|
| 368 |
+
- Error rate < 1%
|
| 369 |
+
- Model accuracy > 80%
|
| 370 |
+
- Payment success rate > 98%
|
| 371 |
+
|
| 372 |
+
#### 4. Test Payment Integration
|
| 373 |
+
- Test with Razorpay test cards
|
| 374 |
+
- Verify payment webhooks
|
| 375 |
+
- Check payment verification
|
| 376 |
+
- Test refund functionality
|
| 377 |
+
|
| 378 |
+
## 📊 Next Steps
|
| 379 |
+
|
| 380 |
+
### Phase 1: Core Implementation ✅
|
| 381 |
+
- [x] AI classification model with feedback learning
|
| 382 |
+
- [x] Razorpay payment integration (sandbox)
|
| 383 |
+
- [x] FastAPI backend with all endpoints
|
| 384 |
+
- [x] Comprehensive testing suite
|
| 385 |
+
- [x] Deployment configurations
|
| 386 |
+
|
| 387 |
+
### Phase 2: Testing & Validation (Current)
|
| 388 |
+
- [ ] Run local test suite (`python test_system.py`)
|
| 389 |
+
- [ ] Test all API endpoints with Postman/curl
|
| 390 |
+
- [ ] Verify payment flows with test credentials
|
| 391 |
+
- [ ] Load testing and performance optimization
|
| 392 |
+
- [ ] Security testing and validation
|
| 393 |
+
|
| 394 |
+
### Phase 3: Production Deployment
|
| 395 |
+
- [ ] Deploy backend to Render/Railway
|
| 396 |
+
- [ ] Configure production environment variables
|
| 397 |
+
- [ ] Set up monitoring and logging
|
| 398 |
+
- [ ] Configure auto-scaling
|
| 399 |
+
- [ ] Set up backup and disaster recovery
|
| 400 |
+
|
| 401 |
+
### Phase 4: Integration & Enhancement
|
| 402 |
+
- [ ] Connect to real parking database
|
| 403 |
+
- [ ] Integrate with external systems (to be handled by other teams)
|
| 404 |
+
- [ ] Add real-time slot updates
|
| 405 |
+
- [ ] Implement caching for performance
|
| 406 |
+
- [ ] Add analytics dashboard
|
| 407 |
+
|
| 408 |
+
### Phase 5: Continuous Improvement
|
| 409 |
+
- [ ] Collect production feedback data
|
| 410 |
+
- [ ] Retrain AI model with real data
|
| 411 |
+
- [ ] A/B test different recommendation algorithms
|
| 412 |
+
- [ ] Optimize model performance
|
| 413 |
+
- [ ] Add advanced features based on usage patterns
|
| 414 |
+
|
| 415 |
+
## 🤝 Integration Points
|
| 416 |
+
|
| 417 |
+
This module provides REST APIs that can be integrated with:
|
| 418 |
+
- **Frontend applications** (Web/Mobile)
|
| 419 |
+
- **WhatsApp/Telegram bots** (handled by other teams)
|
| 420 |
+
- **Admin dashboards**
|
| 421 |
+
- **IoT parking sensors**
|
| 422 |
+
- **Third-party booking systems**
|
| 423 |
+
|
| 424 |
+
## 📄 License
|
| 425 |
+
|
| 426 |
+
MIT License
|
| 427 |
+
|
| 428 |
+
## 📧 Support
|
| 429 |
+
|
| 430 |
+
For issues and questions, please create an issue in the repository.
|
| 431 |
+
|
| 432 |
+
---
|
| 433 |
+
|
| 434 |
+
**AI + Payment Module** | Smart Parking System v1.0
|
check_slots.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Quick script to check what's in the database
|
| 3 |
+
"""
|
| 4 |
+
from backend.database_api import DatabaseAPI
|
| 5 |
+
import json
|
| 6 |
+
|
| 7 |
+
api = DatabaseAPI()
|
| 8 |
+
|
| 9 |
+
print("=" * 60)
|
| 10 |
+
print("CHECKING DATABASE CONTENT")
|
| 11 |
+
print("=" * 60)
|
| 12 |
+
|
| 13 |
+
# Check parking lots
|
| 14 |
+
print("\n1️⃣ PARKING LOTS:")
|
| 15 |
+
lots_result = api.get_parking_lots()
|
| 16 |
+
print(f"Status: {lots_result['status']}")
|
| 17 |
+
if lots_result.get('data'):
|
| 18 |
+
for lot in lots_result['data']:
|
| 19 |
+
print(f"\n📍 Lot {lot.get('lot_id')}: {lot.get('lot_name')}")
|
| 20 |
+
print(f" Location: {lot.get('address')}")
|
| 21 |
+
print(f" Coordinates: ({lot.get('latitude')}, {lot.get('longitude')})")
|
| 22 |
+
print(f" Total Slots: {lot.get('total_slots')}")
|
| 23 |
+
print(f" Raw data: {json.dumps(lot, indent=2)}")
|
| 24 |
+
else:
|
| 25 |
+
print("No parking lots found")
|
| 26 |
+
|
| 27 |
+
# Check available slots for lot 1
|
| 28 |
+
print("\n" + "=" * 60)
|
| 29 |
+
print("2️⃣ AVAILABLE SLOTS FOR LOT 1:")
|
| 30 |
+
slots_result = api.get_available_slots(1)
|
| 31 |
+
print(f"Status: {slots_result['status']}")
|
| 32 |
+
print(f"Message: {slots_result.get('message', 'N/A')}")
|
| 33 |
+
if slots_result.get('data'):
|
| 34 |
+
print(f"Found {len(slots_result['data'])} slots:")
|
| 35 |
+
for slot in slots_result['data']:
|
| 36 |
+
print(f"\n🅿️ Slot {slot.get('id')}: {slot.get('slot_number')}")
|
| 37 |
+
print(f" Parking Lot ID: {slot.get('parking_lot_id')}")
|
| 38 |
+
print(f" Vehicle Type: {slot.get('vehicle_type')}")
|
| 39 |
+
print(f" Available: {slot.get('is_available')}")
|
| 40 |
+
print(f" Active: {slot.get('is_active')}")
|
| 41 |
+
print(f" Hourly Rate: ₹{slot.get('hourly_rate')}")
|
| 42 |
+
print(f" Raw data: {json.dumps(slot, indent=2)}")
|
| 43 |
+
else:
|
| 44 |
+
print("No available slots found")
|
| 45 |
+
print(f"Full response: {json.dumps(slots_result, indent=2)}")
|
| 46 |
+
|
| 47 |
+
# Check all available slots
|
| 48 |
+
print("\n" + "=" * 60)
|
| 49 |
+
print("3️⃣ ALL AVAILABLE SLOTS:")
|
| 50 |
+
all_slots = api.get_all_available_slots()
|
| 51 |
+
print(f"Status: {all_slots['status']}")
|
| 52 |
+
print(f"Total Lots: {all_slots.get('total_lots', 0)}")
|
| 53 |
+
print(f"Total Slots: {all_slots.get('total_slots', 0)}")
|
| 54 |
+
if all_slots.get('data'):
|
| 55 |
+
for slot in all_slots['data'][:3]: # Show first 3
|
| 56 |
+
print(f"\n🅿️ Slot: {slot.get('slot_number')} ({slot.get('lot_name')})")
|
| 57 |
+
print(f" Vehicle: {slot.get('vehicle_type')}, Rate: ₹{slot.get('hourly_rate')}/hr")
|
| 58 |
+
|
| 59 |
+
print("\n" + "=" * 60)
|
demo_ai_model.py
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Interactive AI Model Demo - Test the Recommendation System
|
| 3 |
+
"""
|
| 4 |
+
from backend.database_api import DatabaseAPI, transform_parking_lots_for_ai
|
| 5 |
+
from ai_model.parking_slot_classifier import ParkingSlotClassifier
|
| 6 |
+
import json
|
| 7 |
+
|
| 8 |
+
print("=" * 70)
|
| 9 |
+
print("🤖 SMART PARKING AI MODEL - INTERACTIVE DEMO")
|
| 10 |
+
print("=" * 70)
|
| 11 |
+
|
| 12 |
+
# Initialize
|
| 13 |
+
api = DatabaseAPI()
|
| 14 |
+
classifier = ParkingSlotClassifier()
|
| 15 |
+
|
| 16 |
+
# Load or train model
|
| 17 |
+
try:
|
| 18 |
+
classifier.load_model('parking_model.pkl')
|
| 19 |
+
print("\n✅ AI Model loaded successfully")
|
| 20 |
+
except:
|
| 21 |
+
print("\n🔄 Training new AI model...")
|
| 22 |
+
from ai_model.parking_slot_classifier import generate_training_data
|
| 23 |
+
training_data, labels = generate_training_data(500)
|
| 24 |
+
classifier.train(training_data, labels)
|
| 25 |
+
classifier.save_model('parking_model.pkl')
|
| 26 |
+
print("✅ Model trained and saved")
|
| 27 |
+
|
| 28 |
+
print("\n" + "=" * 70)
|
| 29 |
+
print("📍 STEP 1: GET USER LOCATION")
|
| 30 |
+
print("=" * 70)
|
| 31 |
+
|
| 32 |
+
# Example user location (SRM University AP)
|
| 33 |
+
user_lat = 16.4645
|
| 34 |
+
user_lon = 80.5076
|
| 35 |
+
|
| 36 |
+
print(f"User Location: ({user_lat}, {user_lon})")
|
| 37 |
+
print(f"Location: Near SRM University AP, Guntur")
|
| 38 |
+
|
| 39 |
+
print("\n" + "=" * 70)
|
| 40 |
+
print("🅿️ STEP 2: FETCH AVAILABLE PARKING SLOTS FROM DATABASE")
|
| 41 |
+
print("=" * 70)
|
| 42 |
+
|
| 43 |
+
# Get slots from database
|
| 44 |
+
slots_result = api.get_all_available_slots()
|
| 45 |
+
|
| 46 |
+
if slots_result['status'] == 'success':
|
| 47 |
+
raw_slots = slots_result.get('data', [])
|
| 48 |
+
print(f"✅ Found {len(raw_slots)} available slot(s) in database")
|
| 49 |
+
|
| 50 |
+
# Show raw data
|
| 51 |
+
print(f"\n📊 Raw Database Data:")
|
| 52 |
+
for slot in raw_slots:
|
| 53 |
+
print(f" - Slot {slot.get('slot_number')} at {slot.get('lot_name')}")
|
| 54 |
+
print(f" Type: {slot.get('vehicle_type')}, Rate: ₹{slot.get('hourly_rate')}/hr")
|
| 55 |
+
|
| 56 |
+
print("\n" + "=" * 70)
|
| 57 |
+
print("🔄 STEP 3: TRANSFORM DATA FOR AI MODEL")
|
| 58 |
+
print("=" * 70)
|
| 59 |
+
|
| 60 |
+
# Transform to AI format
|
| 61 |
+
ai_slots = transform_parking_lots_for_ai(raw_slots)
|
| 62 |
+
|
| 63 |
+
print(f"✅ Transformed {len(ai_slots)} slots for AI processing")
|
| 64 |
+
print(f"\n📊 AI Model Input Features:")
|
| 65 |
+
|
| 66 |
+
if ai_slots:
|
| 67 |
+
sample = ai_slots[0]
|
| 68 |
+
print(f" Slot ID: {sample['slot_id']}")
|
| 69 |
+
print(f" Location: ({sample['latitude']}, {sample['longitude']})")
|
| 70 |
+
print(f" Features:")
|
| 71 |
+
print(f" - avg_feedback: {sample['avg_feedback']} (0-5 scale)")
|
| 72 |
+
print(f" - popularity_score: {sample['popularity_score']} (0-1)")
|
| 73 |
+
print(f" - is_available: {sample['is_available']}")
|
| 74 |
+
print(f" - price_factor: {sample['price_factor']} (0-1)")
|
| 75 |
+
print(f" - price_per_hour: ₹{sample['price_per_hour']}")
|
| 76 |
+
print(f" - proximity_score: Will be calculated based on user location")
|
| 77 |
+
|
| 78 |
+
print("\n" + "=" * 70)
|
| 79 |
+
print("🧠 STEP 4: AI MODEL PREDICTION")
|
| 80 |
+
print("=" * 70)
|
| 81 |
+
|
| 82 |
+
# Get AI recommendations
|
| 83 |
+
user_coords = (user_lat, user_lon)
|
| 84 |
+
recommendations = classifier.predict_best_slots(
|
| 85 |
+
ai_slots,
|
| 86 |
+
user_coords,
|
| 87 |
+
top_k=3
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
print(f"✅ AI Model processed {len(ai_slots)} slot(s)")
|
| 91 |
+
print(f"📍 Calculated proximity from user location")
|
| 92 |
+
print(f"🎯 Generated {len(recommendations)} recommendation(s)")
|
| 93 |
+
|
| 94 |
+
print("\n" + "=" * 70)
|
| 95 |
+
print("🏆 STEP 5: TOP RECOMMENDATIONS")
|
| 96 |
+
print("=" * 70)
|
| 97 |
+
|
| 98 |
+
for i, slot in enumerate(recommendations, 1):
|
| 99 |
+
print(f"\n#{i} Recommended Slot: {slot['slot_id']}")
|
| 100 |
+
print(f" 📍 Location: {slot.get('location', 'N/A')}")
|
| 101 |
+
print(f" 🚗 Vehicle Type: {slot.get('vehicle_type', 'N/A')}")
|
| 102 |
+
print(f" 💰 Price: ₹{slot['price_per_hour']}/hour")
|
| 103 |
+
print(f" 📊 AI Scores:")
|
| 104 |
+
print(f" - Recommendation Score: {slot['recommendation_score']:.3f} (FINAL)")
|
| 105 |
+
print(f" - Proximity Score: {slot['proximity_score']:.3f}")
|
| 106 |
+
print(f" - Feedback Score: {slot['avg_feedback']:.1f}/5.0")
|
| 107 |
+
print(f" - Popularity: {slot['popularity_score']:.2f}")
|
| 108 |
+
print(f" - Available: {'✅ Yes' if slot['is_available'] else '❌ No'}")
|
| 109 |
+
|
| 110 |
+
# Calculate distance
|
| 111 |
+
from ai_model.parking_slot_classifier import ParkingSlotClassifier
|
| 112 |
+
temp_classifier = ParkingSlotClassifier()
|
| 113 |
+
slot_coords = (slot['latitude'], slot['longitude'])
|
| 114 |
+
proximity = temp_classifier.calculate_proximity_score(slot_coords, user_coords)
|
| 115 |
+
|
| 116 |
+
# Estimate distance
|
| 117 |
+
distance_km = (1 - proximity) * 5
|
| 118 |
+
if distance_km < 0.1:
|
| 119 |
+
distance_str = f"{distance_km * 1000:.0f} meters"
|
| 120 |
+
else:
|
| 121 |
+
distance_str = f"{distance_km:.2f} km"
|
| 122 |
+
|
| 123 |
+
print(f" - Estimated Distance: {distance_str}")
|
| 124 |
+
|
| 125 |
+
print("\n" + "=" * 70)
|
| 126 |
+
print("📊 HOW THE AI DECIDED")
|
| 127 |
+
print("=" * 70)
|
| 128 |
+
|
| 129 |
+
print(f"""
|
| 130 |
+
The AI considered these factors for each slot:
|
| 131 |
+
|
| 132 |
+
1. PROXIMITY (40% weight)
|
| 133 |
+
- Calculated distance from your location using GPS
|
| 134 |
+
- Closer slots get higher scores
|
| 135 |
+
|
| 136 |
+
2. USER FEEDBACK (30% weight)
|
| 137 |
+
- Average ratings from previous users
|
| 138 |
+
- Based on actual user experiences
|
| 139 |
+
|
| 140 |
+
3. POPULARITY (20% weight)
|
| 141 |
+
- How often this slot is booked
|
| 142 |
+
- Popular slots are often better maintained
|
| 143 |
+
|
| 144 |
+
4. AVAILABILITY (10% weight)
|
| 145 |
+
- Currently available = higher priority
|
| 146 |
+
- Unavailable slots get lower scores
|
| 147 |
+
|
| 148 |
+
5. PRICE (indirect factor)
|
| 149 |
+
- Considered in the overall calculation
|
| 150 |
+
- Balanced with other factors
|
| 151 |
+
""")
|
| 152 |
+
|
| 153 |
+
print("\n" + "=" * 70)
|
| 154 |
+
print("🔄 MODEL LEARNING")
|
| 155 |
+
print("=" * 70)
|
| 156 |
+
|
| 157 |
+
print(f"""
|
| 158 |
+
The AI model improves over time:
|
| 159 |
+
|
| 160 |
+
1. User receives recommendations ✅
|
| 161 |
+
2. User books a slot ✅
|
| 162 |
+
3. User provides feedback (rating + satisfaction) 📝
|
| 163 |
+
4. System stores the feedback
|
| 164 |
+
5. After 10+ feedbacks → Model retrains 🔄
|
| 165 |
+
6. Model learns patterns of good recommendations 🧠
|
| 166 |
+
|
| 167 |
+
Current training: {500} synthetic samples
|
| 168 |
+
Real feedback needed: 10+ samples for retraining
|
| 169 |
+
""")
|
| 170 |
+
|
| 171 |
+
else:
|
| 172 |
+
print(f"❌ Failed to fetch slots: {slots_result.get('message')}")
|
| 173 |
+
|
| 174 |
+
print("\n" + "=" * 70)
|
| 175 |
+
print("✅ DEMO COMPLETE")
|
| 176 |
+
print("=" * 70)
|
| 177 |
+
print(f"""
|
| 178 |
+
To use the AI model in your application:
|
| 179 |
+
|
| 180 |
+
1. GET user's GPS location
|
| 181 |
+
2. POST to /api/recommend-slots with:
|
| 182 |
+
{{
|
| 183 |
+
"user_location": {{"latitude": {user_lat}, "longitude": {user_lon}}},
|
| 184 |
+
"slots": [],
|
| 185 |
+
"top_k": 3
|
| 186 |
+
}}
|
| 187 |
+
|
| 188 |
+
3. Receive top 3 recommended slots
|
| 189 |
+
4. Display to user
|
| 190 |
+
5. Collect feedback after booking
|
| 191 |
+
6. Use feedback to improve model
|
| 192 |
+
|
| 193 |
+
For more details, see: AI_MODEL_GUIDE.md
|
| 194 |
+
""")
|
diagnose_api.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Diagnose the API issue by making direct requests
|
| 3 |
+
"""
|
| 4 |
+
import requests
|
| 5 |
+
import json
|
| 6 |
+
|
| 7 |
+
base_url = "https://aadarshsenapati.in/api/api.php"
|
| 8 |
+
|
| 9 |
+
print("=" * 60)
|
| 10 |
+
print("DIAGNOSING API ENDPOINT")
|
| 11 |
+
print("=" * 60)
|
| 12 |
+
|
| 13 |
+
# Test get_available_slots endpoint
|
| 14 |
+
print("\n📡 Testing get_available_slots endpoint:")
|
| 15 |
+
print(f"URL: {base_url}?action=get_available_slots")
|
| 16 |
+
|
| 17 |
+
try:
|
| 18 |
+
# Try POST request with parking_lot_id
|
| 19 |
+
response = requests.post(
|
| 20 |
+
f"{base_url}?action=get_available_slots",
|
| 21 |
+
json={"parking_lot_id": 1},
|
| 22 |
+
headers={'Content-Type': 'application/json'},
|
| 23 |
+
timeout=10
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
print(f"\nStatus Code: {response.status_code}")
|
| 27 |
+
print(f"Response Headers: {dict(response.headers)}")
|
| 28 |
+
print(f"\nResponse Body:")
|
| 29 |
+
print(response.text[:1000]) # First 1000 chars
|
| 30 |
+
|
| 31 |
+
if response.status_code == 200:
|
| 32 |
+
try:
|
| 33 |
+
data = response.json()
|
| 34 |
+
print(f"\nParsed JSON:")
|
| 35 |
+
print(json.dumps(data, indent=2))
|
| 36 |
+
except:
|
| 37 |
+
print("\nCouldn't parse as JSON")
|
| 38 |
+
|
| 39 |
+
except Exception as e:
|
| 40 |
+
print(f"❌ Error: {e}")
|
| 41 |
+
|
| 42 |
+
# Also try with different parking_lot_id formats
|
| 43 |
+
print("\n" + "=" * 60)
|
| 44 |
+
print("Testing with different parameter formats:")
|
| 45 |
+
|
| 46 |
+
formats = [
|
| 47 |
+
{"parking_lot_id": 1},
|
| 48 |
+
{"parking_lot_id": "1"},
|
| 49 |
+
{"lot_id": 1},
|
| 50 |
+
]
|
| 51 |
+
|
| 52 |
+
for fmt in formats:
|
| 53 |
+
print(f"\n📤 Trying: {fmt}")
|
| 54 |
+
try:
|
| 55 |
+
response = requests.post(
|
| 56 |
+
f"{base_url}?action=get_available_slots",
|
| 57 |
+
json=fmt,
|
| 58 |
+
timeout=5
|
| 59 |
+
)
|
| 60 |
+
print(f" Status: {response.status_code}")
|
| 61 |
+
if response.status_code == 200:
|
| 62 |
+
print(f" Result: {response.json().get('status')}")
|
| 63 |
+
except Exception as e:
|
| 64 |
+
print(f" Error: {e}")
|
| 65 |
+
|
| 66 |
+
print("\n" + "=" * 60)
|
diagnose_booking.py
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Diagnose booking endpoint issue
|
| 3 |
+
"""
|
| 4 |
+
import requests
|
| 5 |
+
import json
|
| 6 |
+
from datetime import datetime, timedelta
|
| 7 |
+
|
| 8 |
+
base_url = "https://aadarshsenapati.in/api/api.php"
|
| 9 |
+
|
| 10 |
+
print("=" * 70)
|
| 11 |
+
print("DIAGNOSING book_slot ENDPOINT")
|
| 12 |
+
print("=" * 70)
|
| 13 |
+
|
| 14 |
+
# Prepare booking data
|
| 15 |
+
start_time = datetime.now()
|
| 16 |
+
end_time = start_time + timedelta(hours=2)
|
| 17 |
+
|
| 18 |
+
booking_data = {
|
| 19 |
+
"user_id": 1,
|
| 20 |
+
"slot_id": 1,
|
| 21 |
+
"start_time": start_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 22 |
+
"end_time": end_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 23 |
+
"total_amount": 100.0
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
print("\n📤 Sending booking request...")
|
| 27 |
+
print(f"URL: {base_url}?action=book_slot")
|
| 28 |
+
print(f"\nPayload:")
|
| 29 |
+
print(json.dumps(booking_data, indent=2))
|
| 30 |
+
|
| 31 |
+
try:
|
| 32 |
+
response = requests.post(
|
| 33 |
+
f"{base_url}?action=book_slot",
|
| 34 |
+
json=booking_data,
|
| 35 |
+
headers={'Content-Type': 'application/json'},
|
| 36 |
+
timeout=10
|
| 37 |
+
)
|
| 38 |
+
|
| 39 |
+
print(f"\n📥 Response Status Code: {response.status_code}")
|
| 40 |
+
print(f"\nResponse Headers:")
|
| 41 |
+
for key, value in response.headers.items():
|
| 42 |
+
print(f" {key}: {value}")
|
| 43 |
+
|
| 44 |
+
print(f"\n📄 Response Body:")
|
| 45 |
+
print(response.text[:2000]) # First 2000 chars
|
| 46 |
+
|
| 47 |
+
if response.status_code == 200:
|
| 48 |
+
try:
|
| 49 |
+
data = response.json()
|
| 50 |
+
print(f"\n✅ Parsed JSON:")
|
| 51 |
+
print(json.dumps(data, indent=2))
|
| 52 |
+
except:
|
| 53 |
+
print("\n⚠️ Response is not valid JSON")
|
| 54 |
+
else:
|
| 55 |
+
print(f"\n❌ HTTP Error: {response.status_code}")
|
| 56 |
+
|
| 57 |
+
# Try to see if there's any HTML error
|
| 58 |
+
if "html" in response.text.lower():
|
| 59 |
+
print("\n⚠️ Response appears to be HTML (likely a PHP error page)")
|
| 60 |
+
# Extract title if present
|
| 61 |
+
if "<title>" in response.text:
|
| 62 |
+
start = response.text.find("<title>") + 7
|
| 63 |
+
end = response.text.find("</title>")
|
| 64 |
+
print(f"Error Title: {response.text[start:end]}")
|
| 65 |
+
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"\n❌ Request failed: {e}")
|
| 68 |
+
|
| 69 |
+
# Try with different data formats
|
| 70 |
+
print("\n" + "=" * 70)
|
| 71 |
+
print("TRYING DIFFERENT DATA FORMATS")
|
| 72 |
+
print("=" * 70)
|
| 73 |
+
|
| 74 |
+
# Try 1: String slot_id
|
| 75 |
+
test_data_1 = {**booking_data, "slot_id": "1"}
|
| 76 |
+
print("\n1️⃣ Trying with string slot_id...")
|
| 77 |
+
try:
|
| 78 |
+
response = requests.post(
|
| 79 |
+
f"{base_url}?action=book_slot",
|
| 80 |
+
json=test_data_1,
|
| 81 |
+
timeout=5
|
| 82 |
+
)
|
| 83 |
+
print(f" Status: {response.status_code}")
|
| 84 |
+
if response.status_code == 200:
|
| 85 |
+
print(f" Result: {response.json().get('status')}")
|
| 86 |
+
except Exception as e:
|
| 87 |
+
print(f" Error: {e}")
|
| 88 |
+
|
| 89 |
+
# Try 2: Without total_amount
|
| 90 |
+
test_data_2 = {k: v for k, v in booking_data.items() if k != 'total_amount'}
|
| 91 |
+
print("\n2️⃣ Trying without total_amount...")
|
| 92 |
+
try:
|
| 93 |
+
response = requests.post(
|
| 94 |
+
f"{base_url}?action=book_slot",
|
| 95 |
+
json=test_data_2,
|
| 96 |
+
timeout=5
|
| 97 |
+
)
|
| 98 |
+
print(f" Status: {response.status_code}")
|
| 99 |
+
if response.status_code == 200:
|
| 100 |
+
print(f" Result: {response.json().get('status')}")
|
| 101 |
+
except Exception as e:
|
| 102 |
+
print(f" Error: {e}")
|
| 103 |
+
|
| 104 |
+
# Try 3: Minimal data
|
| 105 |
+
test_data_3 = {
|
| 106 |
+
"user_id": 1,
|
| 107 |
+
"slot_id": 1
|
| 108 |
+
}
|
| 109 |
+
print("\n3️⃣ Trying with minimal data (user_id, slot_id only)...")
|
| 110 |
+
try:
|
| 111 |
+
response = requests.post(
|
| 112 |
+
f"{base_url}?action=book_slot",
|
| 113 |
+
json=test_data_3,
|
| 114 |
+
timeout=5
|
| 115 |
+
)
|
| 116 |
+
print(f" Status: {response.status_code}")
|
| 117 |
+
if response.status_code == 200:
|
| 118 |
+
print(f" Result: {response.json().get('status')}")
|
| 119 |
+
else:
|
| 120 |
+
print(f" Response: {response.text[:200]}")
|
| 121 |
+
except Exception as e:
|
| 122 |
+
print(f" Error: {e}")
|
| 123 |
+
|
| 124 |
+
print("\n" + "=" * 70)
|
| 125 |
+
print("💡 COMMON CAUSES OF 500 ERROR:")
|
| 126 |
+
print("=" * 70)
|
| 127 |
+
print("""
|
| 128 |
+
1. Table name mismatch (e.g., 'bookings' vs 'booking')
|
| 129 |
+
2. Column name mismatch (e.g., 'slot_id' vs 'parking_slot_id')
|
| 130 |
+
3. Missing table or columns in database
|
| 131 |
+
4. SQL syntax error in PHP code
|
| 132 |
+
5. Missing required fields
|
| 133 |
+
6. Data type mismatch (e.g., expecting INT but getting STRING)
|
| 134 |
+
7. Foreign key constraint violation
|
| 135 |
+
8. PHP syntax error or uncaught exception
|
| 136 |
+
|
| 137 |
+
📋 Check your PHP error logs for the actual error message!
|
| 138 |
+
""")
|
diagnose_payment_update.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Diagnose Payment Update Issue
|
| 3 |
+
"""
|
| 4 |
+
import requests
|
| 5 |
+
import json
|
| 6 |
+
from datetime import datetime, timedelta
|
| 7 |
+
from backend.database_api import DatabaseAPI
|
| 8 |
+
|
| 9 |
+
api = DatabaseAPI()
|
| 10 |
+
base_url = "https://aadarshsenapati.in/api/api.php"
|
| 11 |
+
|
| 12 |
+
print("=" * 70)
|
| 13 |
+
print("DIAGNOSING PAYMENT UPDATE ISSUE")
|
| 14 |
+
print("=" * 70)
|
| 15 |
+
|
| 16 |
+
# Step 1: Create a test booking first
|
| 17 |
+
print("\n1️⃣ Creating a test booking...")
|
| 18 |
+
start_time = datetime.now()
|
| 19 |
+
end_time = start_time + timedelta(hours=2)
|
| 20 |
+
|
| 21 |
+
booking_result = api.book_slot(
|
| 22 |
+
user_id=9,
|
| 23 |
+
slot_id=1,
|
| 24 |
+
start_time=start_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 25 |
+
end_time=end_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 26 |
+
total_amount=120.0
|
| 27 |
+
)
|
| 28 |
+
|
| 29 |
+
if booking_result['status'] == 'success':
|
| 30 |
+
booking_uid = booking_result['booking_uid']
|
| 31 |
+
print(f"✅ Booking created: {booking_uid}")
|
| 32 |
+
|
| 33 |
+
# Step 2: Check initial status
|
| 34 |
+
print(f"\n2️⃣ Checking initial booking status...")
|
| 35 |
+
status_result = api.get_booking_status(booking_uid)
|
| 36 |
+
if status_result['status'] == 'success':
|
| 37 |
+
booking_data = status_result['data']
|
| 38 |
+
print(f"Initial payment_status: '{booking_data.get('payment_status')}'")
|
| 39 |
+
print(f"Full booking data:")
|
| 40 |
+
print(json.dumps(booking_data, indent=2))
|
| 41 |
+
|
| 42 |
+
# Step 3: Update payment status
|
| 43 |
+
print(f"\n3️⃣ Updating payment status to 'Paid'...")
|
| 44 |
+
|
| 45 |
+
# Direct API call to see exact request/response
|
| 46 |
+
payment_data = {
|
| 47 |
+
"booking_uid": booking_uid,
|
| 48 |
+
"payment_status": "Paid",
|
| 49 |
+
"transaction_id": f"txn_test_{booking_uid}",
|
| 50 |
+
"amount": 120.0
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
print(f"\nPayload being sent:")
|
| 54 |
+
print(json.dumps(payment_data, indent=2))
|
| 55 |
+
|
| 56 |
+
response = requests.post(
|
| 57 |
+
f"{base_url}?action=update_payment_status",
|
| 58 |
+
json=payment_data,
|
| 59 |
+
headers={'Content-Type': 'application/json'},
|
| 60 |
+
timeout=10
|
| 61 |
+
)
|
| 62 |
+
|
| 63 |
+
print(f"\nResponse Status: {response.status_code}")
|
| 64 |
+
print(f"Response Body:")
|
| 65 |
+
print(response.text)
|
| 66 |
+
|
| 67 |
+
if response.status_code == 200:
|
| 68 |
+
try:
|
| 69 |
+
result = response.json()
|
| 70 |
+
print(f"\nParsed Response:")
|
| 71 |
+
print(json.dumps(result, indent=2))
|
| 72 |
+
except:
|
| 73 |
+
print("Could not parse JSON")
|
| 74 |
+
|
| 75 |
+
# Step 4: Check updated status
|
| 76 |
+
print(f"\n4️⃣ Checking booking status after update...")
|
| 77 |
+
status_result = api.get_booking_status(booking_uid)
|
| 78 |
+
if status_result['status'] == 'success':
|
| 79 |
+
booking_data = status_result['data']
|
| 80 |
+
payment_status = booking_data.get('payment_status')
|
| 81 |
+
print(f"After update payment_status: '{payment_status}'")
|
| 82 |
+
print(f"Full booking data:")
|
| 83 |
+
print(json.dumps(booking_data, indent=2))
|
| 84 |
+
|
| 85 |
+
# Analysis
|
| 86 |
+
print(f"\n5️⃣ ANALYSIS:")
|
| 87 |
+
if payment_status == 'Paid':
|
| 88 |
+
print("✅ Payment status updated correctly!")
|
| 89 |
+
elif payment_status == 'Completed':
|
| 90 |
+
print("⚠️ Payment status is 'Completed' (should be 'Paid')")
|
| 91 |
+
print(" Valid statuses: Pending, Paid, Failed, Refunded")
|
| 92 |
+
elif payment_status == '':
|
| 93 |
+
print("❌ Payment status is EMPTY (removed)")
|
| 94 |
+
print(" This suggests the UPDATE query is setting it to empty string")
|
| 95 |
+
elif payment_status is None:
|
| 96 |
+
print("❌ Payment status is NULL")
|
| 97 |
+
print(" This suggests the UPDATE query is setting it to NULL")
|
| 98 |
+
elif payment_status == 'Pending':
|
| 99 |
+
print("❌ Payment status is still 'Pending'")
|
| 100 |
+
print(" This suggests the UPDATE query didn't execute")
|
| 101 |
+
else:
|
| 102 |
+
print(f"⚠️ Payment status is: '{payment_status}'")
|
| 103 |
+
print(" Unexpected value")
|
| 104 |
+
|
| 105 |
+
else:
|
| 106 |
+
print(f"❌ Failed to create booking: {booking_result.get('message')}")
|
| 107 |
+
|
| 108 |
+
print("\n" + "=" * 70)
|
| 109 |
+
print("💡 COMMON CAUSES:")
|
| 110 |
+
print("=" * 70)
|
| 111 |
+
print("""
|
| 112 |
+
1. UPDATE query is setting payment_status to empty string instead of value
|
| 113 |
+
2. Column name mismatch (e.g., 'paymentStatus' vs 'payment_status')
|
| 114 |
+
3. Missing WHERE clause causing wrong row to update
|
| 115 |
+
4. Database user lacks UPDATE permission
|
| 116 |
+
5. SQL syntax error silently failing
|
| 117 |
+
|
| 118 |
+
🔍 Check your PHP update_payment code!
|
| 119 |
+
""")
|
final_system_test.py
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Final System Test - Verify Everything Works
|
| 3 |
+
"""
|
| 4 |
+
from backend.database_api import DatabaseAPI, transform_parking_lots_for_ai
|
| 5 |
+
from datetime import datetime, timedelta
|
| 6 |
+
import json
|
| 7 |
+
|
| 8 |
+
def print_header(title):
|
| 9 |
+
print("\n" + "="*70)
|
| 10 |
+
print(f"🧪 {title}")
|
| 11 |
+
print("="*70)
|
| 12 |
+
|
| 13 |
+
def main():
|
| 14 |
+
print("""
|
| 15 |
+
╔══════════════════════════════════════════════════════════════════╗
|
| 16 |
+
║ SMART PARKING SYSTEM ║
|
| 17 |
+
║ FINAL SYSTEM TEST ║
|
| 18 |
+
╚══════════════════════════════════════════════════════════════════╝
|
| 19 |
+
""")
|
| 20 |
+
|
| 21 |
+
api = DatabaseAPI()
|
| 22 |
+
results = {}
|
| 23 |
+
|
| 24 |
+
# Test 1: Get Available Slots
|
| 25 |
+
print_header("TEST 1: Get Available Parking Slots")
|
| 26 |
+
try:
|
| 27 |
+
result = api.get_all_available_slots()
|
| 28 |
+
if result['status'] == 'success' and result.get('data'):
|
| 29 |
+
slots = result['data']
|
| 30 |
+
print(f"✅ PASSED - Found {len(slots)} available slot(s)")
|
| 31 |
+
print(f" Sample: {slots[0].get('lot_name')}-{slots[0].get('slot_number')}")
|
| 32 |
+
results['Get Slots'] = True
|
| 33 |
+
else:
|
| 34 |
+
print(f"❌ FAILED - No slots found")
|
| 35 |
+
results['Get Slots'] = False
|
| 36 |
+
except Exception as e:
|
| 37 |
+
print(f"❌ FAILED - {e}")
|
| 38 |
+
results['Get Slots'] = False
|
| 39 |
+
|
| 40 |
+
# Test 2: AI Data Transformation
|
| 41 |
+
print_header("TEST 2: AI Data Transformation")
|
| 42 |
+
try:
|
| 43 |
+
slots_result = api.get_all_available_slots()
|
| 44 |
+
if slots_result['status'] == 'success':
|
| 45 |
+
transformed = transform_parking_lots_for_ai(slots_result['data'])
|
| 46 |
+
if transformed:
|
| 47 |
+
print(f"✅ PASSED - Transformed {len(transformed)} slot(s) for AI")
|
| 48 |
+
sample = transformed[0]
|
| 49 |
+
print(f" Slot ID: {sample['slot_id']}")
|
| 50 |
+
print(f" Coordinates: ({sample['latitude']}, {sample['longitude']})")
|
| 51 |
+
print(f" Price: ₹{sample['price_per_hour']}/hr")
|
| 52 |
+
results['AI Transform'] = True
|
| 53 |
+
else:
|
| 54 |
+
print(f"❌ FAILED - No transformed data")
|
| 55 |
+
results['AI Transform'] = False
|
| 56 |
+
except Exception as e:
|
| 57 |
+
print(f"❌ FAILED - {e}")
|
| 58 |
+
results['AI Transform'] = False
|
| 59 |
+
|
| 60 |
+
# Test 3: User Registration
|
| 61 |
+
print_header("TEST 3: User Registration")
|
| 62 |
+
try:
|
| 63 |
+
result = api.register_user(
|
| 64 |
+
name="System Test User",
|
| 65 |
+
phone="+919876543210",
|
| 66 |
+
email="systest@parking.com"
|
| 67 |
+
)
|
| 68 |
+
if result['status'] == 'success':
|
| 69 |
+
print(f"✅ PASSED - {result.get('message')}")
|
| 70 |
+
results['User Registration'] = True
|
| 71 |
+
else:
|
| 72 |
+
print(f"❌ FAILED - {result.get('message')}")
|
| 73 |
+
results['User Registration'] = False
|
| 74 |
+
except Exception as e:
|
| 75 |
+
print(f"❌ FAILED - {e}")
|
| 76 |
+
results['User Registration'] = False
|
| 77 |
+
|
| 78 |
+
# Test 4: Create Booking
|
| 79 |
+
print_header("TEST 4: Create Booking")
|
| 80 |
+
booking_uid = None
|
| 81 |
+
try:
|
| 82 |
+
start_time = datetime.now()
|
| 83 |
+
end_time = start_time + timedelta(hours=2)
|
| 84 |
+
|
| 85 |
+
result = api.book_slot(
|
| 86 |
+
user_id=9, # Known existing user
|
| 87 |
+
slot_id=1, # Known existing slot
|
| 88 |
+
start_time=start_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 89 |
+
end_time=end_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 90 |
+
total_amount=120.0
|
| 91 |
+
)
|
| 92 |
+
|
| 93 |
+
if result['status'] == 'success':
|
| 94 |
+
booking_uid = result.get('booking_uid')
|
| 95 |
+
print(f"✅ PASSED - Booking created")
|
| 96 |
+
print(f" Booking UID: {booking_uid}")
|
| 97 |
+
results['Create Booking'] = True
|
| 98 |
+
else:
|
| 99 |
+
print(f"❌ FAILED - {result.get('message')}")
|
| 100 |
+
results['Create Booking'] = False
|
| 101 |
+
except Exception as e:
|
| 102 |
+
print(f"❌ FAILED - {e}")
|
| 103 |
+
results['Create Booking'] = False
|
| 104 |
+
|
| 105 |
+
# Test 5: Get Booking Status
|
| 106 |
+
if booking_uid:
|
| 107 |
+
print_header("TEST 5: Get Booking Status")
|
| 108 |
+
try:
|
| 109 |
+
result = api.get_booking_status(booking_uid)
|
| 110 |
+
if result['status'] == 'success' and result.get('data'):
|
| 111 |
+
booking = result['data']
|
| 112 |
+
print(f"✅ PASSED - Booking retrieved")
|
| 113 |
+
print(f" Status: {booking.get('status')}")
|
| 114 |
+
print(f" Payment: {booking.get('payment_status')}")
|
| 115 |
+
print(f" Amount: ₹{booking.get('total_amount')}")
|
| 116 |
+
results['Get Booking'] = True
|
| 117 |
+
else:
|
| 118 |
+
print(f"❌ FAILED - Booking not found")
|
| 119 |
+
results['Get Booking'] = False
|
| 120 |
+
except Exception as e:
|
| 121 |
+
print(f"❌ FAILED - {e}")
|
| 122 |
+
results['Get Booking'] = False
|
| 123 |
+
else:
|
| 124 |
+
print_header("TEST 5: Get Booking Status")
|
| 125 |
+
print("⏭️ SKIPPED - No booking created")
|
| 126 |
+
results['Get Booking'] = None
|
| 127 |
+
|
| 128 |
+
# Test 6: Update Payment
|
| 129 |
+
if booking_uid:
|
| 130 |
+
print_header("TEST 6: Update Payment Status")
|
| 131 |
+
try:
|
| 132 |
+
result = api.update_payment(
|
| 133 |
+
booking_uid=booking_uid,
|
| 134 |
+
payment_status='Paid',
|
| 135 |
+
transaction_id=f'txn_test_{booking_uid}',
|
| 136 |
+
amount=120.0
|
| 137 |
+
)
|
| 138 |
+
if result['status'] == 'success':
|
| 139 |
+
print(f"✅ PASSED - Payment updated to Paid")
|
| 140 |
+
results['Update Payment'] = True
|
| 141 |
+
else:
|
| 142 |
+
print(f"❌ FAILED - {result.get('message')}")
|
| 143 |
+
results['Update Payment'] = False
|
| 144 |
+
except Exception as e:
|
| 145 |
+
print(f"❌ FAILED - {e}")
|
| 146 |
+
results['Update Payment'] = False
|
| 147 |
+
else:
|
| 148 |
+
print_header("TEST 6: Update Payment Status")
|
| 149 |
+
print("⏭️ SKIPPED - No booking created")
|
| 150 |
+
results['Update Payment'] = None
|
| 151 |
+
|
| 152 |
+
# Summary
|
| 153 |
+
print("\n" + "="*70)
|
| 154 |
+
print("📊 TEST SUMMARY")
|
| 155 |
+
print("="*70)
|
| 156 |
+
|
| 157 |
+
passed = sum(1 for v in results.values() if v is True)
|
| 158 |
+
failed = sum(1 for v in results.values() if v is False)
|
| 159 |
+
skipped = sum(1 for v in results.values() if v is None)
|
| 160 |
+
total = passed + failed
|
| 161 |
+
|
| 162 |
+
for test_name, result in results.items():
|
| 163 |
+
if result is True:
|
| 164 |
+
print(f"✅ PASSED: {test_name}")
|
| 165 |
+
elif result is False:
|
| 166 |
+
print(f"❌ FAILED: {test_name}")
|
| 167 |
+
else:
|
| 168 |
+
print(f"⏭️ SKIPPED: {test_name}")
|
| 169 |
+
|
| 170 |
+
print("\n" + "="*70)
|
| 171 |
+
print(f"Total: {passed}/{total} tests passed")
|
| 172 |
+
if skipped:
|
| 173 |
+
print(f"Skipped: {skipped} test(s)")
|
| 174 |
+
|
| 175 |
+
if passed == total and total > 0:
|
| 176 |
+
print("\n🎉 ALL TESTS PASSED! System is ready!")
|
| 177 |
+
elif passed >= total * 0.8:
|
| 178 |
+
print("\n✅ Most tests passed! System is functional!")
|
| 179 |
+
else:
|
| 180 |
+
print("\n⚠️ Some tests failed. Check the output above.")
|
| 181 |
+
|
| 182 |
+
print("\n💡 To start the API server:")
|
| 183 |
+
print(" python backend/main.py")
|
| 184 |
+
print("\n📖 For more info, see:")
|
| 185 |
+
print(" - SUCCESS_SUMMARY.md")
|
| 186 |
+
print(" - TESTING_GUIDE.md")
|
| 187 |
+
print("="*70)
|
| 188 |
+
|
| 189 |
+
if __name__ == "__main__":
|
| 190 |
+
main()
|
parking_model.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:58a841e4f900172e5662e2f41492ff9aff3d1ef67c7820c20b746186a94ab2ae
|
| 3 |
+
size 753436
|
requirements.txt
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
numpy>=1.24.0
|
| 2 |
+
scikit-learn>=1.3.0
|
| 3 |
+
pandas>=2.0.0
|
| 4 |
+
|
| 5 |
+
# Web Framework
|
| 6 |
+
fastapi>=0.104.0
|
| 7 |
+
uvicorn[standard]>=0.24.0
|
| 8 |
+
pydantic>=2.0.0
|
| 9 |
+
|
| 10 |
+
# HTTP Requests (for database API)
|
| 11 |
+
requests>=2.31.0
|
| 12 |
+
|
| 13 |
+
# Payment Gateway
|
| 14 |
+
razorpay>=1.4.0
|
| 15 |
+
|
| 16 |
+
# Database (optional - for production)
|
| 17 |
+
sqlalchemy>=2.0.0
|
| 18 |
+
psycopg2-binary>=2.9.0
|
| 19 |
+
|
| 20 |
+
# Environment variables
|
| 21 |
+
python-dotenv>=1.0.0
|
| 22 |
+
|
| 23 |
+
# CORS
|
| 24 |
+
python-multipart>=0.0.6
|
| 25 |
+
|
| 26 |
+
# For production deployment
|
| 27 |
+
gunicorn>=21.0.0
|
run_tests.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Quick Test - Run all basic tests at once
|
| 3 |
+
"""
|
| 4 |
+
import subprocess
|
| 5 |
+
import sys
|
| 6 |
+
|
| 7 |
+
def run_test(name, command):
|
| 8 |
+
"""Run a test and display results"""
|
| 9 |
+
print("\n" + "=" * 70)
|
| 10 |
+
print(f"🧪 TEST: {name}")
|
| 11 |
+
print("=" * 70)
|
| 12 |
+
|
| 13 |
+
try:
|
| 14 |
+
result = subprocess.run(
|
| 15 |
+
command,
|
| 16 |
+
shell=True,
|
| 17 |
+
capture_output=True,
|
| 18 |
+
text=True,
|
| 19 |
+
timeout=30
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
print(result.stdout)
|
| 23 |
+
if result.stderr:
|
| 24 |
+
print("STDERR:", result.stderr)
|
| 25 |
+
|
| 26 |
+
return result.returncode == 0
|
| 27 |
+
except subprocess.TimeoutExpired:
|
| 28 |
+
print("❌ Test timed out")
|
| 29 |
+
return False
|
| 30 |
+
except Exception as e:
|
| 31 |
+
print(f"❌ Error: {e}")
|
| 32 |
+
return False
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def main():
|
| 36 |
+
print("""
|
| 37 |
+
╔══════════════════════════════════════════════════════════════╗
|
| 38 |
+
║ SMART PARKING SYSTEM - QUICK TEST SUITE ║
|
| 39 |
+
╚══════════════════════════════════════════════════════════════╝
|
| 40 |
+
""")
|
| 41 |
+
|
| 42 |
+
tests = [
|
| 43 |
+
("Database Slot Check", "python check_slots.py"),
|
| 44 |
+
("Full Database Integration", "python test_database.py"),
|
| 45 |
+
]
|
| 46 |
+
|
| 47 |
+
results = {}
|
| 48 |
+
|
| 49 |
+
for name, command in tests:
|
| 50 |
+
results[name] = run_test(name, command)
|
| 51 |
+
|
| 52 |
+
# Summary
|
| 53 |
+
print("\n" + "=" * 70)
|
| 54 |
+
print("📊 TEST SUMMARY")
|
| 55 |
+
print("=" * 70)
|
| 56 |
+
|
| 57 |
+
for name, passed in results.items():
|
| 58 |
+
status = "✅ PASSED" if passed else "❌ FAILED"
|
| 59 |
+
print(f"{status}: {name}")
|
| 60 |
+
|
| 61 |
+
total = len(results)
|
| 62 |
+
passed = sum(1 for v in results.values() if v)
|
| 63 |
+
|
| 64 |
+
print(f"\n Total: {passed}/{total} tests passed")
|
| 65 |
+
|
| 66 |
+
if passed == total:
|
| 67 |
+
print("\n🎉 All tests passed!")
|
| 68 |
+
else:
|
| 69 |
+
print("\n⚠️ Some tests failed. Check the output above.")
|
| 70 |
+
|
| 71 |
+
print("\n💡 To start the API server, run:")
|
| 72 |
+
print(" python backend/main.py")
|
| 73 |
+
print("\n💡 Then visit http://127.0.0.1:8000/docs for interactive API testing")
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
if __name__ == "__main__":
|
| 77 |
+
main()
|
test_api_raw.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Diagnose the actual API response structure
|
| 3 |
+
"""
|
| 4 |
+
import requests
|
| 5 |
+
import json
|
| 6 |
+
|
| 7 |
+
API_URL = "https://aadarshsenapati.in/api/api.php"
|
| 8 |
+
|
| 9 |
+
print("=" * 70)
|
| 10 |
+
print("RAW API RESPONSE DIAGNOSTIC")
|
| 11 |
+
print("=" * 70)
|
| 12 |
+
|
| 13 |
+
# Test 1: Get parking lots
|
| 14 |
+
print("\n1. GET PARKING LOTS")
|
| 15 |
+
print("-" * 70)
|
| 16 |
+
response = requests.get(f"{API_URL}?action=get_parking_lots", timeout=10)
|
| 17 |
+
print(f"Status Code: {response.status_code}")
|
| 18 |
+
print(f"\nRaw Response Text:")
|
| 19 |
+
print(response.text)
|
| 20 |
+
print(f"\nParsed JSON:")
|
| 21 |
+
data = response.json()
|
| 22 |
+
print(json.dumps(data, indent=2))
|
| 23 |
+
|
| 24 |
+
if data.get('status') == 'success' and data.get('data'):
|
| 25 |
+
print(f"\n📊 First Record Fields:")
|
| 26 |
+
first_record = data['data'][0]
|
| 27 |
+
for key, value in first_record.items():
|
| 28 |
+
print(f" {key}: {value} (type: {type(value).__name__})")
|
| 29 |
+
|
| 30 |
+
# Test 2: Get users (if endpoint exists)
|
| 31 |
+
print("\n\n2. GET USERS")
|
| 32 |
+
print("-" * 70)
|
| 33 |
+
try:
|
| 34 |
+
response = requests.get(f"{API_URL}?action=get_users", timeout=10)
|
| 35 |
+
print(f"Status Code: {response.status_code}")
|
| 36 |
+
if response.status_code == 200:
|
| 37 |
+
print(json.dumps(response.json(), indent=2))
|
| 38 |
+
except Exception as e:
|
| 39 |
+
print(f"Error: {e}")
|
| 40 |
+
|
| 41 |
+
# Test 3: Get slots (if different from lots)
|
| 42 |
+
print("\n\n3. GET SLOTS")
|
| 43 |
+
print("-" * 70)
|
| 44 |
+
try:
|
| 45 |
+
response = requests.get(f"{API_URL}?action=get_slots", timeout=10)
|
| 46 |
+
print(f"Status Code: {response.status_code}")
|
| 47 |
+
if response.status_code == 200:
|
| 48 |
+
data = response.json()
|
| 49 |
+
print(json.dumps(data, indent=2))
|
| 50 |
+
if data.get('status') == 'success' and data.get('data'):
|
| 51 |
+
print(f"\n📊 First Slot Record Fields:")
|
| 52 |
+
first_record = data['data'][0]
|
| 53 |
+
for key, value in first_record.items():
|
| 54 |
+
print(f" {key}: {value} (type: {type(value).__name__})")
|
| 55 |
+
except Exception as e:
|
| 56 |
+
print(f"Error: {e}")
|
| 57 |
+
|
| 58 |
+
# Test 4: Get slots by lot_id
|
| 59 |
+
print("\n\n4. GET SLOTS BY LOT ID")
|
| 60 |
+
print("-" * 70)
|
| 61 |
+
try:
|
| 62 |
+
response = requests.get(f"{API_URL}?action=get_slots_by_lot&lot_id=1", timeout=10)
|
| 63 |
+
print(f"Status Code: {response.status_code}")
|
| 64 |
+
if response.status_code == 200:
|
| 65 |
+
data = response.json()
|
| 66 |
+
print(json.dumps(data, indent=2))
|
| 67 |
+
if data.get('status') == 'success' and data.get('data'):
|
| 68 |
+
print(f"\n📊 First Slot Record Fields:")
|
| 69 |
+
first_record = data['data'][0]
|
| 70 |
+
for key, value in first_record.items():
|
| 71 |
+
print(f" {key}: {value} (type: {type(value).__name__})")
|
| 72 |
+
except Exception as e:
|
| 73 |
+
print(f"Error: {e}")
|
| 74 |
+
|
| 75 |
+
# Test 5: Get available slots
|
| 76 |
+
print("\n\n5. GET AVAILABLE SLOTS")
|
| 77 |
+
print("-" * 70)
|
| 78 |
+
try:
|
| 79 |
+
response = requests.get(f"{API_URL}?action=get_available_slots", timeout=10)
|
| 80 |
+
print(f"Status Code: {response.status_code}")
|
| 81 |
+
if response.status_code == 200:
|
| 82 |
+
data = response.json()
|
| 83 |
+
print(json.dumps(data, indent=2))
|
| 84 |
+
if data.get('status') == 'success' and data.get('data'):
|
| 85 |
+
print(f"\n📊 First Slot Record Fields:")
|
| 86 |
+
first_record = data['data'][0]
|
| 87 |
+
for key, value in first_record.items():
|
| 88 |
+
print(f" {key}: {value} (type: {type(value).__name__})")
|
| 89 |
+
except Exception as e:
|
| 90 |
+
print(f"Error: {e}")
|
| 91 |
+
|
| 92 |
+
# Test 6: Try to get parking_slots table data
|
| 93 |
+
print("\n\n6. GET PARKING SLOTS (alternative endpoint name)")
|
| 94 |
+
print("-" * 70)
|
| 95 |
+
try:
|
| 96 |
+
response = requests.get(f"{API_URL}?action=get_parking_slots", timeout=10)
|
| 97 |
+
print(f"Status Code: {response.status_code}")
|
| 98 |
+
if response.status_code == 200:
|
| 99 |
+
data = response.json()
|
| 100 |
+
print(json.dumps(data, indent=2))
|
| 101 |
+
if data.get('status') == 'success' and data.get('data'):
|
| 102 |
+
print(f"\n📊 First Slot Record Fields:")
|
| 103 |
+
first_record = data['data'][0]
|
| 104 |
+
for key, value in first_record.items():
|
| 105 |
+
print(f" {key}: {value} (type: {type(value).__name__})")
|
| 106 |
+
except Exception as e:
|
| 107 |
+
print(f"Error: {e}")
|
| 108 |
+
|
| 109 |
+
print("\n" + "=" * 70)
|
| 110 |
+
print("END DIAGNOSTIC")
|
| 111 |
+
print("=" * 70)
|
test_booking_userid.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Test booking with valid user_id
|
| 3 |
+
"""
|
| 4 |
+
import requests
|
| 5 |
+
import json
|
| 6 |
+
from datetime import datetime, timedelta
|
| 7 |
+
|
| 8 |
+
base_url = "https://aadarshsenapati.in/api/api.php"
|
| 9 |
+
|
| 10 |
+
print("=" * 70)
|
| 11 |
+
print("TESTING BOOKING WITH DIFFERENT USER IDs")
|
| 12 |
+
print("=" * 70)
|
| 13 |
+
|
| 14 |
+
# Prepare booking data
|
| 15 |
+
start_time = datetime.now()
|
| 16 |
+
end_time = start_time + timedelta(hours=2)
|
| 17 |
+
|
| 18 |
+
# Try different user IDs
|
| 19 |
+
user_ids_to_try = [1, 9, 10]
|
| 20 |
+
|
| 21 |
+
for user_id in user_ids_to_try:
|
| 22 |
+
print(f"\n{'='*70}")
|
| 23 |
+
print(f"🧪 Testing with user_id: {user_id}")
|
| 24 |
+
print('='*70)
|
| 25 |
+
|
| 26 |
+
booking_data = {
|
| 27 |
+
"user_id": user_id,
|
| 28 |
+
"slot_id": 1,
|
| 29 |
+
"start_time": start_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 30 |
+
"end_time": end_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 31 |
+
"total_amount": 120.0
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
try:
|
| 35 |
+
response = requests.post(
|
| 36 |
+
f"{base_url}?action=book_slot",
|
| 37 |
+
json=booking_data,
|
| 38 |
+
headers={'Content-Type': 'application/json'},
|
| 39 |
+
timeout=10
|
| 40 |
+
)
|
| 41 |
+
|
| 42 |
+
print(f"Status Code: {response.status_code}")
|
| 43 |
+
|
| 44 |
+
if response.status_code == 200:
|
| 45 |
+
try:
|
| 46 |
+
result = response.json()
|
| 47 |
+
print(f"✅ SUCCESS!")
|
| 48 |
+
print(f"Response: {json.dumps(result, indent=2)}")
|
| 49 |
+
|
| 50 |
+
if result.get('status') == 'success':
|
| 51 |
+
print(f"\n🎉 Booking created successfully!")
|
| 52 |
+
print(f" Booking UID: {result.get('booking_uid')}")
|
| 53 |
+
print(f" User ID: {user_id} ✅ WORKS!")
|
| 54 |
+
break # Stop after first success
|
| 55 |
+
except:
|
| 56 |
+
print(f"⚠️ Response is not JSON: {response.text[:200]}")
|
| 57 |
+
else:
|
| 58 |
+
print(f"❌ FAILED with user_id: {user_id}")
|
| 59 |
+
|
| 60 |
+
except Exception as e:
|
| 61 |
+
print(f"❌ Error: {e}")
|
| 62 |
+
|
| 63 |
+
print("\n" + "=" * 70)
|
| 64 |
+
print("💡 RECOMMENDATION:")
|
| 65 |
+
print("=" * 70)
|
| 66 |
+
print("""
|
| 67 |
+
The booking endpoint works, but specific user_ids may not exist.
|
| 68 |
+
|
| 69 |
+
Solutions:
|
| 70 |
+
1. Use user_id that exists (like 9 from your manual test)
|
| 71 |
+
2. Create user_id = 1 in database
|
| 72 |
+
3. Update Python code to use existing user_id
|
| 73 |
+
""")
|
test_database.py
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Test Database API Integration
|
| 3 |
+
Tests the connection to https://aadarshsenapati.in/api/api.php
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import sys
|
| 7 |
+
import os
|
| 8 |
+
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
| 9 |
+
|
| 10 |
+
from backend.database_api import DatabaseAPI, transform_parking_lots_for_ai
|
| 11 |
+
from datetime import datetime, timedelta
|
| 12 |
+
import json
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def test_database_connection():
|
| 16 |
+
"""Test basic database connectivity"""
|
| 17 |
+
print("\n" + "=" * 70)
|
| 18 |
+
print("DATABASE API CONNECTION TEST")
|
| 19 |
+
print("=" * 70)
|
| 20 |
+
|
| 21 |
+
api = DatabaseAPI()
|
| 22 |
+
|
| 23 |
+
# Test 1: Get parking lots and slots
|
| 24 |
+
print("\n1️⃣ Testing: Get Available Parking Slots")
|
| 25 |
+
print("-" * 70)
|
| 26 |
+
result = api.get_all_available_slots()
|
| 27 |
+
|
| 28 |
+
if result['status'] == 'success':
|
| 29 |
+
slots = result.get('data', [])
|
| 30 |
+
total_lots = result.get('total_lots', 0)
|
| 31 |
+
print(f"✅ SUCCESS: Found {len(slots)} available slots from {total_lots} parking lot(s)")
|
| 32 |
+
|
| 33 |
+
if slots:
|
| 34 |
+
print(f"\n📊 Sample Parking Slot:")
|
| 35 |
+
sample = slots[0]
|
| 36 |
+
print(f" Slot ID: {sample.get('slot_id')}")
|
| 37 |
+
print(f" Slot Number: {sample.get('slot_number')}")
|
| 38 |
+
print(f" Lot Name: {sample.get('lot_name')}")
|
| 39 |
+
print(f" Location: {sample.get('lot_address')}")
|
| 40 |
+
print(f" Coordinates: ({sample.get('lot_latitude')}, {sample.get('lot_longitude')})")
|
| 41 |
+
print(f" Vehicle Type: {sample.get('vehicle_type')}")
|
| 42 |
+
print(f" Price/Hour: ₹{sample.get('hourly_rate')}")
|
| 43 |
+
|
| 44 |
+
# Test data transformation
|
| 45 |
+
print(f"\n🔄 Transforming data for AI model...")
|
| 46 |
+
transformed = transform_parking_lots_for_ai(slots)
|
| 47 |
+
print(f"✅ Transformed {len(transformed)} slots")
|
| 48 |
+
print(f"\n📊 Transformed Sample:")
|
| 49 |
+
t_sample = transformed[0]
|
| 50 |
+
print(f" Slot ID: {t_sample['slot_id']}")
|
| 51 |
+
print(f" DB Slot ID: {t_sample.get('db_slot_id')}")
|
| 52 |
+
print(f" Coordinates: ({t_sample['latitude']}, {t_sample['longitude']})")
|
| 53 |
+
print(f" Proximity Score: {t_sample['proximity_score']}")
|
| 54 |
+
print(f" Popularity Score: {t_sample['popularity_score']}")
|
| 55 |
+
print(f" Price Factor: {t_sample['price_factor']}")
|
| 56 |
+
print(f" Price/Hour: ₹{t_sample['price_per_hour']}")
|
| 57 |
+
else:
|
| 58 |
+
print(f"❌ FAILED: {result.get('message')}")
|
| 59 |
+
|
| 60 |
+
return api
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def test_user_registration(api):
|
| 64 |
+
"""Test user registration"""
|
| 65 |
+
print("\n2️⃣ Testing: User Registration")
|
| 66 |
+
print("-" * 70)
|
| 67 |
+
|
| 68 |
+
test_user = {
|
| 69 |
+
"name": "Test User AI",
|
| 70 |
+
"phone": "+919999888877",
|
| 71 |
+
"email": "aitest@smartparking.com"
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
result = api.register_user(**test_user)
|
| 75 |
+
|
| 76 |
+
if result['status'] == 'success':
|
| 77 |
+
print(f"✅ SUCCESS: {result.get('message')}")
|
| 78 |
+
print(f" Name: {test_user['name']}")
|
| 79 |
+
print(f" Phone: {test_user['phone']}")
|
| 80 |
+
else:
|
| 81 |
+
print(f"❌ FAILED: {result.get('message')}")
|
| 82 |
+
|
| 83 |
+
return result['status'] == 'success'
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def test_booking_flow(api):
|
| 87 |
+
"""Test complete booking flow"""
|
| 88 |
+
print("\n3️⃣ Testing: Booking Flow")
|
| 89 |
+
print("-" * 70)
|
| 90 |
+
|
| 91 |
+
# Get available slots first
|
| 92 |
+
slots_result = api.get_all_available_slots()
|
| 93 |
+
if slots_result['status'] != 'success' or not slots_result.get('data'):
|
| 94 |
+
print("❌ Cannot test booking: No available slots")
|
| 95 |
+
return False
|
| 96 |
+
|
| 97 |
+
# Use first available slot
|
| 98 |
+
slot = slots_result['data'][0]
|
| 99 |
+
slot_db_id = slot.get('slot_id') or slot.get('id') or 1
|
| 100 |
+
slot_number = slot.get('slot_number', 'Unknown')
|
| 101 |
+
lot_name = slot.get('lot_name', 'Unknown')
|
| 102 |
+
|
| 103 |
+
# Create booking
|
| 104 |
+
start_time = datetime.now()
|
| 105 |
+
end_time = start_time + timedelta(hours=2)
|
| 106 |
+
|
| 107 |
+
# Use user_id = 9 (known to exist in database)
|
| 108 |
+
# In production, this should be the authenticated user's ID
|
| 109 |
+
booking_data = {
|
| 110 |
+
"user_id": 9, # Using existing user ID from database
|
| 111 |
+
"slot_id": int(slot_db_id),
|
| 112 |
+
"start_time": start_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 113 |
+
"end_time": end_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 114 |
+
"total_amount": 120.0
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
print(f"\n📝 Creating booking...")
|
| 118 |
+
print(f" Lot: {lot_name}")
|
| 119 |
+
print(f" Slot: {slot_number} (DB ID: {slot_db_id})")
|
| 120 |
+
print(f" Duration: 2 hours")
|
| 121 |
+
print(f" Amount: ₹120")
|
| 122 |
+
print(f" User ID: 9 (existing user)")
|
| 123 |
+
|
| 124 |
+
result = api.book_slot(**booking_data)
|
| 125 |
+
|
| 126 |
+
if result['status'] == 'success':
|
| 127 |
+
booking_uid = result.get('booking_uid')
|
| 128 |
+
print(f"✅ SUCCESS: Booking created")
|
| 129 |
+
print(f" Booking UID: {booking_uid}")
|
| 130 |
+
|
| 131 |
+
# Test getting booking status
|
| 132 |
+
print(f"\n📊 Fetching booking status...")
|
| 133 |
+
status_result = api.get_booking_status(booking_uid)
|
| 134 |
+
|
| 135 |
+
if status_result['status'] == 'success':
|
| 136 |
+
booking = status_result.get('data', {})
|
| 137 |
+
print(f"✅ Booking found:")
|
| 138 |
+
print(f" Status: {booking.get('status')}")
|
| 139 |
+
print(f" Payment Status: {booking.get('payment_status')}")
|
| 140 |
+
print(f" Amount: ₹{booking.get('total_amount')}")
|
| 141 |
+
|
| 142 |
+
return booking_uid
|
| 143 |
+
else:
|
| 144 |
+
print(f"❌ FAILED: {result.get('message')}")
|
| 145 |
+
return None
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def test_payment_update(api, booking_uid):
|
| 149 |
+
"""Test payment status update"""
|
| 150 |
+
if not booking_uid:
|
| 151 |
+
print("\n⏭️ Skipping payment test (no booking UID)")
|
| 152 |
+
return
|
| 153 |
+
|
| 154 |
+
print("\n4️⃣ Testing: Payment Update")
|
| 155 |
+
print("-" * 70)
|
| 156 |
+
|
| 157 |
+
payment_data = {
|
| 158 |
+
"booking_uid": booking_uid,
|
| 159 |
+
"payment_status": "Paid",
|
| 160 |
+
"transaction_id": f"txn_test_{booking_uid}",
|
| 161 |
+
"amount": 120.0
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
print(f"💳 Updating payment status to 'Paid'...")
|
| 165 |
+
result = api.update_payment(**payment_data)
|
| 166 |
+
|
| 167 |
+
if result['status'] == 'success':
|
| 168 |
+
print(f"✅ SUCCESS: {result.get('message')}")
|
| 169 |
+
|
| 170 |
+
# Verify update
|
| 171 |
+
print(f"\n✓ Verifying update...")
|
| 172 |
+
status_result = api.get_booking_status(booking_uid)
|
| 173 |
+
if status_result['status'] == 'success':
|
| 174 |
+
booking = status_result.get('data', {})
|
| 175 |
+
print(f" Payment Status: {booking.get('payment_status')}")
|
| 176 |
+
else:
|
| 177 |
+
print(f"❌ FAILED: {result.get('message')}")
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
def test_feedback_submission(api, booking_uid):
|
| 181 |
+
"""Test feedback submission"""
|
| 182 |
+
if not booking_uid:
|
| 183 |
+
print("\n⏭️ Skipping feedback test (no booking UID)")
|
| 184 |
+
return
|
| 185 |
+
|
| 186 |
+
print("\n5️⃣ Testing: Feedback Submission")
|
| 187 |
+
print("-" * 70)
|
| 188 |
+
|
| 189 |
+
# Get booking ID (not UID) first
|
| 190 |
+
status_result = api.get_booking_status(booking_uid)
|
| 191 |
+
if status_result['status'] != 'success':
|
| 192 |
+
print("❌ Cannot get booking details for feedback")
|
| 193 |
+
return
|
| 194 |
+
|
| 195 |
+
booking = status_result.get('data', {})
|
| 196 |
+
booking_id = booking.get('id')
|
| 197 |
+
user_id = booking.get('user_id', 1)
|
| 198 |
+
|
| 199 |
+
feedback_data = {
|
| 200 |
+
"user_id": user_id,
|
| 201 |
+
"booking_id": booking_id,
|
| 202 |
+
"rating": 5.0,
|
| 203 |
+
"comments": "Excellent parking spot! Very convenient location."
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
print(f"⭐ Submitting feedback...")
|
| 207 |
+
print(f" Rating: {feedback_data['rating']}/5.0")
|
| 208 |
+
print(f" Comment: {feedback_data['comments']}")
|
| 209 |
+
|
| 210 |
+
result = api.add_feedback(**feedback_data)
|
| 211 |
+
|
| 212 |
+
if result['status'] == 'success':
|
| 213 |
+
print(f"✅ SUCCESS: {result.get('message')}")
|
| 214 |
+
else:
|
| 215 |
+
print(f"❌ FAILED: {result.get('message')}")
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
def test_booking_cancellation(api, booking_uid):
|
| 219 |
+
"""Test booking cancellation"""
|
| 220 |
+
if not booking_uid:
|
| 221 |
+
print("\n⏭️ Skipping cancellation test (no booking UID)")
|
| 222 |
+
return
|
| 223 |
+
|
| 224 |
+
print("\n6️⃣ Testing: Booking Cancellation")
|
| 225 |
+
print("-" * 70)
|
| 226 |
+
|
| 227 |
+
print(f"❌ Cancelling booking {booking_uid}...")
|
| 228 |
+
result = api.cancel_booking(booking_uid)
|
| 229 |
+
|
| 230 |
+
if result['status'] == 'success':
|
| 231 |
+
print(f"✅ SUCCESS: {result.get('message')}")
|
| 232 |
+
|
| 233 |
+
# Verify cancellation
|
| 234 |
+
status_result = api.get_booking_status(booking_uid)
|
| 235 |
+
if status_result['status'] == 'success':
|
| 236 |
+
booking = status_result.get('data', {})
|
| 237 |
+
print(f" Status: {booking.get('status')}")
|
| 238 |
+
else:
|
| 239 |
+
print(f"❌ FAILED: {result.get('message')}")
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
def main():
|
| 243 |
+
"""Run all database tests"""
|
| 244 |
+
print("\n" + "=" * 70)
|
| 245 |
+
print("🚀 SMART PARKING - DATABASE API INTEGRATION TESTS")
|
| 246 |
+
print("=" * 70)
|
| 247 |
+
print(f"Database URL: https://aadarshsenapati.in/api/api.php")
|
| 248 |
+
print(f"Test Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
| 249 |
+
|
| 250 |
+
try:
|
| 251 |
+
# Initialize API
|
| 252 |
+
api = test_database_connection()
|
| 253 |
+
|
| 254 |
+
# Test user registration
|
| 255 |
+
test_user_registration(api)
|
| 256 |
+
|
| 257 |
+
# Test booking flow
|
| 258 |
+
booking_uid = test_booking_flow(api)
|
| 259 |
+
|
| 260 |
+
# Test payment update
|
| 261 |
+
test_payment_update(api, booking_uid)
|
| 262 |
+
|
| 263 |
+
# Test feedback
|
| 264 |
+
test_feedback_submission(api, booking_uid)
|
| 265 |
+
|
| 266 |
+
# Don't cancel in tests - keep the data
|
| 267 |
+
# test_booking_cancellation(api, booking_uid)
|
| 268 |
+
|
| 269 |
+
print("\n" + "=" * 70)
|
| 270 |
+
print("✅ DATABASE API INTEGRATION TESTS COMPLETED")
|
| 271 |
+
print("=" * 70)
|
| 272 |
+
print("\n💡 Next Steps:")
|
| 273 |
+
print(" 1. Verify data in database")
|
| 274 |
+
print(" 2. Test AI recommendations with real data")
|
| 275 |
+
print(" 3. Integrate with payment system")
|
| 276 |
+
print(" 4. Deploy to production")
|
| 277 |
+
|
| 278 |
+
except Exception as e:
|
| 279 |
+
print(f"\n❌ ERROR: {e}")
|
| 280 |
+
import traceback
|
| 281 |
+
traceback.print_exc()
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
if __name__ == "__main__":
|
| 285 |
+
main()
|
test_slot_availability.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Test Slot Availability Update - Prevent Double Booking
|
| 3 |
+
"""
|
| 4 |
+
from backend.database_api import DatabaseAPI
|
| 5 |
+
from datetime import datetime, timedelta
|
| 6 |
+
import json
|
| 7 |
+
|
| 8 |
+
api = DatabaseAPI()
|
| 9 |
+
|
| 10 |
+
print("=" * 70)
|
| 11 |
+
print("TESTING SLOT AVAILABILITY UPDATE (PREVENT DOUBLE BOOKING)")
|
| 12 |
+
print("=" * 70)
|
| 13 |
+
|
| 14 |
+
# Step 1: Check initial slot availability
|
| 15 |
+
print("\n1️⃣ Checking initial slot availability...")
|
| 16 |
+
slots_result = api.get_all_available_slots()
|
| 17 |
+
|
| 18 |
+
if slots_result['status'] == 'success' and slots_result.get('data'):
|
| 19 |
+
slot = slots_result['data'][0]
|
| 20 |
+
slot_id = slot.get('slot_id') or slot.get('id')
|
| 21 |
+
print(f"Slot ID: {slot_id}")
|
| 22 |
+
print(f"Slot Number: {slot.get('slot_number')}")
|
| 23 |
+
print(f"Initial status: Available ✅")
|
| 24 |
+
|
| 25 |
+
# Step 2: Create a booking
|
| 26 |
+
print(f"\n2️⃣ Creating booking for slot {slot_id}...")
|
| 27 |
+
start_time = datetime.now()
|
| 28 |
+
end_time = start_time + timedelta(hours=2)
|
| 29 |
+
|
| 30 |
+
booking_result = api.book_slot(
|
| 31 |
+
user_id=9,
|
| 32 |
+
slot_id=int(slot_id),
|
| 33 |
+
start_time=start_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 34 |
+
end_time=end_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 35 |
+
total_amount=120.0
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
if booking_result['status'] == 'success':
|
| 39 |
+
booking_uid = booking_result['booking_uid']
|
| 40 |
+
print(f"✅ Booking created: {booking_uid}")
|
| 41 |
+
|
| 42 |
+
# Step 3: Check if slot is now unavailable
|
| 43 |
+
print(f"\n3️⃣ Checking slot availability after booking...")
|
| 44 |
+
|
| 45 |
+
# Direct API call to check slot status
|
| 46 |
+
import requests
|
| 47 |
+
response = requests.get(
|
| 48 |
+
f"https://aadarshsenapati.in/api/api.php?action=get_available_slots",
|
| 49 |
+
json={"parking_lot_id": 1},
|
| 50 |
+
timeout=10
|
| 51 |
+
)
|
| 52 |
+
|
| 53 |
+
print(f"Available slots response:")
|
| 54 |
+
print(json.dumps(response.json(), indent=2))
|
| 55 |
+
|
| 56 |
+
# Also try to get all slots (including unavailable)
|
| 57 |
+
print(f"\n4️⃣ Attempting to book the same slot again...")
|
| 58 |
+
duplicate_booking = api.book_slot(
|
| 59 |
+
user_id=9,
|
| 60 |
+
slot_id=int(slot_id),
|
| 61 |
+
start_time=start_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 62 |
+
end_time=end_time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 63 |
+
total_amount=120.0
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
if duplicate_booking['status'] == 'success':
|
| 67 |
+
print(f"❌ WARNING: Duplicate booking allowed!")
|
| 68 |
+
print(f" Duplicate booking UID: {duplicate_booking['booking_uid']}")
|
| 69 |
+
print(f" This means is_available was not updated to 0")
|
| 70 |
+
else:
|
| 71 |
+
print(f"✅ GOOD: Duplicate booking prevented!")
|
| 72 |
+
print(f" Message: {duplicate_booking.get('message')}")
|
| 73 |
+
|
| 74 |
+
# Step 5: Test cancellation (should release slot)
|
| 75 |
+
print(f"\n5️⃣ Testing booking cancellation...")
|
| 76 |
+
cancel_result = api.cancel_booking(booking_uid)
|
| 77 |
+
|
| 78 |
+
if cancel_result['status'] == 'success':
|
| 79 |
+
print(f"✅ Booking cancelled")
|
| 80 |
+
|
| 81 |
+
# Check if slot is available again
|
| 82 |
+
print(f"\n6️⃣ Checking if slot is available after cancellation...")
|
| 83 |
+
slots_after = api.get_all_available_slots()
|
| 84 |
+
|
| 85 |
+
if slots_after['status'] == 'success':
|
| 86 |
+
available_count = len(slots_after.get('data', []))
|
| 87 |
+
print(f"Available slots now: {available_count}")
|
| 88 |
+
|
| 89 |
+
if available_count > 0:
|
| 90 |
+
print(f"✅ GOOD: Slot released and available again!")
|
| 91 |
+
else:
|
| 92 |
+
print(f"❌ WARNING: Slot not released after cancellation")
|
| 93 |
+
else:
|
| 94 |
+
print(f"❌ Cancellation failed: {cancel_result.get('message')}")
|
| 95 |
+
else:
|
| 96 |
+
print(f"❌ Booking failed: {booking_result.get('message')}")
|
| 97 |
+
else:
|
| 98 |
+
print("❌ No slots found to test")
|
| 99 |
+
|
| 100 |
+
print("\n" + "=" * 70)
|
| 101 |
+
print("SUMMARY")
|
| 102 |
+
print("=" * 70)
|
| 103 |
+
print("""
|
| 104 |
+
✅ EXPECTED BEHAVIOR:
|
| 105 |
+
1. Initial slot shows as available (is_available = 1)
|
| 106 |
+
2. After booking, slot becomes unavailable (is_available = 0)
|
| 107 |
+
3. Duplicate booking should be prevented
|
| 108 |
+
4. After cancellation, slot becomes available again (is_available = 1)
|
| 109 |
+
|
| 110 |
+
❌ CURRENT ISSUE (if not working):
|
| 111 |
+
- update_slot endpoint might not be implemented in PHP
|
| 112 |
+
- is_available not being updated when booking
|
| 113 |
+
- Multiple vehicles can book same slot
|
| 114 |
+
|
| 115 |
+
🔧 FIX NEEDED IN PHP:
|
| 116 |
+
Implement update_slot endpoint to update is_available field
|
| 117 |
+
""")
|
test_system.py
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Test script for the AI model and payment integration
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import sys
|
| 6 |
+
import os
|
| 7 |
+
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
| 8 |
+
|
| 9 |
+
from ai_model.parking_slot_classifier import ParkingSlotClassifier, generate_training_data
|
| 10 |
+
from backend.payment_service import PaymentService, PaymentSimulator
|
| 11 |
+
import json
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def test_ai_model():
|
| 15 |
+
"""Test the parking slot classifier"""
|
| 16 |
+
print("=" * 50)
|
| 17 |
+
print("Testing AI Model")
|
| 18 |
+
print("=" * 50)
|
| 19 |
+
|
| 20 |
+
# Initialize classifier
|
| 21 |
+
classifier = ParkingSlotClassifier()
|
| 22 |
+
|
| 23 |
+
# Generate and train with synthetic data
|
| 24 |
+
print("\n1. Generating training data...")
|
| 25 |
+
training_data, labels = generate_training_data(100)
|
| 26 |
+
print(f" Generated {len(training_data)} training samples")
|
| 27 |
+
|
| 28 |
+
print("\n2. Training model...")
|
| 29 |
+
classifier.train(training_data, labels)
|
| 30 |
+
print(" Model trained successfully")
|
| 31 |
+
|
| 32 |
+
# Test prediction
|
| 33 |
+
print("\n3. Testing predictions...")
|
| 34 |
+
test_slots = [
|
| 35 |
+
{
|
| 36 |
+
'slot_id': 'A1',
|
| 37 |
+
'latitude': 28.6139,
|
| 38 |
+
'longitude': 77.2090,
|
| 39 |
+
'avg_feedback': 4.5,
|
| 40 |
+
'popularity_score': 0.8,
|
| 41 |
+
'is_available': True,
|
| 42 |
+
'price_factor': 0.7,
|
| 43 |
+
'price_per_hour': 50.0
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
'slot_id': 'B2',
|
| 47 |
+
'latitude': 28.6150,
|
| 48 |
+
'longitude': 77.2100,
|
| 49 |
+
'avg_feedback': 3.2,
|
| 50 |
+
'popularity_score': 0.4,
|
| 51 |
+
'is_available': True,
|
| 52 |
+
'price_factor': 0.5,
|
| 53 |
+
'price_per_hour': 40.0
|
| 54 |
+
},
|
| 55 |
+
{
|
| 56 |
+
'slot_id': 'C3',
|
| 57 |
+
'latitude': 28.6145,
|
| 58 |
+
'longitude': 77.2095,
|
| 59 |
+
'avg_feedback': 4.8,
|
| 60 |
+
'popularity_score': 0.9,
|
| 61 |
+
'is_available': True,
|
| 62 |
+
'price_factor': 0.9,
|
| 63 |
+
'price_per_hour': 60.0
|
| 64 |
+
}
|
| 65 |
+
]
|
| 66 |
+
|
| 67 |
+
user_location = (28.6139, 77.2090)
|
| 68 |
+
best_slots = classifier.predict_best_slots(test_slots, user_location, top_k=3)
|
| 69 |
+
|
| 70 |
+
print("\n Top 3 Recommended Slots:")
|
| 71 |
+
for i, slot in enumerate(best_slots, 1):
|
| 72 |
+
print(f" {i}. {slot['slot_id']} - Score: {slot['recommendation_score']:.3f}")
|
| 73 |
+
print(f" Proximity: {slot['proximity_score']:.3f}, Rating: {slot['avg_feedback']}")
|
| 74 |
+
|
| 75 |
+
print("\n✅ AI Model Test Passed!")
|
| 76 |
+
return classifier
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def test_payment_service():
|
| 80 |
+
"""Test the payment service"""
|
| 81 |
+
print("\n" + "=" * 50)
|
| 82 |
+
print("Testing Payment Service")
|
| 83 |
+
print("=" * 50)
|
| 84 |
+
|
| 85 |
+
# Use simulator (doesn't require actual Razorpay connection)
|
| 86 |
+
print("\n1. Testing Payment Simulator...")
|
| 87 |
+
simulator = PaymentSimulator()
|
| 88 |
+
|
| 89 |
+
# Simulate payment
|
| 90 |
+
order_id = "order_test_123"
|
| 91 |
+
amount = 100.0
|
| 92 |
+
|
| 93 |
+
payment_result = simulator.simulate_payment(order_id, amount)
|
| 94 |
+
print(f" Payment ID: {payment_result['payment_id']}")
|
| 95 |
+
print(f" Amount: ₹{payment_result['amount']}")
|
| 96 |
+
print(f" Status: {payment_result['status']}")
|
| 97 |
+
|
| 98 |
+
# Retrieve simulated payment
|
| 99 |
+
payment_details = simulator.get_simulated_payment(payment_result['payment_id'])
|
| 100 |
+
print(f"\n Retrieved Payment: {json.dumps(payment_details, indent=2)}")
|
| 101 |
+
|
| 102 |
+
print("\n✅ Payment Service Test Passed!")
|
| 103 |
+
|
| 104 |
+
# Try real Razorpay (will fail gracefully if credentials are invalid)
|
| 105 |
+
print("\n2. Testing Real Razorpay Connection...")
|
| 106 |
+
try:
|
| 107 |
+
payment_service = PaymentService(
|
| 108 |
+
"rzp_test_RYlqJbc24Sl6jz",
|
| 109 |
+
"bghQe0L7iort9vmqb6Jlf8Ec"
|
| 110 |
+
)
|
| 111 |
+
print(" ✅ Razorpay client initialized")
|
| 112 |
+
|
| 113 |
+
# Try creating an order
|
| 114 |
+
order = payment_service.create_payment_order(
|
| 115 |
+
amount=50.0,
|
| 116 |
+
booking_id="TEST_123",
|
| 117 |
+
notes={'test': 'true'}
|
| 118 |
+
)
|
| 119 |
+
|
| 120 |
+
if order['success']:
|
| 121 |
+
print(f" ✅ Order created: {order['order_id']}")
|
| 122 |
+
else:
|
| 123 |
+
print(f" ⚠️ Order creation failed: {order.get('error')}")
|
| 124 |
+
|
| 125 |
+
except Exception as e:
|
| 126 |
+
print(f" ⚠️ Razorpay connection failed: {e}")
|
| 127 |
+
print(" (This is expected if credentials are invalid)")
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
def test_integration():
|
| 131 |
+
"""Test integration between AI model and payment"""
|
| 132 |
+
print("\n" + "=" * 50)
|
| 133 |
+
print("Testing Full Integration")
|
| 134 |
+
print("=" * 50)
|
| 135 |
+
|
| 136 |
+
print("\n1. User searches for parking...")
|
| 137 |
+
user_location = (28.6139, 77.2090)
|
| 138 |
+
print(f" User location: {user_location}")
|
| 139 |
+
|
| 140 |
+
print("\n2. AI recommends best slots...")
|
| 141 |
+
classifier = ParkingSlotClassifier()
|
| 142 |
+
|
| 143 |
+
# Quick train with small dataset
|
| 144 |
+
training_data, labels = generate_training_data(50)
|
| 145 |
+
classifier.train(training_data, labels)
|
| 146 |
+
|
| 147 |
+
# Sample available slots
|
| 148 |
+
available_slots = [
|
| 149 |
+
{
|
| 150 |
+
'slot_id': 'P101',
|
| 151 |
+
'latitude': 28.6145,
|
| 152 |
+
'longitude': 77.2095,
|
| 153 |
+
'avg_feedback': 4.2,
|
| 154 |
+
'popularity_score': 0.7,
|
| 155 |
+
'is_available': True,
|
| 156 |
+
'price_factor': 0.6,
|
| 157 |
+
'price_per_hour': 45.0
|
| 158 |
+
},
|
| 159 |
+
{
|
| 160 |
+
'slot_id': 'P102',
|
| 161 |
+
'latitude': 28.6140,
|
| 162 |
+
'longitude': 77.2088,
|
| 163 |
+
'avg_feedback': 4.8,
|
| 164 |
+
'popularity_score': 0.9,
|
| 165 |
+
'is_available': True,
|
| 166 |
+
'price_factor': 0.8,
|
| 167 |
+
'price_per_hour': 55.0
|
| 168 |
+
}
|
| 169 |
+
]
|
| 170 |
+
|
| 171 |
+
recommendations = classifier.predict_best_slots(available_slots, user_location, top_k=2)
|
| 172 |
+
|
| 173 |
+
print("\n Recommendations:")
|
| 174 |
+
for i, slot in enumerate(recommendations, 1):
|
| 175 |
+
print(f" {i}. Slot {slot['slot_id']} - Score: {slot['recommendation_score']:.3f}")
|
| 176 |
+
|
| 177 |
+
print("\n3. User selects a slot...")
|
| 178 |
+
selected_slot = recommendations[0]
|
| 179 |
+
print(f" Selected: {selected_slot['slot_id']}")
|
| 180 |
+
|
| 181 |
+
print("\n4. Creating payment order...")
|
| 182 |
+
simulator = PaymentSimulator()
|
| 183 |
+
booking_id = "BKG_TEST_001"
|
| 184 |
+
duration = 2
|
| 185 |
+
amount = selected_slot['price_per_hour'] * duration
|
| 186 |
+
|
| 187 |
+
payment = simulator.simulate_payment(f"order_{booking_id}", amount)
|
| 188 |
+
print(f" Payment ID: {payment['payment_id']}")
|
| 189 |
+
print(f" Amount: ₹{amount}")
|
| 190 |
+
|
| 191 |
+
print("\n5. User provides feedback...")
|
| 192 |
+
feedback = {
|
| 193 |
+
'booking_id': booking_id,
|
| 194 |
+
'slot_id': selected_slot['slot_id'],
|
| 195 |
+
'rating': 5.0,
|
| 196 |
+
'satisfaction': True
|
| 197 |
+
}
|
| 198 |
+
print(f" Rating: {feedback['rating']}/5")
|
| 199 |
+
print(f" Satisfied: {feedback['satisfaction']}")
|
| 200 |
+
|
| 201 |
+
print("\n✅ Full Integration Test Passed!")
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
if __name__ == "__main__":
|
| 205 |
+
print("\n🚀 Starting Smart Parking System Tests\n")
|
| 206 |
+
|
| 207 |
+
try:
|
| 208 |
+
# Test AI Model
|
| 209 |
+
classifier = test_ai_model()
|
| 210 |
+
|
| 211 |
+
# Test Payment Service
|
| 212 |
+
test_payment_service()
|
| 213 |
+
|
| 214 |
+
# Test Integration
|
| 215 |
+
test_integration()
|
| 216 |
+
|
| 217 |
+
print("\n" + "=" * 50)
|
| 218 |
+
print("✅ ALL TESTS PASSED!")
|
| 219 |
+
print("=" * 50)
|
| 220 |
+
print("\n📝 Next Steps:")
|
| 221 |
+
print("1. Set up real parking slot database")
|
| 222 |
+
print("2. Configure Twilio WhatsApp webhook")
|
| 223 |
+
print("3. Deploy backend to Render")
|
| 224 |
+
print("4. Deploy WhatsApp bot to production")
|
| 225 |
+
print("5. Test with real users")
|
| 226 |
+
|
| 227 |
+
except Exception as e:
|
| 228 |
+
print(f"\n❌ Test Failed: {e}")
|
| 229 |
+
import traceback
|
| 230 |
+
traceback.print_exc()
|