#!/usr/bin/env python3 """ Simple Tablet Lending and Return Management System Using only built-in Python modules (no Flask required) """ import sqlite3 import os from datetime import datetime from http.server import HTTPServer, BaseHTTPRequestHandler from urllib.parse import parse_qs, urlparse import json # Database setup DATABASE = 'tablets.db' def get_db(): """Get database connection""" conn = sqlite3.connect(DATABASE) conn.row_factory = sqlite3.Row return conn def init_db(): """Initialize database with required tables""" with get_db() as conn: cursor = conn.cursor() # Create tablets table 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', notes TEXT ) ''') # Create users table cursor.execute(''' CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT, phone TEXT, identification TEXT UNIQUE ) ''') # Create loans table 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) ) ''') # Create non_loanable_devices table cursor.execute(''' CREATE TABLE IF NOT EXISTS non_loanable_devices ( id INTEGER PRIMARY KEY AUTOINCREMENT, brand TEXT NOT NULL, model TEXT NOT NULL, serial_number TEXT UNIQUE NOT NULL, device_type TEXT NOT NULL, location TEXT, status TEXT DEFAULT 'available', notes TEXT, purchase_date TEXT, purchase_cost REAL ) ''') conn.commit() class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): def _set_headers(self, content_type="text/html"): self.send_response(200) self.send_header('Content-type', content_type) self.end_headers() def _send_html(self, content): self._set_headers() self.wfile.write(content.encode('utf-8')) def _send_json(self, data): self._set_headers(content_type="application/json") self.wfile.write(json.dumps(data).encode('utf-8')) def _parse_form_data(self): content_length = int(self.headers['Content-Length']) post_data = self.rfile.read(content_length) return parse_qs(post_data.decode('utf-8')) def do_GET(self): parsed_path = urlparse(self.path) if parsed_path.path == '/': self._handle_index() elif parsed_path.path == '/add_tablet': self._handle_add_tablet_form() elif parsed_path.path == '/add_user': self._handle_add_user_form() elif parsed_path.path == '/loan_tablet': self._handle_loan_tablet_form() elif parsed_path.path == '/history': self._handle_history() elif parsed_path.path.startswith('/return_tablet/'): self._handle_return_tablet(parsed_path.path) else: self._send_html("

404 Not Found

") def do_POST(self): parsed_path = urlparse(self.path) if parsed_path.path == '/add_tablet': self._handle_add_tablet() elif parsed_path.path == '/add_user': self._handle_add_user() elif parsed_path.path == '/loan_tablet': self._handle_loan_tablet() else: self._send_html("

404 Not Found

") def _handle_index(self): with get_db() as conn: cursor = conn.cursor() # Get available tablets cursor.execute("SELECT * FROM tablets WHERE status = 'available'") available_tablets = cursor.fetchall() # Get active loans 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' ''') active_loans = cursor.fetchall() html = f""" Tablet Management System

Tablet Management System

Available Tablets

""" if available_tablets: for tablet in available_tablets: html += f""" """ else: html += "" html += """
Brand Model Serial Number Notes
{tablet['brand']} {tablet['model']} {tablet['serial_number']} {tablet['notes'] or '-'}
No available tablets.

Active Loans

""" if active_loans: for loan in active_loans: html += f""" """ else: html += "" html += """
Tablet Serial Number Borrower Loan Date Actions
{loan['brand']} {loan['model']} {loan['serial_number']} {loan['name']} {loan['loan_date']} Return
No active loans.
""" self._send_html(html) def _handle_add_tablet_form(self): html = """ Add Tablet

Add New Tablet

""" self._send_html(html) def _handle_add_tablet(self): form_data = self._parse_form_data() brand = form_data['brand'][0] model = form_data['model'][0] serial_number = form_data['serial_number'][0] notes = form_data.get('notes', [''])[0] try: with get_db() as conn: cursor = conn.cursor() cursor.execute(''' INSERT INTO tablets (brand, model, serial_number, status, notes) VALUES (?, ?, ?, 'available', ?) ''', (brand, model, serial_number, notes)) conn.commit() self.send_response(303) self.send_header('Location', '/') self.end_headers() except sqlite3.IntegrityError: self._send_html("

Error: Serial number already exists!

Try again

") def _handle_add_user_form(self): html = """ Add User

Add New User

""" self._send_html(html) def _handle_add_user(self): form_data = self._parse_form_data() name = form_data['name'][0] email = form_data.get('email', [''])[0] phone = form_data.get('phone', [''])[0] identification = form_data['identification'][0] try: with get_db() as conn: cursor = conn.cursor() cursor.execute(''' INSERT INTO users (name, email, phone, identification) VALUES (?, ?, ?, ?) ''', (name, email, phone, identification)) conn.commit() self.send_response(303) self.send_header('Location', '/') self.end_headers() except sqlite3.IntegrityError: self._send_html("

Error: Identification already exists!

Try again

") def _handle_loan_tablet_form(self): with get_db() as conn: cursor = conn.cursor() cursor.execute("SELECT * FROM tablets WHERE status = 'available'") available_tablets = cursor.fetchall() cursor.execute("SELECT * FROM users") users = cursor.fetchall() html = """ Loan Tablet

Loan Tablet

""" self._send_html(html) def _handle_loan_tablet(self): form_data = self._parse_form_data() tablet_id = form_data['tablet_id'][0] user_id = form_data['user_id'][0] with get_db() as conn: cursor = conn.cursor() # 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() self.send_response(303) self.send_header('Location', '/') self.end_headers() def _handle_return_tablet(self, path): loan_id = path.split('/')[-1] with get_db() as conn: cursor = conn.cursor() # Get loan information cursor.execute("SELECT tablet_id FROM loans WHERE id = ?", (loan_id,)) loan = cursor.fetchone() if loan: tablet_id = loan['tablet_id'] # 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() self.send_response(303) self.send_header('Location', '/') self.end_headers() def _handle_history(self): with get_db() as conn: 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() html = """ Loan History

Loan History

""" if loans: for loan in loans: html += f""" """ else: html += "" html += """
Tablet Serial Number Borrower Loan Date Return Date Status
{loan['brand']} {loan['model']} {loan['serial_number']} {loan['name']} {loan['loan_date']} {loan['return_date'] or '-'} {loan['status']}
No loan history available.
""" self._send_html(html) def run_server(): """Run the HTTP server""" server_address = ('', 8000) httpd = HTTPServer(server_address, SimpleHTTPRequestHandler) print(f"Server running on http://localhost:8000") print("Press Ctrl+C to stop the server") httpd.serve_forever() if __name__ == '__main__': # Initialize database init_db() # Run the server run_server()