diff --git a/README.md b/README.md
index 4a75b92..58fab68 100644
--- a/README.md
+++ b/README.md
@@ -10,16 +10,15 @@ A simple SQLite-based system for managing tablet lending and returns.
- **Return Management**: Record when tablets are returned
- **History Tracking**: Complete history of all loans and returns
- **User Loans View**: See all tablets loaned to each user (demonstrates one-to-many relationship)
-- **Non-Loanable Devices**: Track inventory devices that cannot be loaned (e.g., projectors, monitors)
- **Project Notes**: Markdown editor for development documentation
## Files
-- `minimal_app.py` - Interactive command-line application (includes non-loanable device management)
+- `minimal_app.py` - Interactive command-line application
- `test_app.py` - Test script that demonstrates functionality
-- `tablets.db` - SQLite database (created automatically, includes non_loanable_devices table)
-- `simple_app.py` - Web-based version (requires Flask, includes non-loanable device management)
-- `app.py` - Alternative web version (requires Flask, includes non-loanable device management)
+- `tablets.db` - SQLite database (created automatically)
+- `simple_app.py` - Web-based version (requires Flask)
+- `app.py` - Alternative web version (requires Flask)
## Quick Start
@@ -145,7 +144,6 @@ python3 app.py
- **Loan Tablet**: Loan a tablet to a user (with search for large datasets)
- **User Loans**: View all tablets loaned to each user - demonstrates the **one-to-many relationship** (one user, multiple tablets)
- **Loan History**: Complete history of all loan and return transactions
-- **Non-Loanable Devices**: Manage inventory of devices that cannot be loaned (add, edit, delete, view)
- **Project Management**: Markdown editor for development notes (saved to `notes_development/project_notes.md`)
## Database Backup
@@ -155,17 +153,6 @@ To backup your data:
cp tablets.db tablets_backup_$(date +%Y%m%d).db
```
-## Version Control
-
-This project uses Git for version control with the following structure:
-
-- `master` - Production-ready releases
-- `develop` - Integration branch for features
-- `feature/*` - Individual feature branches
-- `hotfix/*` - Urgent bug fixes
-
-See `CONTRIBUTING.md` for detailed workflow and commit conventions.
-
## License
This is a simple educational project. Feel free to use and modify it as needed.
\ No newline at end of file
diff --git a/REQUIREMENTS.md b/REQUIREMENTS.md
deleted file mode 100644
index f0c6929..0000000
--- a/REQUIREMENTS.md
+++ /dev/null
@@ -1,221 +0,0 @@
-# Requisitos del Sistema de Gestión de Préstamos de Tablets
-
-## Descripción General
-
-El sistema debe permitir la gestión del préstamo y devolución de dispositivos tablets entre un inventario y un conjunto de usuarios. El enfoque principal es el seguimiento del estado de cada dispositivo y su relación con los usuarios que los han tomado prestados.
-
----
-## Requisitos Faltantes
-
-### Gestión de dispositivos no prestables
-
-✅ **IMPLEMENTADO** - El sistema ahora permite:
-- Registrar nuevos dispositivos no prestables en un inventario separado (tabla `non_loanable_devices`)
-- Gestionar dispositivos no prestables a través de:
- - Interfaz web (app.py): /non_loanable_devices, /add_non_loanable_device, /edit_non_loanable_device, /delete_non_loanable_device
- - Interfaz CLI (minimal_app.py): Opciones 8, 9, 10 del menú
-- La implementación utiliza una tabla separada en la misma base de datos con los siguientes campos:
- - brand, model, serial_number (único), device_type, location, status, notes, purchase_date, purchase_cost
-
-## Requisitos Funcionales
-
-### Gestión de Dispositivos
-
-El sistema debe permitir:
-- Registrar nuevos dispositivos en el inventario
-- Identificar cada dispositivo de manera única
-- Almacenar información descriptiva de cada dispositivo (marca, modelo, número de serie)
-- Consultar el estado actual de cada dispositivo (disponible, prestado)
-
-### Gestión de Usuarios
-
-El sistema debe permitir:
-- Registrar nuevos usuarios
-- Identificar cada usuario de manera única
-- Almacenar información de contacto básica (nombre, identificación)
-- Consultar la información de los usuarios registrados
-
-### Gestión de Préstamos
-
-El sistema debe permitir:
-- Asignar un dispositivo disponible a un usuario
-- Registrar la fecha y hora del préstamo
-- Registrar la fecha y hora de la devolución
-- Consultar el historial de préstamos de un dispositivo
-- Consultar el historial de préstamos de un usuario
-- Visualizar todos los dispositivos actualmente prestados
-
-### Consulta y Reportes
-
-El sistema debe permitir:
-- Buscar dispositivos por cualquier atributo (marca, modelo, número de serie)
-- Buscar usuarios por cualquier atributo (nombre, identificación)
-- Filtrar préstamos por estado (activos, finalizados)
-- Filtrar préstamos por dispositivo
-- Filtrar préstamos por usuario
-- Ver el historial completo de préstamos y devoluciones
-
----
-
-## Modelo de Datos
-
-### Entidades Principales
-
-1. **Dispositivo**
- - Identificador único
- - Marca
- - Modelo
- - Número de serie (único)
- - Estado (disponible, prestado)
-
-2. **Usuario**
- - Identificador único
- - Nombre
- - Identificación (única)
-
-3. **Préstamo**
- - Identificador único
- - Dispositivo asociado
- - Usuario asociado
- - Fecha de préstamo
- - Fecha de devolución (opcional)
- - Estado (activo, finalizado)
-
-### Relaciones
-
-- Un **usuario** puede tener **múltiples préstamos** (relación uno a muchos)
-- Un **dispositivo** solo puede estar en **un préstamo activo** a la vez
-- Un **préstamo** relaciona exactamente un dispositivo con un usuario
-- El historial de préstamos permite rastrear todos los movimientos de cada dispositivo
-
-### Reglas de Negocio
-
-1. Un dispositivo en estado "prestado" no puede ser prestado a otro usuario
-2. Un préstamo finalizado debe registrar fecha de devolución
-3. La identificación de dispositivos y usuarios debe ser única
-4. Al devolver un dispositivo, este vuelve al estado "disponible"
-
----
-
-## Flujos de Trabajo
-
-### Registro de un Nuevo Dispositivo
-
-1. El sistema solicita la información del dispositivo (marca, modelo, número de serie)
-2. El sistema valida que el número de serie no esté registrado
-3. El sistema registra el dispositivo con estado "disponible"
-4. El sistema confirma el registro
-
-### Registro de un Nuevo Usuario
-
-1. El sistema solicita la información del usuario (nombre, identificación)
-2. El sistema valida que la identificación no esté registrada
-3. El sistema registra el usuario
-4. El sistema confirma el registro
-
-### Préstamo de un Dispositivo
-
-1. El sistema muestra los dispositivos disponibles
-2. El usuario selecciona un dispositivo
-3. El sistema muestra los usuarios registrados
-4. El usuario selecciona un usuario
-5. El sistema registra el préstamo con:
- - Dispositivo seleccionado
- - Usuario seleccionado
- - Fecha y hora actual
- - Estado "activo"
-6. El sistema actualiza el estado del dispositivo a "prestado"
-7. El sistema confirma el préstamo
-
-### Devolución de un Dispositivo
-
-1. El sistema muestra los préstamos activos
-2. El usuario selecciona un préstamo
-3. El sistema registra la fecha y hora de devolución
-4. El sistema actualiza el estado del préstamo a "finalizado"
-5. El sistema actualiza el estado del dispositivo a "disponible"
-6. El sistema confirma la devolución
-
-### Consulta de Préstamos por Usuario
-
-1. El sistema muestra la lista de usuarios
-2. El usuario selecciona un usuario
-3. El sistema muestra:
- - Dispositivos actualmente prestados (préstamos activos)
- - Historial de préstamos pasados (opcional: expandible)
-4. El sistema permite buscar por cualquier campo
-
----
-
-## Requisitos No Funcionales
-
-### Usabilidad
-
-- La interfaz debe permitir búsqueda eficiente en listas grandes (500+ elementos)
-- La visualización de información debe ser clara y organizada
-- Los estados deben ser fácilmente identificables
-- Las acciones principales deben ser accesibles
-
-### Escalabilidad
-
-- El diseño debe soportar un crecimiento en el número de dispositivos y usuarios
-- La búsqueda debe ser eficiente
-- El historial debe ser consultable sin afectar el rendimiento
-
-### Mantenibilidad
-
-- La estructura de datos debe ser clara
-- Las relaciones entre entidades deben estar bien definidas
-- Los flujos de trabajo deben estar documentados
-
----
-
-## Diseño de Interfaz (Conceptual)
-
-### Vistas Principales
-
-1. **Vista de Inventario**
- - Lista de dispositivos
- - Filtros por estado
- - Búsqueda
-
-2. **Vista de Usuarios**
- - Lista de usuarios
- - Búsqueda
-
-3. **Vista de Préstamos Activos**
- - Lista de préstamos en curso
- - Filtros por dispositivo/usuario
- - Acciones: devolver dispositivo
-
-4. **Vista de Historial**
- - Lista completa de préstamos
- - Filtros por fecha, usuario, dispositivo, estado
- - Detalles de cada préstamo
-
-5. **Vista de Préstamos por Usuario**
- - Lista de usuarios
- - Para cada usuario: dispositivos actualmente prestados
- - Opcional: historial de préstamos pasados (expandible)
-
-### Elementos de Interacción
-
-- Campos de búsqueda en todas las listas
-- Botones de acción claros (Prestar, Devolver, Registrar)
-- Indicadores visuales de estado (colores, iconos)
-- Confirmación de acciones críticas
-
----
-
-## Notas de Implementación
-
-Este documento describe los requisitos a nivel de diseño. La implementación específica (lenguaje de programación, base de datos, framework, arquitectura) queda a criterio del equipo de desarrollo y puede variar según las necesidades técnicas.
-
-Los detalles técnicos como:
-- Tecnologías específicas
-- Estructura de base de datos física
-- APIs
-- Autenticación
-- Despliegue
-
-Deberán ser definidos en la fase de diseño técnico y pueden evolucionar sin afectar los requisitos funcionales descritos aquí.
diff --git a/TECHNICAL_SPECIFICATIONS.md b/TECHNICAL_SPECIFICATIONS.md
deleted file mode 100644
index 8a17aef..0000000
--- a/TECHNICAL_SPECIFICATIONS.md
+++ /dev/null
@@ -1,149 +0,0 @@
-# Especificaciones Técnicas
-
-Documento complementario a `REQUIREMENTS.md` con propuestas concretas de implementación técnica.
-
----
-
-## 1. Concurrencia en Base de Datos
-
-| Opción | Descripción | Ventajas | Desventajas |
-|--------|-------------|---------|-------------|
-| **SQLite + WAL** | Modo Write-Ahead Logging | Zero-config, embebido, buena para <100 conexiones | Limitado a 1 escritor simultáneo |
-| **PostgreSQL** | Base de datos relacional | Concurrencia completa, transacciones ACID | Requiere servidor |
-| **Transacciones** | Aislamiento READ COMMITTED | Previene lecturas sucias | Bloqueos temporales |
-| **Locking optimista** | Versión de fila en actualizaciones | Sin bloqueos | Conflictos requieren reintento |
-
-**Recomendación**: SQLite con WAL para prototipos, PostgreSQL para producción. Usar transacciones para operaciones críticas (préstamo/devolución).
-
----
-
-## 2. Autenticación Básica
-
-| Opción | Descripción | Complejidad |
-|--------|-------------|-------------|
-| **Sesiones (Flask)** | Cookies firmadas | Baja |
-| **JWT** | Tokens sin estado | Media |
-| **OAuth 2.0** | Delegación a proveedores | Alta |
-| **Basic Auth** | HTTP Basic Authentication | Mínima |
-
-**Flujo mínimo**:
-```
-Login (user/pass) → Session/JWT → Middleware verifica rol → Acceso a endpoints
-```
-
-**Roles sugeridos**:
-- `admin`: CRUD completo, gestión de usuarios
-- `staff`: Préstamos/devoluciones
-- `viewer`: Solo consulta
-
----
-
-## 3. Separación Frontend/Backend
-
-| Arquitectura | Descripción | Stack Ejemplo |
-|--------------|-------------|---------------|
-| **Monolítica + Templates** | Servidor renderiza HTML | Flask+Jinja2, Django |
-| **API + SPA** | Backend API, frontend dinámico | FastAPI + React/Vue |
-| **API + SSR** | Backend API + renderizado servidor | Next.js + API |
-| **Microservicios** | Servicios independientes | Backend API + Frontend estático |
-
-**Para este proyecto**:
-- **Opción A**: Flask + Jinja2 (simple, suficiente para requisitos)
-- **Opción B**: FastAPI + React (escalable, separable)
-
----
-
-## 4. Búsqueda Eficiente (500+ elementos)
-
-| Opción | Descripción | Implementación |
-|--------|-------------|----------------|
-| **Índices DB** | B-tree en columnas buscadas | `CREATE INDEX idx_brand ON tablets(brand)` |
-| **Búsqueda full-text** | Búsqueda en texto | SQLite FTS5, PostgreSQL tsvector |
-| **Filtrado cliente** | JavaScript filtra datos | Ideal para <2000 elementos |
-| **Paginación** | Dividir resultados | `LIMIT 50 OFFSET 0` |
-
-**Recomendación**: Índices en `serial_number`, `brand`, `model`, `user.name`, `user.identification`.
-
----
-
-## 5. Estructura de Proyecto Propuesta
-
-```
-project/
-├── backend/
-│ ├── models/ # Entidades (Device, User, Loan)
-│ ├── services/ # Lógica de negocio
-│ ├── repositories/ # Acceso a datos
-│ ├── routes/ # Endpoints/API
-│ └── app.py # Configuración
-├── frontend/ # Opcional para opción B
-│ ├── public/
-│ └── src/
-├── migrations/ # Control de cambios DB
-├── tests/
-└── docs/
-```
-
----
-
-## 6. Decisiones Clave por Tomar
-
-| Decisión | Opciones | Impacto |
-|----------|----------|---------|
-| Base de datos | SQLite / PostgreSQL | Concurrencia, despliegue |
-| Autenticación | Sesiones / JWT / Ninguna | Seguridad, complejidad |
-| Frontend | Templates / SPA / Ninguno | Experiencia usuario |
-| Despliegue | Local / Docker / Cloud | Escalabilidad |
-
----
-
-## 7. Ejemplo de Implementación Mínima (Pseudocódigo)
-
-```python
-# modelos.py
-class Device:
- id: int (PK)
- serial_number: str (unique)
- status: str (available/loaned)
- loans: List[Loan] (one-to-many)
-
-class User:
- id: int (PK)
- identification: str (unique)
- loans: List[Loan] (one-to-many)
-
-class Loan:
- id: int (PK)
- device_id: int (FK)
- user_id: int (FK)
- loan_date: datetime
- return_date: datetime (nullable)
- status: str (active/returned)
-
-# servicios/loan_service.py
-def loan_device(device_id: int, user_id: int) -> Loan:
- with transaction(): # Atomicidad
- device = get_device_for_update(device_id)
- if device.status != 'available':
- raise DeviceNotAvailableError()
-
- loan = Loan.create(
- device_id=device_id,
- user_id=user_id,
- loan_date=now(),
- status='active'
- )
- device.status = 'loaned'
- return loan
-```
-
----
-
-## 8. Consideraciones Adicionales
-
-- **Validaciones**: Únicas (serial_number, identification) a nivel de base de datos
-- **Auditoría**: Campos `created_at`, `updated_at` en todas las entidades
-- **Backups**: Script para exportar base de datos periódicamente
-- **Logging**: Registrar préstamos/devoluciones para auditoría
-- **Versionado API**: `/api/v1/...` para compatibilidad futura
-- **Pruebas**: Cubrir flujos críticos (préstamo con dispositivo no disponible, devolución de préstamo inexistente)
diff --git a/app.py b/app.py
index 7dfba4d..a5332b7 100644
--- a/app.py
+++ b/app.py
@@ -63,22 +63,6 @@ def init_db():
)
''')
- # Create non_loanable_devices table for devices that cannot be loaned
- 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()
@app.route('/')
@@ -335,99 +319,6 @@ def user_loans():
return render_template('user_loans.html', users_with_loans=user_loans_list)
-@app.route('/non_loanable_devices')
-def non_loanable_devices():
- """Show all non-loanable devices"""
- with get_db() as conn:
- cursor = conn.cursor()
- cursor.execute("SELECT * FROM non_loanable_devices ORDER BY device_type, brand, model")
- devices = cursor.fetchall()
-
- return render_template('non_loanable_devices.html', devices=devices)
-
-
-@app.route('/add_non_loanable_device', methods=['GET', 'POST'])
-def add_non_loanable_device():
- """Add a new non-loanable device to inventory"""
- if request.method == 'POST':
- brand = request.form['brand']
- model = request.form['model']
- serial_number = request.form['serial_number']
- device_type = request.form['device_type']
- location = request.form['location']
- notes = request.form['notes']
- purchase_date = request.form.get('purchase_date', '')
- purchase_cost = request.form.get('purchase_cost', '')
-
- try:
- with get_db() as conn:
- cursor = conn.cursor()
- cursor.execute('''
- INSERT INTO non_loanable_devices
- (brand, model, serial_number, device_type, location, status, notes, purchase_date, purchase_cost)
- VALUES (?, ?, ?, ?, ?, 'available', ?, ?, ?)
- ''', (brand, model, serial_number, device_type, location, notes, purchase_date, purchase_cost))
- conn.commit()
- flash('Non-loanable device added successfully!', 'success')
- except sqlite3.IntegrityError:
- flash('Error: Serial number already exists!', 'error')
-
- return redirect(url_for('non_loanable_devices'))
-
- return render_template('add_non_loanable_device.html')
-
-
-@app.route('/edit_non_loanable_device/', methods=['GET', 'POST'])
-def edit_non_loanable_device(device_id):
- """Edit a non-loanable device"""
- with get_db() as conn:
- cursor = conn.cursor()
- cursor.execute("SELECT * FROM non_loanable_devices WHERE id = ?", (device_id,))
- device = cursor.fetchone()
-
- if not device:
- flash('Error: Device not found!', 'error')
- return redirect(url_for('non_loanable_devices'))
-
- if request.method == 'POST':
- brand = request.form['brand']
- model = request.form['model']
- serial_number = request.form['serial_number']
- device_type = request.form['device_type']
- location = request.form['location']
- status = request.form['status']
- notes = request.form['notes']
- purchase_date = request.form.get('purchase_date', '')
- purchase_cost = request.form.get('purchase_cost', '')
-
- try:
- cursor.execute('''
- UPDATE non_loanable_devices SET
- brand = ?, model = ?, serial_number = ?, device_type = ?,
- location = ?, status = ?, notes = ?, purchase_date = ?, purchase_cost = ?
- WHERE id = ?
- ''', (brand, model, serial_number, device_type, location, status, notes, purchase_date, purchase_cost, device_id))
- conn.commit()
- flash('Device updated successfully!', 'success')
- return redirect(url_for('non_loanable_devices'))
- except sqlite3.IntegrityError:
- flash('Error: Serial number already exists!', 'error')
-
- return render_template('edit_non_loanable_device.html', device=device)
-
-
-@app.route('/delete_non_loanable_device/')
-def delete_non_loanable_device(device_id):
- """Delete a non-loanable device"""
- with get_db() as conn:
- cursor = conn.cursor()
- cursor.execute("DELETE FROM non_loanable_devices WHERE id = ?", (device_id,))
- conn.commit()
- flash('Device deleted successfully!', 'success')
-
- return redirect(url_for('non_loanable_devices'))
-
-
if __name__ == '__main__':
# Initialize database
init_db()
diff --git a/gestiontablets.sh b/gestiontablets.sh
deleted file mode 100644
index 1d4b29d..0000000
--- a/gestiontablets.sh
+++ /dev/null
@@ -1 +0,0 @@
-vibe --resume fa1bb230
diff --git a/minimal_app.py b/minimal_app.py
index 381a26d..ff0295a 100644
--- a/minimal_app.py
+++ b/minimal_app.py
@@ -44,22 +44,6 @@ def init_db():
)
''')
- # 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()
conn.close()
@@ -218,59 +202,6 @@ def show_loan_history():
conn.close()
-
-def add_non_loanable_device(brand, model, serial_number, device_type, location='', notes='', purchase_date='', purchase_cost=None):
- """Add a new non-loanable device to inventory"""
- conn = sqlite3.connect('tablets.db')
- cursor = conn.cursor()
-
- try:
- cursor.execute('''
- INSERT INTO non_loanable_devices
- (brand, model, serial_number, device_type, location, status, notes, purchase_date, purchase_cost)
- VALUES (?, ?, ?, ?, ?, 'available', ?, ?, ?)
- ''', (brand, model, serial_number, device_type, location, notes, purchase_date, purchase_cost))
- conn.commit()
- print(f"✓ Added non-loanable device: {brand} {model} ({serial_number}) - Type: {device_type}")
- except sqlite3.IntegrityError:
- print(f"✗ Error: Serial number {serial_number} already exists")
- finally:
- conn.close()
-
-
-def show_non_loanable_devices():
- """Show all non-loanable devices"""
- conn = sqlite3.connect('tablets.db')
- cursor = conn.cursor()
-
- cursor.execute("SELECT id, brand, model, serial_number, device_type, location, status FROM non_loanable_devices")
- devices = cursor.fetchall()
-
- print("\n=== Non-Loanable Devices ===")
- if devices:
- for device in devices:
- print(f"ID: {device[0]}, Type: {device[4]}, {device[1]} {device[2]} ({device[3]}), Location: {device[5] or 'N/A'}, Status: {device[6]}")
- else:
- print("No non-loanable devices")
-
- conn.close()
-
-
-def delete_non_loanable_device(device_id):
- """Delete a non-loanable device"""
- conn = sqlite3.connect('tablets.db')
- cursor = conn.cursor()
-
- cursor.execute("DELETE FROM non_loanable_devices WHERE id = ?", (device_id,))
- conn.commit()
-
- if cursor.rowcount > 0:
- print(f"✓ Non-loanable device {device_id} deleted")
- else:
- print(f"✗ Error: Device {device_id} not found")
-
- conn.close()
-
def main():
"""Main menu"""
init_db()
@@ -287,12 +218,9 @@ def main():
print("5. Show Available Tablets")
print("6. Show Active Loans")
print("7. Show Loan History")
- print("8. Add Non-Loanable Device")
- print("9. Show Non-Loanable Devices")
- print("10. Delete Non-Loanable Device")
- print("11. Exit")
+ print("8. Exit")
- choice = input("Enter your choice (1-11): ")
+ choice = input("Enter your choice (1-8): ")
if choice == '1':
print("\n=== Add Tablet ===")
@@ -341,28 +269,6 @@ def main():
show_loan_history()
elif choice == '8':
- print("\n=== Add Non-Loanable Device ===")
- brand = input("Brand: ")
- model = input("Model: ")
- serial_number = input("Serial Number: ")
- device_type = input("Device Type (e.g., projector, monitor): ")
- location = input("Location (optional): ")
- notes = input("Notes (optional): ")
- add_non_loanable_device(brand, model, serial_number, device_type, location, notes)
-
- elif choice == '9':
- show_non_loanable_devices()
-
- elif choice == '10':
- print("\n=== Delete Non-Loanable Device ===")
- show_non_loanable_devices()
- device_id = input("Enter Device ID to delete: ")
- try:
- delete_non_loanable_device(int(device_id))
- except ValueError:
- print("✗ Error: Invalid ID format")
-
- elif choice == '11':
print("Goodbye!")
break
diff --git a/simple_app.py b/simple_app.py
index 0674035..f50478d 100644
--- a/simple_app.py
+++ b/simple_app.py
@@ -62,22 +62,6 @@ def init_db():
)
''')
- # 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):
diff --git a/templates/add_non_loanable_device.html b/templates/add_non_loanable_device.html
deleted file mode 100644
index ae0489e..0000000
--- a/templates/add_non_loanable_device.html
+++ /dev/null
@@ -1,63 +0,0 @@
-{% extends "base.html" %}
-
-{% block content %}
-
Add Non-Loanable Device
-
Add a device that will be tracked in inventory but cannot be loaned to users (e.g., projectors, monitors, etc.)
-{% endblock %}
diff --git a/templates/user_loans.html b/templates/user_loans.html
index 07fac86..8c10045 100644
--- a/templates/user_loans.html
+++ b/templates/user_loans.html
@@ -7,98 +7,45 @@
This page demonstrates the many-to-many relationship between users and tablets via the loans table.
-
-
-
-
-
-
-
+
{% for user_data in users_with_loans %}
{% set user = user_data.user %}
{% set loans = user_data.loans %}
- {% set active_loans = loans|selectattr('status', 'equalto', 'active')|list %}
- {% set returned_loans = loans|selectattr('status', 'equalto', 'returned')|list %}
-