Initial commit: Tablet lending system with user-tablet many-to-many relationship

- Database schema: tablets, users, loans (junction table)
- CLI app: minimal_app.py
- Web apps: app.py (Flask), simple_app.py (http.server)
- Features: loan management, search, user loans view, project notes
- Git structure: CONTRIBUTING.md, .gitignore

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
ijuanes 2026-06-03 10:43:17 +01:00
commit 8a8d2f02fa
25 changed files with 2885 additions and 0 deletions

296
minimal_app.py Normal file
View file

@ -0,0 +1,296 @@
#!/usr/bin/env python3
"""
Minimal Tablet Lending and Return Management System
Using only built-in Python modules
"""
import sqlite3
from datetime import datetime
def init_db():
"""Initialize database with required tables"""
conn = sqlite3.connect('tablets.db')
cursor = conn.cursor()
# Create tables
cursor.execute('''
CREATE TABLE IF NOT EXISTS tablets (
id INTEGER PRIMARY KEY AUTOINCREMENT,
brand TEXT NOT NULL,
model TEXT NOT NULL,
serial_number TEXT UNIQUE NOT NULL,
status TEXT DEFAULT 'available'
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
identification TEXT UNIQUE
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS loans (
id INTEGER PRIMARY KEY AUTOINCREMENT,
tablet_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
loan_date TEXT NOT NULL,
return_date TEXT,
status TEXT DEFAULT 'active',
FOREIGN KEY (tablet_id) REFERENCES tablets (id),
FOREIGN KEY (user_id) REFERENCES users (id)
)
''')
conn.commit()
conn.close()
def add_tablet(brand, model, serial_number):
"""Add a new tablet to inventory"""
conn = sqlite3.connect('tablets.db')
cursor = conn.cursor()
try:
cursor.execute('''
INSERT INTO tablets (brand, model, serial_number, status)
VALUES (?, ?, ?, 'available')
''', (brand, model, serial_number))
conn.commit()
print(f"✓ Added tablet: {brand} {model} ({serial_number})")
except sqlite3.IntegrityError:
print(f"✗ Error: Serial number {serial_number} already exists")
finally:
conn.close()
def add_user(name, identification):
"""Add a new user"""
conn = sqlite3.connect('tablets.db')
cursor = conn.cursor()
try:
cursor.execute('''
INSERT INTO users (name, identification)
VALUES (?, ?)
''', (name, identification))
conn.commit()
print(f"✓ Added user: {name} ({identification})")
except sqlite3.IntegrityError:
print(f"✗ Error: Identification {identification} already exists")
finally:
conn.close()
def loan_tablet(tablet_id, user_id):
"""Loan a tablet to a user"""
conn = sqlite3.connect('tablets.db')
cursor = conn.cursor()
# Check if tablet is available
cursor.execute("SELECT status FROM tablets WHERE id = ?", (tablet_id,))
result = cursor.fetchone()
if result and result[0] == 'available':
# Update tablet status
cursor.execute("UPDATE tablets SET status = 'loaned' WHERE id = ?", (tablet_id,))
# Create loan record
loan_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
cursor.execute('''
INSERT INTO loans (tablet_id, user_id, loan_date, status)
VALUES (?, ?, ?, 'active')
''', (tablet_id, user_id, loan_date))
conn.commit()
print(f"✓ Tablet {tablet_id} loaned to user {user_id}")
else:
print(f"✗ Error: Tablet {tablet_id} is not available for loan")
conn.close()
def return_tablet(loan_id):
"""Return a loaned tablet"""
conn = sqlite3.connect('tablets.db')
cursor = conn.cursor()
# Get loan information
cursor.execute("SELECT tablet_id FROM loans WHERE id = ? AND status = 'active'", (loan_id,))
loan = cursor.fetchone()
if loan:
tablet_id = loan[0]
# Update loan status and return date
return_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
cursor.execute('''
UPDATE loans SET status = 'returned', return_date = ? WHERE id = ?
''', (return_date, loan_id))
# Update tablet status
cursor.execute("UPDATE tablets SET status = 'available' WHERE id = ?", (tablet_id,))
conn.commit()
print(f"✓ Tablet returned for loan {loan_id}")
else:
print(f"✗ Error: Loan {loan_id} not found or already returned")
conn.close()
def show_available_tablets():
"""Show available tablets"""
conn = sqlite3.connect('tablets.db')
cursor = conn.cursor()
cursor.execute("SELECT id, brand, model, serial_number FROM tablets WHERE status = 'available'")
tablets = cursor.fetchall()
print("\n=== Available Tablets ===")
if tablets:
for tablet in tablets:
print(f"ID: {tablet[0]}, {tablet[1]} {tablet[2]} ({tablet[3]})")
else:
print("No available tablets")
conn.close()
def show_active_loans():
"""Show active loans"""
conn = sqlite3.connect('tablets.db')
cursor = conn.cursor()
cursor.execute('''
SELECT l.id, t.brand, t.model, t.serial_number, u.name, l.loan_date
FROM loans l
JOIN tablets t ON l.tablet_id = t.id
JOIN users u ON l.user_id = u.id
WHERE l.status = 'active'
''')
loans = cursor.fetchall()
print("\n=== Active Loans ===")
if loans:
for loan in loans:
print(f"Loan ID: {loan[0]}, Tablet: {loan[1]} {loan[2]} ({loan[3]}), Borrower: {loan[4]}, Loan Date: {loan[5]}")
else:
print("No active loans")
conn.close()
def show_loan_history():
"""Show complete loan history"""
conn = sqlite3.connect('tablets.db')
cursor = conn.cursor()
cursor.execute('''
SELECT l.id, t.brand, t.model, t.serial_number, u.name,
l.loan_date, l.return_date, l.status
FROM loans l
JOIN tablets t ON l.tablet_id = t.id
JOIN users u ON l.user_id = u.id
ORDER BY l.loan_date DESC
''')
loans = cursor.fetchall()
print("\n=== Loan History ===")
if loans:
for loan in loans:
return_date = loan[6] or 'Not returned'
print(f"Loan ID: {loan[0]}, Tablet: {loan[1]} {loan[2]} ({loan[3]}), Borrower: {loan[4]}")
print(f" Loan Date: {loan[5]}, Return Date: {return_date}, Status: {loan[7]}")
else:
print("No loan history")
conn.close()
def main():
"""Main menu"""
init_db()
print("=== Tablet Lending and Return Management System ===")
print("Using SQLite database: tablets.db")
while True:
print("\nMenu:")
print("1. Add Tablet")
print("2. Add User")
print("3. Loan Tablet")
print("4. Return Tablet")
print("5. Show Available Tablets")
print("6. Show Active Loans")
print("7. Show Loan History")
print("8. Exit")
choice = input("Enter your choice (1-8): ")
if choice == '1':
print("\n=== Add Tablet ===")
brand = input("Brand: ")
model = input("Model: ")
serial_number = input("Serial Number: ")
add_tablet(brand, model, serial_number)
elif choice == '2':
print("\n=== Add User ===")
name = input("Name: ")
identification = input("Identification: ")
add_user(name, identification)
elif choice == '3':
print("\n=== Loan Tablet ===")
show_available_tablets()
show_users()
tablet_id = input("Enter Tablet ID to loan: ")
user_id = input("Enter User ID: ")
try:
loan_tablet(int(tablet_id), int(user_id))
except ValueError:
print("✗ Error: Invalid ID format")
elif choice == '4':
print("\n=== Return Tablet ===")
show_active_loans()
loan_id = input("Enter Loan ID to return: ")
try:
return_tablet(int(loan_id))
except ValueError:
print("✗ Error: Invalid Loan ID format")
elif choice == '5':
show_available_tablets()
elif choice == '6':
show_active_loans()
elif choice == '7':
show_loan_history()
elif choice == '8':
print("Goodbye!")
break
else:
print("✗ Invalid choice. Please try again.")
def show_users():
"""Show available users"""
conn = sqlite3.connect('tablets.db')
cursor = conn.cursor()
cursor.execute("SELECT id, name, identification FROM users")
users = cursor.fetchall()
print("\n=== Available Users ===")
if users:
for user in users:
print(f"ID: {user[0]}, {user[1]} ({user[2]})")
else:
print("No users available")
conn.close()
if __name__ == '__main__':
main()