Initial commit: Parking Manager

Features:
- Manager-centric parking spot management
- Fair assignment algorithm (parking/presence ratio)
- Presence tracking calendar
- Closing days (specific & weekly recurring)
- Guarantees and exclusions
- Authelia/LLDAP integration for SSO

Stack:
- FastAPI backend
- SQLite database
- Vanilla JS frontend
- Docker deployment
This commit is contained in:
Stefano Manfredi
2025-11-26 23:37:50 +00:00
commit c74a0ed350
49 changed files with 9094 additions and 0 deletions

183
create_test_db.py Normal file
View File

@@ -0,0 +1,183 @@
"""
Create test database with sample data
Run: .venv/bin/python create_test_db.py
Manager-centric model:
- Managers own parking spots (manager_parking_quota)
- Each manager has a spot prefix (A, B, C...) for display names
- Offices are containers for employees (like LDAP groups)
LDAP Group Simulation:
- parking_admin: admin role
- parking_manager: manager role
- office groups (presales, design, operations): employee office assignment
"""
import uuid
from datetime import datetime, timezone
from database.connection import engine, SessionLocal
from database.models import Base, User, Office, OfficeMembership
from services.auth import hash_password
# Drop and recreate all tables for clean slate
Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)
db = SessionLocal()
now = datetime.now(timezone.utc).isoformat()
password_hash = hash_password("password123")
# Create offices (representing LDAP groups)
offices = [
Office(id="presales", name="Presales", location="Building A", created_at=now),
Office(id="design", name="Design", location="Building B", created_at=now),
Office(id="operations", name="Operations", location="Building C", created_at=now),
]
for office in offices:
db.add(office)
print(f"Created office: {office.name}")
db.commit()
# Create users
# LDAP groups simulation:
# admin: parking_admin, presales
# manager1: parking_manager, presales, design
# manager2: parking_manager, operations
# user1: presales
# user2: design
# user3: design
# user4: operations
# user5: operations
users_data = [
{
"id": "admin",
"email": "admin@example.com",
"name": "Admin User",
"role": "admin",
"office_id": "presales", # Primary office from LDAP groups
},
{
"id": "manager1",
"email": "manager1@example.com",
"name": "Alice Manager",
"role": "manager",
"office_id": "presales",
"manager_parking_quota": 3, # For 5 users: admin, alice, user1, user2, user3
"manager_spot_prefix": "A",
},
{
"id": "manager2",
"email": "manager2@example.com",
"name": "Bob Manager",
"role": "manager",
"office_id": "operations",
"manager_parking_quota": 2, # For 3 users: bob, user4, user5
"manager_spot_prefix": "B",
},
{
"id": "user1",
"email": "user1@example.com",
"name": "User One",
"role": "employee",
"office_id": "presales",
},
{
"id": "user2",
"email": "user2@example.com",
"name": "User Two",
"role": "employee",
"office_id": "design",
},
{
"id": "user3",
"email": "user3@example.com",
"name": "User Three",
"role": "employee",
"office_id": "design",
},
{
"id": "user4",
"email": "user4@example.com",
"name": "User Four",
"role": "employee",
"office_id": "operations",
},
{
"id": "user5",
"email": "user5@example.com",
"name": "User Five",
"role": "employee",
"office_id": "operations",
},
]
for data in users_data:
user = User(
id=data["id"],
email=data["email"],
password_hash=password_hash,
name=data["name"],
role=data["role"],
office_id=data.get("office_id"),
manager_parking_quota=data.get("manager_parking_quota", 0),
manager_spot_prefix=data.get("manager_spot_prefix"),
created_at=now
)
db.add(user)
print(f"Created user: {user.email} ({user.role})")
db.commit()
# Create office memberships for managers
# Manager 1 (Alice) manages Presales and Design
for office_id in ["presales", "design"]:
membership = OfficeMembership(
id=str(uuid.uuid4()),
user_id="manager1",
office_id=office_id,
created_at=now
)
db.add(membership)
print(f"Created membership: Alice -> {office_id}")
# Manager 2 (Bob) manages Operations
membership = OfficeMembership(
id=str(uuid.uuid4()),
user_id="manager2",
office_id="operations",
created_at=now
)
db.add(membership)
print(f"Created membership: Bob -> operations")
db.commit()
db.close()
print("\n" + "="*60)
print("Test database created successfully!")
print("="*60)
print("\nTest accounts (all use password: password123):")
print("-"*60)
print(f"{'Email':<25} {'Role':<10} {'Office':<12} {'Spots'}")
print("-"*60)
print(f"{'admin@example.com':<25} {'admin':<10} {'presales':<12}")
print(f"{'manager1@example.com':<25} {'manager':<10} {'presales':<12}")
print(f"{'manager2@example.com':<25} {'manager':<10} {'operations':<12}")
print(f"{'user1@example.com':<25} {'employee':<10} {'presales':<12}")
print(f"{'user2@example.com':<25} {'employee':<10} {'design':<12}")
print(f"{'user3@example.com':<25} {'employee':<10} {'design':<12}")
print(f"{'user4@example.com':<25} {'employee':<10} {'operations':<12}")
print(f"{'user5@example.com':<25} {'employee':<10} {'operations':<12}")
print("-"*60)
print("\nParking pools:")
print(" Alice (manager1): 3 spots (A1,A2,A3)")
print(" -> presales: admin, alice, user1")
print(" -> design: user2, user3")
print(" -> 5 users, 3 spots = 60% ratio target")
print()
print(" Bob (manager2): 2 spots (B1,B2)")
print(" -> operations: bob, user4, user5")
print(" -> 3 users, 2 spots = 67% ratio target")