remove test files
This commit is contained in:
@@ -1,93 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Location Data Migration Script
|
||||
Run this FIRST to add location columns to your existing database
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from flask import Flask
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from sqlalchemy import text
|
||||
|
||||
def create_app():
|
||||
"""Create Flask app for migration"""
|
||||
app = Flask(__name__)
|
||||
database_url = os.environ.get('DATABASE_URL', 'postgresql://postgres:postgres1411@localhost/qr_management')
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = database_url
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
return app
|
||||
|
||||
def add_location_columns():
|
||||
"""Add location tracking columns to attendance_data table"""
|
||||
print("🚀 Adding location tracking capabilities to your QR system...")
|
||||
|
||||
app = create_app()
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
with app.app_context():
|
||||
try:
|
||||
# Check if table exists
|
||||
result = db.session.execute(text("""
|
||||
SELECT EXISTS (
|
||||
SELECT FROM information_schema.tables
|
||||
WHERE table_name = 'attendance_data'
|
||||
);
|
||||
"""))
|
||||
|
||||
if not result.fetchone()[0]:
|
||||
print("❌ attendance_data table not found. Please set up your QR system first.")
|
||||
return False
|
||||
|
||||
print("✅ Found attendance_data table")
|
||||
|
||||
# Add location columns with IF NOT EXISTS for safety
|
||||
location_columns = [
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS latitude FLOAT",
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS longitude FLOAT",
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS accuracy FLOAT",
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS altitude FLOAT",
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS location_source VARCHAR(50) DEFAULT 'manual'",
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS address VARCHAR(500)"
|
||||
]
|
||||
|
||||
print("\n📝 Adding location columns...")
|
||||
for sql_command in location_columns:
|
||||
try:
|
||||
db.session.execute(text(sql_command))
|
||||
column_name = sql_command.split()[4]
|
||||
print(f" ✅ Added: {column_name}")
|
||||
except Exception as e:
|
||||
print(f" ⚠️ Column may already exist: {e}")
|
||||
|
||||
db.session.commit()
|
||||
|
||||
# Verify columns were added
|
||||
result = db.session.execute(text("""
|
||||
SELECT column_name
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'attendance_data'
|
||||
AND column_name IN ('latitude', 'longitude', 'accuracy',
|
||||
'altitude', 'location_source', 'address')
|
||||
ORDER BY column_name;
|
||||
"""))
|
||||
|
||||
added_columns = [row[0] for row in result.fetchall()]
|
||||
print(f"\n✅ Migration completed! Added {len(added_columns)} location columns:")
|
||||
print(f" 📝 Columns: {', '.join(added_columns)}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Migration failed: {e}")
|
||||
db.session.rollback()
|
||||
return False
|
||||
|
||||
if __name__ == '__main__':
|
||||
success = add_location_columns()
|
||||
if success:
|
||||
print("\n🎉 Database migration successful!")
|
||||
print(" Now you can update your app.py with the enhanced AttendanceData model")
|
||||
else:
|
||||
print("❌ Migration failed. Please check your database connection and try again.")
|
||||
sys.exit(1)
|
||||
@@ -1,148 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple Database Migration for Geolocation
|
||||
Run this script FIRST before updating your app.py
|
||||
"""
|
||||
|
||||
import psycopg2
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Database connection (adjust if needed)
|
||||
DATABASE_URL = os.environ.get('DATABASE_URL', 'postgresql://postgres:postgres1411@localhost/qr_management')
|
||||
|
||||
def add_location_columns():
|
||||
"""Add location columns to attendance_data table"""
|
||||
|
||||
print("🚀 Adding location tracking columns to your database...")
|
||||
|
||||
try:
|
||||
# Connect to database
|
||||
conn = psycopg2.connect(DATABASE_URL)
|
||||
cursor = conn.cursor()
|
||||
|
||||
print("✅ Connected to database")
|
||||
|
||||
# Check if attendance_data table exists
|
||||
cursor.execute("""
|
||||
SELECT EXISTS (
|
||||
SELECT FROM information_schema.tables
|
||||
WHERE table_name = 'attendance_data'
|
||||
);
|
||||
""")
|
||||
|
||||
if not cursor.fetchone()[0]:
|
||||
print("❌ attendance_data table not found!")
|
||||
print(" Make sure your QR system is set up first")
|
||||
return False
|
||||
|
||||
print("✅ attendance_data table found")
|
||||
|
||||
# Add location columns (using IF NOT EXISTS for safety)
|
||||
location_columns = [
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS latitude FLOAT",
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS longitude FLOAT",
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS accuracy FLOAT",
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS altitude FLOAT",
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS location_source VARCHAR(50) DEFAULT 'manual'",
|
||||
"ALTER TABLE attendance_data ADD COLUMN IF NOT EXISTS address VARCHAR(255)"
|
||||
]
|
||||
|
||||
print("\n📝 Adding columns...")
|
||||
for sql in location_columns:
|
||||
try:
|
||||
cursor.execute(sql)
|
||||
column_name = sql.split()[4] # Extract column name
|
||||
print(f" ✅ Added: {column_name}")
|
||||
except Exception as e:
|
||||
print(f" ⚠️ Column may already exist: {e}")
|
||||
|
||||
# Commit changes
|
||||
conn.commit()
|
||||
|
||||
# Verify columns were added
|
||||
cursor.execute("""
|
||||
SELECT column_name
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'attendance_data'
|
||||
AND column_name IN ('latitude', 'longitude', 'accuracy',
|
||||
'altitude', 'location_source', 'address')
|
||||
ORDER BY column_name;
|
||||
""")
|
||||
|
||||
added_columns = [row[0] for row in cursor.fetchall()]
|
||||
|
||||
print(f"\n📊 Verification:")
|
||||
print(f" ✅ Location columns found: {len(added_columns)}")
|
||||
if added_columns:
|
||||
print(f" 📝 Columns: {', '.join(added_columns)}")
|
||||
|
||||
# Check existing data
|
||||
cursor.execute("SELECT COUNT(*) FROM attendance_data")
|
||||
total_records = cursor.fetchone()[0]
|
||||
print(f" 📊 Total attendance records: {total_records}")
|
||||
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
print("\n🎉 Database migration completed successfully!")
|
||||
|
||||
return True
|
||||
|
||||
except psycopg2.Error as e:
|
||||
print(f"❌ Database error: {e}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ Unexpected error: {e}")
|
||||
return False
|
||||
|
||||
def test_connection():
|
||||
"""Test database connection"""
|
||||
try:
|
||||
conn = psycopg2.connect(DATABASE_URL)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT version();")
|
||||
version = cursor.fetchone()[0]
|
||||
print(f"✅ Database connection successful")
|
||||
cursor.close()
|
||||
conn.close()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"❌ Database connection failed: {e}")
|
||||
print(f" Check your DATABASE_URL: {DATABASE_URL}")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("📍 QR Code System - Geolocation Migration")
|
||||
print("=" * 50)
|
||||
|
||||
# Test connection first
|
||||
if not test_connection():
|
||||
print("\n❌ Cannot connect to database. Please check:")
|
||||
print("1. PostgreSQL is running")
|
||||
print("2. Database credentials are correct")
|
||||
print("3. Database exists")
|
||||
sys.exit(1)
|
||||
|
||||
# Run migration
|
||||
success = add_location_columns()
|
||||
|
||||
if success:
|
||||
print("\n✅ Ready for geolocation integration!")
|
||||
print("\nNext steps:")
|
||||
print("1. Replace your qr_destination.html template")
|
||||
print("2. Replace your qr_destination.js file")
|
||||
print("3. Update your qr_checkin route in app.py")
|
||||
print("4. Restart your Flask application")
|
||||
print("5. Test geolocation on a mobile device")
|
||||
else:
|
||||
print("\n❌ Migration failed. Please check the errors above.")
|
||||
print("\nYou can also add the columns manually:")
|
||||
print("ALTER TABLE attendance_data ADD COLUMN latitude FLOAT;")
|
||||
print("ALTER TABLE attendance_data ADD COLUMN longitude FLOAT;")
|
||||
print("ALTER TABLE attendance_data ADD COLUMN accuracy FLOAT;")
|
||||
print("ALTER TABLE attendance_data ADD COLUMN altitude FLOAT;")
|
||||
print("ALTER TABLE attendance_data ADD COLUMN location_source VARCHAR(50) DEFAULT 'manual';")
|
||||
print("ALTER TABLE attendance_data ADD COLUMN address VARCHAR(255);")
|
||||
|
||||
print("\n" + "=" * 50)
|
||||
@@ -1,339 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Database Update Script for QR Code Management System
|
||||
Adds attendance tracking functionality to existing database
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from flask import Flask
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from sqlalchemy import text
|
||||
|
||||
def create_app():
|
||||
"""Create Flask application for database updates"""
|
||||
app = Flask(__name__)
|
||||
|
||||
# Database configuration
|
||||
database_url = os.environ.get('DATABASE_URL', 'postgresql://postgres:postgres1411@localhost/qr_management')
|
||||
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = database_url
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
app.config['SECRET_KEY'] = 'update-key-change-in-production'
|
||||
|
||||
return app
|
||||
|
||||
def add_attendance_table():
|
||||
"""Add attendance_data table to existing database"""
|
||||
|
||||
print("🔄 Adding attendance tracking functionality...")
|
||||
print("=" * 60)
|
||||
|
||||
app = create_app()
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
with app.app_context():
|
||||
try:
|
||||
# Create attendance_data table
|
||||
create_table_sql = """
|
||||
CREATE TABLE IF NOT EXISTS attendance_data (
|
||||
id SERIAL PRIMARY KEY,
|
||||
qr_code_id INTEGER NOT NULL REFERENCES qr_codes(id) ON DELETE CASCADE,
|
||||
employee_id VARCHAR(50) NOT NULL,
|
||||
check_in_date DATE NOT NULL,
|
||||
check_in_time TIME NOT NULL,
|
||||
device_info VARCHAR(200),
|
||||
user_agent TEXT,
|
||||
ip_address VARCHAR(45),
|
||||
location_name VARCHAR(100) NOT NULL,
|
||||
status VARCHAR(20) DEFAULT 'present',
|
||||
created_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
"""
|
||||
|
||||
db.session.execute(text(create_table_sql))
|
||||
print("✅ Created attendance_data table")
|
||||
|
||||
# Create indexes for better performance
|
||||
indexes_sql = [
|
||||
"CREATE INDEX IF NOT EXISTS idx_attendance_qr_code ON attendance_data(qr_code_id);",
|
||||
"CREATE INDEX IF NOT EXISTS idx_attendance_employee ON attendance_data(employee_id);",
|
||||
"CREATE INDEX IF NOT EXISTS idx_attendance_date ON attendance_data(check_in_date);",
|
||||
"CREATE INDEX IF NOT EXISTS idx_attendance_timestamp ON attendance_data(created_timestamp);"
|
||||
]
|
||||
|
||||
for index_sql in indexes_sql:
|
||||
db.session.execute(text(index_sql))
|
||||
|
||||
print("✅ Created database indexes")
|
||||
|
||||
# Add QR code URL field to qr_codes table if it doesn't exist
|
||||
add_url_field_sql = """
|
||||
ALTER TABLE qr_codes
|
||||
ADD COLUMN IF NOT EXISTS qr_url VARCHAR(255) UNIQUE;
|
||||
"""
|
||||
|
||||
db.session.execute(text(add_url_field_sql))
|
||||
print("✅ Added qr_url field to qr_codes table")
|
||||
|
||||
# Update existing QR codes with unique URLs
|
||||
update_urls_sql = """
|
||||
UPDATE qr_codes
|
||||
SET qr_url = CONCAT('qr-', id, '-', LOWER(REPLACE(REPLACE(name, ' ', '-'), '''', '')))
|
||||
WHERE qr_url IS NULL;
|
||||
"""
|
||||
|
||||
db.session.execute(text(update_urls_sql))
|
||||
print("✅ Generated URLs for existing QR codes")
|
||||
|
||||
# Create a view for attendance reporting
|
||||
create_view_sql = """
|
||||
CREATE OR REPLACE VIEW attendance_report AS
|
||||
SELECT
|
||||
ad.id,
|
||||
ad.employee_id,
|
||||
ad.check_in_date,
|
||||
ad.check_in_time,
|
||||
ad.device_info,
|
||||
ad.location_name,
|
||||
ad.status,
|
||||
ad.created_timestamp,
|
||||
qc.name as qr_code_name,
|
||||
qc.location as qr_location,
|
||||
qc.location_event,
|
||||
qc.location_address,
|
||||
u.full_name as qr_creator_name
|
||||
FROM attendance_data ad
|
||||
JOIN qr_codes qc ON ad.qr_code_id = qc.id
|
||||
JOIN users u ON qc.created_by = u.id
|
||||
ORDER BY ad.created_timestamp DESC;
|
||||
"""
|
||||
|
||||
db.session.execute(text(create_view_sql))
|
||||
print("✅ Created attendance_report view")
|
||||
|
||||
# Commit all changes
|
||||
db.session.commit()
|
||||
|
||||
print("\n🎉 Database update completed successfully!")
|
||||
print("\n📋 Changes Summary:")
|
||||
print(" - Added attendance_data table")
|
||||
print(" - Created performance indexes")
|
||||
print(" - Added qr_url field to qr_codes")
|
||||
print(" - Generated URLs for existing QR codes")
|
||||
print(" - Created attendance_report view")
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
print(f"❌ Error during database update: {str(e)}")
|
||||
print("\n🔧 Troubleshooting tips:")
|
||||
print(" 1. Ensure PostgreSQL is running")
|
||||
print(" 2. Check database connection string")
|
||||
print(" 3. Verify database user has CREATE permissions")
|
||||
sys.exit(1)
|
||||
|
||||
def create_sample_attendance():
|
||||
"""Create sample attendance data for testing"""
|
||||
|
||||
print("\n📦 Creating sample attendance data...")
|
||||
|
||||
app = create_app()
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
with app.app_context():
|
||||
try:
|
||||
# Get existing QR codes
|
||||
qr_codes_result = db.session.execute(text("SELECT id, name FROM qr_codes WHERE active_status = true LIMIT 3"))
|
||||
qr_codes = qr_codes_result.fetchall()
|
||||
|
||||
if not qr_codes:
|
||||
print(" ⚠️ No active QR codes found, skipping sample data creation")
|
||||
return
|
||||
|
||||
# Sample attendance data
|
||||
sample_data = [
|
||||
{
|
||||
'employee_id': 'EMP001',
|
||||
'device_info': 'iPhone 14 Pro - iOS 16.5',
|
||||
'status': 'present'
|
||||
},
|
||||
{
|
||||
'employee_id': 'EMP002',
|
||||
'device_info': 'Samsung Galaxy S23 - Android 13',
|
||||
'status': 'present'
|
||||
},
|
||||
{
|
||||
'employee_id': 'EMP003',
|
||||
'device_info': 'iPad Air - iOS 16.5',
|
||||
'status': 'present'
|
||||
}
|
||||
]
|
||||
|
||||
for i, qr_code in enumerate(qr_codes):
|
||||
if i < len(sample_data):
|
||||
sample = sample_data[i]
|
||||
|
||||
insert_sql = """
|
||||
INSERT INTO attendance_data
|
||||
(qr_code_id, employee_id, check_in_date, check_in_time, device_info, location_name, status)
|
||||
VALUES (:qr_id, :emp_id, CURRENT_DATE, CURRENT_TIME, :device, :location, :status)
|
||||
"""
|
||||
|
||||
db.session.execute(text(insert_sql), {
|
||||
'qr_id': qr_code[0],
|
||||
'emp_id': sample['employee_id'],
|
||||
'device': sample['device_info'],
|
||||
'location': qr_code[1],
|
||||
'status': sample['status']
|
||||
})
|
||||
|
||||
db.session.commit()
|
||||
print(f" ✅ Created {len(sample_data)} sample attendance records")
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
print(f" ❌ Failed to create sample data: {str(e)}")
|
||||
|
||||
def verify_database():
|
||||
"""Verify database changes were applied correctly"""
|
||||
|
||||
print("\n🔍 Verifying database changes...")
|
||||
|
||||
app = create_app()
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
with app.app_context():
|
||||
try:
|
||||
# Check if attendance_data table exists
|
||||
table_check = db.session.execute(text("""
|
||||
SELECT EXISTS (
|
||||
SELECT FROM information_schema.tables
|
||||
WHERE table_name = 'attendance_data'
|
||||
);
|
||||
"""))
|
||||
|
||||
if table_check.fetchone()[0]:
|
||||
print(" ✅ attendance_data table exists")
|
||||
|
||||
# Count records
|
||||
count_result = db.session.execute(text("SELECT COUNT(*) FROM attendance_data"))
|
||||
record_count = count_result.fetchone()[0]
|
||||
print(f" 📊 Found {record_count} attendance records")
|
||||
else:
|
||||
print(" ❌ attendance_data table not found")
|
||||
return False
|
||||
|
||||
# Check if qr_url field was added
|
||||
field_check = db.session.execute(text("""
|
||||
SELECT EXISTS (
|
||||
SELECT FROM information_schema.columns
|
||||
WHERE table_name = 'qr_codes' AND column_name = 'qr_url'
|
||||
);
|
||||
"""))
|
||||
|
||||
if field_check.fetchone()[0]:
|
||||
print(" ✅ qr_url field added to qr_codes table")
|
||||
|
||||
# Check how many QR codes have URLs
|
||||
url_count = db.session.execute(text("SELECT COUNT(*) FROM qr_codes WHERE qr_url IS NOT NULL"))
|
||||
url_records = url_count.fetchone()[0]
|
||||
print(f" 📊 {url_records} QR codes have generated URLs")
|
||||
else:
|
||||
print(" ❌ qr_url field not found in qr_codes table")
|
||||
return False
|
||||
|
||||
# Check if view exists
|
||||
view_check = db.session.execute(text("""
|
||||
SELECT EXISTS (
|
||||
SELECT FROM information_schema.views
|
||||
WHERE table_name = 'attendance_report'
|
||||
);
|
||||
"""))
|
||||
|
||||
if view_check.fetchone()[0]:
|
||||
print(" ✅ attendance_report view created")
|
||||
else:
|
||||
print(" ❌ attendance_report view not found")
|
||||
return False
|
||||
|
||||
print("\n✅ All database changes verified successfully!")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Verification failed: {str(e)}")
|
||||
return False
|
||||
|
||||
def rollback_changes():
|
||||
"""Rollback database changes if needed"""
|
||||
|
||||
print("\n⚠️ WARNING: This will remove all attendance tracking functionality!")
|
||||
confirm = input("Are you sure you want to rollback? Type 'ROLLBACK' to confirm: ")
|
||||
|
||||
if confirm != 'ROLLBACK':
|
||||
print("❌ Rollback cancelled")
|
||||
return
|
||||
|
||||
app = create_app()
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
with app.app_context():
|
||||
try:
|
||||
# Drop view
|
||||
db.session.execute(text("DROP VIEW IF EXISTS attendance_report"))
|
||||
print(" ✅ Dropped attendance_report view")
|
||||
|
||||
# Drop table
|
||||
db.session.execute(text("DROP TABLE IF EXISTS attendance_data"))
|
||||
print(" ✅ Dropped attendance_data table")
|
||||
|
||||
# Remove qr_url column
|
||||
db.session.execute(text("ALTER TABLE qr_codes DROP COLUMN IF EXISTS qr_url"))
|
||||
print(" ✅ Removed qr_url column")
|
||||
|
||||
db.session.commit()
|
||||
print("\n✅ Rollback completed successfully!")
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
print(f"❌ Error during rollback: {str(e)}")
|
||||
|
||||
def main():
|
||||
"""Main script entry point"""
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
command = sys.argv[1].lower()
|
||||
|
||||
if command == 'update':
|
||||
add_attendance_table()
|
||||
|
||||
# Ask if user wants sample data
|
||||
create_sample = input("\n❓ Would you like to create sample attendance data? (y/N): ").lower().strip()
|
||||
if create_sample in ['y', 'yes']:
|
||||
create_sample_attendance()
|
||||
|
||||
verify_database()
|
||||
|
||||
elif command == 'verify':
|
||||
verify_database()
|
||||
|
||||
elif command == 'rollback':
|
||||
rollback_changes()
|
||||
|
||||
elif command == 'sample':
|
||||
create_sample_attendance()
|
||||
|
||||
else:
|
||||
print("❌ Unknown command. Available commands:")
|
||||
print(" update - Add attendance tracking to database")
|
||||
print(" verify - Verify database changes")
|
||||
print(" rollback - Remove attendance tracking (DANGEROUS)")
|
||||
print(" sample - Create sample attendance data")
|
||||
else:
|
||||
# Default action is update
|
||||
add_attendance_table()
|
||||
verify_database()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,359 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Database Setup Script for QR Code Management System
|
||||
Handles database initialization, migrations, and sample data creation
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from flask import Flask
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from werkzeug.security import generate_password_hash
|
||||
|
||||
def create_app():
|
||||
"""Create Flask application for database setup"""
|
||||
app = Flask(__name__)
|
||||
|
||||
# Database configuration
|
||||
database_url = os.environ.get('DATABASE_URL', 'postgresql://postgres:postgres1411@localhost/qr_management')
|
||||
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = database_url
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
app.config['SECRET_KEY'] = 'setup-key-change-in-production'
|
||||
|
||||
return app
|
||||
|
||||
def create_models(db):
|
||||
"""Define database models"""
|
||||
|
||||
# User Model
|
||||
class User(db.Model):
|
||||
"""
|
||||
User model to manage system users with role-based access control
|
||||
"""
|
||||
__tablename__ = 'users'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
full_name = db.Column(db.String(100), nullable=False)
|
||||
email = db.Column(db.String(120), unique=True, nullable=False)
|
||||
username = db.Column(db.String(80), unique=True, nullable=False)
|
||||
password_hash = db.Column(db.String(256), nullable=False)
|
||||
role = db.Column(db.String(20), nullable=False, default='staff') # admin or staff
|
||||
created_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
|
||||
created_date = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
active_status = db.Column(db.Boolean, default=True)
|
||||
last_login_date = db.Column(db.DateTime, nullable=True)
|
||||
|
||||
# Relationships
|
||||
created_users = db.relationship('User', backref=db.backref('creator', remote_side=[id]))
|
||||
created_qr_codes = db.relationship('QRCode', backref='creator', lazy='dynamic')
|
||||
|
||||
def set_password(self, password):
|
||||
"""Hash and set user password"""
|
||||
self.password_hash = generate_password_hash(password)
|
||||
|
||||
def check_password(self, password):
|
||||
"""Verify user password"""
|
||||
from werkzeug.security import check_password_hash
|
||||
return check_password_hash(self.password_hash, password)
|
||||
|
||||
def is_admin(self):
|
||||
"""Check if user has admin privileges"""
|
||||
return self.role == 'admin'
|
||||
|
||||
# QR Code Model
|
||||
class QRCode(db.Model):
|
||||
"""
|
||||
QR Code model to manage QR code records and metadata
|
||||
"""
|
||||
__tablename__ = 'qr_codes'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(100), nullable=False)
|
||||
location = db.Column(db.String(100), nullable=False)
|
||||
location_address = db.Column(db.Text, nullable=False)
|
||||
location_event = db.Column(db.String(200), nullable=False)
|
||||
qr_code_image = db.Column(db.Text, nullable=False) # Base64 encoded image
|
||||
created_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
created_date = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
active_status = db.Column(db.Boolean, default=True)
|
||||
|
||||
return User, QRCode
|
||||
|
||||
def setup_database():
|
||||
"""
|
||||
Complete database setup including:
|
||||
- Table creation
|
||||
- Default admin user
|
||||
- Sample data (optional)
|
||||
"""
|
||||
|
||||
print("🚀 Starting QR Code Management System Database Setup...")
|
||||
print("=" * 60)
|
||||
|
||||
# Create Flask app and initialize database
|
||||
app = create_app()
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
with app.app_context():
|
||||
try:
|
||||
# Create models
|
||||
User, QRCode = create_models(db)
|
||||
|
||||
print("📊 Creating database tables...")
|
||||
db.create_all()
|
||||
print("✅ Database tables created successfully!")
|
||||
|
||||
# Create default admin user
|
||||
print("\n👤 Creating default admin user...")
|
||||
create_default_admin(db, User)
|
||||
|
||||
# Ask if user wants sample data
|
||||
create_sample = input("\n❓ Would you like to create sample QR codes? (y/N): ").lower().strip()
|
||||
if create_sample in ['y', 'yes']:
|
||||
create_sample_data(db, User, QRCode)
|
||||
|
||||
print("\n🎉 Database setup completed successfully!")
|
||||
print("\n📋 Setup Summary:")
|
||||
print(" - Database tables created")
|
||||
print(" - Default admin user created")
|
||||
print(" - Login credentials: admin / admin123")
|
||||
print(" - ⚠️ IMPORTANT: Change the default password after first login!")
|
||||
|
||||
if create_sample in ['y', 'yes']:
|
||||
print(" - Sample QR codes created")
|
||||
|
||||
print("\n🚀 You can now start the application with: python app.py")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error during database setup: {str(e)}")
|
||||
print("\n🔧 Troubleshooting tips:")
|
||||
print(" 1. Make sure PostgreSQL is running")
|
||||
print(" 2. Check your database connection string")
|
||||
print(" 3. Ensure the database exists")
|
||||
print(" 4. Verify database user permissions")
|
||||
sys.exit(1)
|
||||
|
||||
def create_default_admin(db, User):
|
||||
"""Create default admin user if it doesn't exist"""
|
||||
|
||||
# Check if admin user already exists
|
||||
admin = User.query.filter_by(username='admin').first()
|
||||
|
||||
if admin:
|
||||
print(" ℹ️ Admin user already exists, skipping creation")
|
||||
return
|
||||
|
||||
try:
|
||||
# Create default admin user
|
||||
admin_user = User(
|
||||
full_name='System Administrator',
|
||||
email='admin@qrmanager.local',
|
||||
username='admin',
|
||||
role='admin',
|
||||
active_status=True,
|
||||
created_date=datetime.utcnow()
|
||||
)
|
||||
admin_user.set_password('admin123') # Default password - should be changed
|
||||
|
||||
db.session.add(admin_user)
|
||||
db.session.commit()
|
||||
|
||||
print(" ✅ Default admin user created successfully!")
|
||||
print(" 📧 Email: admin@qrmanager.local")
|
||||
print(" 👤 Username: admin")
|
||||
print(" 🔑 Password: admin123")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Failed to create admin user: {str(e)}")
|
||||
db.session.rollback()
|
||||
raise
|
||||
|
||||
def create_sample_data(db, User, QRCode):
|
||||
"""Create sample QR codes for demonstration"""
|
||||
|
||||
print("\n📦 Creating sample data...")
|
||||
|
||||
# Get admin user
|
||||
admin = User.query.filter_by(username='admin').first()
|
||||
if not admin:
|
||||
print(" ❌ Admin user not found, cannot create sample data")
|
||||
return
|
||||
|
||||
# Sample QR codes data
|
||||
sample_qr_codes = [
|
||||
{
|
||||
'name': 'Conference Room A Check-in',
|
||||
'location': 'Conference Room A',
|
||||
'location_address': '123 Business Plaza, Suite 400, New York, NY 10001',
|
||||
'location_event': 'Weekly Team Meeting',
|
||||
},
|
||||
{
|
||||
'name': 'Main Lobby Registration',
|
||||
'location': 'Main Lobby',
|
||||
'location_address': '456 Corporate Center, Ground Floor, Chicago, IL 60601',
|
||||
'location_event': 'Annual Company Conference 2025',
|
||||
},
|
||||
{
|
||||
'name': 'Training Room B',
|
||||
'location': 'Training Room B',
|
||||
'location_address': '789 Innovation Hub, 2nd Floor, San Francisco, CA 94105',
|
||||
'location_event': 'Employee Onboarding Session',
|
||||
},
|
||||
{
|
||||
'name': 'Customer Service Desk',
|
||||
'location': 'Customer Service Counter',
|
||||
'location_address': '321 Service Plaza, Main Floor, Austin, TX 78701',
|
||||
'location_event': 'Customer Support Check-in',
|
||||
},
|
||||
{
|
||||
'name': 'Cafeteria Feedback Station',
|
||||
'location': 'Employee Cafeteria',
|
||||
'location_address': '654 Office Complex, Lower Level, Seattle, WA 98101',
|
||||
'location_event': 'Meal Feedback Collection',
|
||||
}
|
||||
]
|
||||
|
||||
try:
|
||||
# Import QR code generation function
|
||||
import qrcode
|
||||
import io
|
||||
import base64
|
||||
|
||||
for qr_data in sample_qr_codes:
|
||||
# Generate QR code image
|
||||
qr_content = f"Event: {qr_data['location_event']}\nLocation: {qr_data['location']}\nAddress: {qr_data['location_address']}"
|
||||
|
||||
# Create QR code
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
qr.add_data(qr_content)
|
||||
qr.make(fit=True)
|
||||
|
||||
# Generate image
|
||||
img = qr.make_image(fill_color="black", back_color="white")
|
||||
|
||||
# Convert to base64
|
||||
buffer = io.BytesIO()
|
||||
img.save(buffer, format='PNG')
|
||||
img_str = base64.b64encode(buffer.getvalue()).decode()
|
||||
|
||||
# Create QR code record
|
||||
qr_code = QRCode(
|
||||
name=qr_data['name'],
|
||||
location=qr_data['location'],
|
||||
location_address=qr_data['location_address'],
|
||||
location_event=qr_data['location_event'],
|
||||
qr_code_image=img_str,
|
||||
created_by=admin.id,
|
||||
created_date=datetime.utcnow(),
|
||||
active_status=True
|
||||
)
|
||||
|
||||
db.session.add(qr_code)
|
||||
|
||||
db.session.commit()
|
||||
print(f" ✅ Created {len(sample_qr_codes)} sample QR codes!")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Failed to create sample data: {str(e)}")
|
||||
db.session.rollback()
|
||||
raise
|
||||
|
||||
def reset_database():
|
||||
"""Reset database (drop all tables and recreate)"""
|
||||
|
||||
print("⚠️ WARNING: This will delete ALL data in the database!")
|
||||
confirm = input("Are you sure you want to reset the database? Type 'RESET' to confirm: ")
|
||||
|
||||
if confirm != 'RESET':
|
||||
print("❌ Database reset cancelled")
|
||||
return
|
||||
|
||||
app = create_app()
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
with app.app_context():
|
||||
try:
|
||||
# Create models
|
||||
User, QRCode = create_models(db)
|
||||
|
||||
print("🗑️ Dropping all tables...")
|
||||
db.drop_all()
|
||||
|
||||
print("📊 Recreating tables...")
|
||||
db.create_all()
|
||||
|
||||
print("✅ Database reset completed!")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error during database reset: {str(e)}")
|
||||
sys.exit(1)
|
||||
|
||||
def check_database_connection():
|
||||
"""Test database connectivity"""
|
||||
|
||||
print("🔍 Testing database connection...")
|
||||
|
||||
app = create_app()
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
with app.app_context():
|
||||
try:
|
||||
# Create models
|
||||
User, QRCode = create_models(db)
|
||||
|
||||
# Try to execute a simple query
|
||||
db.session.execute('SELECT 1').fetchone()
|
||||
print("✅ Database connection successful!")
|
||||
|
||||
# Check if tables exist
|
||||
from sqlalchemy import inspect
|
||||
inspector = inspect(db.engine)
|
||||
tables = inspector.get_table_names()
|
||||
|
||||
if 'users' in tables and 'qr_codes' in tables:
|
||||
print("✅ Required tables exist")
|
||||
|
||||
# Count records
|
||||
user_count = User.query.count()
|
||||
qr_count = QRCode.query.count()
|
||||
|
||||
print(f"📊 Database contains: {user_count} users, {qr_count} QR codes")
|
||||
else:
|
||||
print("⚠️ Some tables are missing - run setup to create them")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Database connection failed: {str(e)}")
|
||||
print("\n🔧 Check your database configuration:")
|
||||
print(f" Database URL: {app.config['SQLALCHEMY_DATABASE_URI']}")
|
||||
sys.exit(1)
|
||||
|
||||
def main():
|
||||
"""Main setup script entry point"""
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
command = sys.argv[1].lower()
|
||||
|
||||
if command == 'reset':
|
||||
reset_database()
|
||||
elif command == 'check':
|
||||
check_database_connection()
|
||||
elif command == 'setup':
|
||||
setup_database()
|
||||
else:
|
||||
print("❌ Unknown command. Available commands:")
|
||||
print(" setup - Set up database and create default data")
|
||||
print(" reset - Reset database (delete all data)")
|
||||
print(" check - Check database connection and status")
|
||||
else:
|
||||
# Default action is setup
|
||||
setup_database()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user