diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000..743835c Binary files /dev/null and b/core/__pycache__/forms.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 60a1227..baa5259 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 42da972..2b28062 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 0581aad..8aa66a5 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/forms.py b/core/forms.py new file mode 100644 index 0000000..7dcbdc5 --- /dev/null +++ b/core/forms.py @@ -0,0 +1,25 @@ +from django import forms +from .models import Book, Transaction + +class BookForm(forms.ModelForm): + class Meta: + model = Book + fields = ['title', 'author', 'isbn', 'total_copies'] + widgets = { + 'title': forms.TextInput(attrs={'class': 'form-control'}), + 'author': forms.TextInput(attrs={'class': 'form-control'}), + 'isbn': forms.TextInput(attrs={'class': 'form-control'}), + 'total_copies': forms.NumberInput(attrs={'class': 'form-control'}), + } + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['total_copies'].initial = 1 + +class IssueBookForm(forms.ModelForm): + class Meta: + model = Transaction + fields = ['borrower_name'] + widgets = { + 'borrower_name': forms.TextInput(attrs={'class': 'form-control'}), + } diff --git a/core/migrations/0003_transaction.py b/core/migrations/0003_transaction.py new file mode 100644 index 0000000..48c47fc --- /dev/null +++ b/core/migrations/0003_transaction.py @@ -0,0 +1,25 @@ +# Generated by Django 5.2.7 on 2025-10-25 14:19 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0002_preload_books'), + ] + + operations = [ + migrations.CreateModel( + name='Transaction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('borrower_name', models.CharField(max_length=200)), + ('issue_date', models.DateTimeField(auto_now_add=True)), + ('return_date', models.DateTimeField(blank=True, null=True)), + ('is_returned', models.BooleanField(default=False)), + ('book', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.book')), + ], + ), + ] diff --git a/core/migrations/__pycache__/0003_transaction.cpython-311.pyc b/core/migrations/__pycache__/0003_transaction.cpython-311.pyc new file mode 100644 index 0000000..4ccf2cf Binary files /dev/null and b/core/migrations/__pycache__/0003_transaction.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index e6c3602..e24712a 100644 --- a/core/models.py +++ b/core/models.py @@ -8,4 +8,14 @@ class Book(models.Model): available_copies = models.PositiveIntegerField(default=1) def __str__(self): - return self.title \ No newline at end of file + return self.title + +class Transaction(models.Model): + book = models.ForeignKey(Book, on_delete=models.CASCADE) + borrower_name = models.CharField(max_length=200) + issue_date = models.DateTimeField(auto_now_add=True) + return_date = models.DateTimeField(null=True, blank=True) + is_returned = models.BooleanField(default=False) + + def __str__(self): + return f"{self.book.title} - {self.borrower_name}" \ No newline at end of file diff --git a/core/templates/core/add_book.html b/core/templates/core/add_book.html new file mode 100644 index 0000000..cea3144 --- /dev/null +++ b/core/templates/core/add_book.html @@ -0,0 +1,42 @@ +{% extends 'base.html' %} + +{% block title %} + Add Book - {{ project_name }} +{% endblock title %} + +{% block content %} +
+
+
+
+
+

Add a New Book

+
+
+
+ {% csrf_token %} +
+ + {{ form.title }} +
+
+ + {{ form.author }} +
+
+ + {{ form.isbn }} +
+
+ + {{ form.total_copies }} +
+ + Cancel +
+
+
+
+
+
+{% endblock content %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index bfa028a..16f338b 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -5,9 +5,15 @@ {% block content %}
-
-

Public Library Catalog

-

Browse our collection of available books.

+
+
+

Public Library Catalog

+

Browse our collection of available books.

+
+
+ Add Book + View Transactions +
@@ -18,6 +24,7 @@ Author ISBN Available Copies + Actions @@ -27,10 +34,17 @@ {{ book.author }} {{ book.isbn }} {{ book.available_copies }} / {{ book.total_copies }} + + {% if book.available_copies > 0 %} + Issue + {% else %} + + {% endif %} + {% empty %} - No books available at the moment. + No books available at the moment. {% endfor %} diff --git a/core/templates/core/issue_book.html b/core/templates/core/issue_book.html new file mode 100644 index 0000000..4b3d40b --- /dev/null +++ b/core/templates/core/issue_book.html @@ -0,0 +1,30 @@ +{% extends 'base.html' %} + +{% block title %} + Issue Book - {{ project_name }} +{% endblock title %} + +{% block content %} +
+
+
+
+
+

Issue Book: {{ book.title }}

+
+
+
+ {% csrf_token %} +
+ + {{ form.borrower_name }} +
+ + Cancel +
+
+
+
+
+
+{% endblock content %} diff --git a/core/templates/core/transactions.html b/core/templates/core/transactions.html new file mode 100644 index 0000000..f612ddc --- /dev/null +++ b/core/templates/core/transactions.html @@ -0,0 +1,58 @@ +{% extends 'base.html' %} + +{% block title %} + Transactions - {{ project_name }} +{% endblock title %} + +{% block content %} +
+
+
+

Transaction Log

+

History of all book issues and returns.

+
+ Back to Catalog +
+ +
+ + + + + + + + + + + + + {% for transaction in transactions %} + + + + + + + + + {% empty %} + + + + {% endfor %} + +
Book TitleBorrower NameIssue DateReturn DateStatusActions
{{ transaction.book.title }}{{ transaction.borrower_name }}{{ transaction.issue_date|date:"Y-m-d H:i" }}{{ transaction.return_date|date:"Y-m-d H:i"|default:"--" }} + {% if transaction.is_returned %} + Returned + {% else %} + Issued + {% endif %} + + {% if not transaction.is_returned %} + Return + {% endif %} +
No transactions found.
+
+
+{% endblock content %} diff --git a/core/urls.py b/core/urls.py index 8e0d0ae..fab64ac 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,11 @@ from django.urls import path -from .views import index +from .views import index, add_book, issue_book, transactions, return_book urlpatterns = [ path("", index, name="index"), + path("add_book/", add_book, name="add_book"), + path("issue_book//", issue_book, name="issue_book"), + path("transactions/", transactions, name="transactions"), + path("return_book//", return_book, name="return_book"), ] diff --git a/core/views.py b/core/views.py index ecac1f8..3eb3bd0 100644 --- a/core/views.py +++ b/core/views.py @@ -1,5 +1,7 @@ -from django.shortcuts import render -from .models import Book +from django.shortcuts import render, redirect, get_object_or_404 +from .models import Book, Transaction +from .forms import BookForm, IssueBookForm +from django.utils import timezone def index(request): books = Book.objects.all() @@ -7,4 +9,62 @@ def index(request): 'books': books, 'project_name': 'Library', } - return render(request, 'core/index.html', context) \ No newline at end of file + return render(request, 'core/index.html', context) + +def add_book(request): + if request.method == 'POST': + form = BookForm(request.POST) + if form.is_valid(): + book = form.save(commit=False) + book.available_copies = book.total_copies + book.save() + return redirect('index') + else: + form = BookForm() + context = { + 'form': form, + 'project_name': 'Library', + } + return render(request, 'core/add_book.html', context) + +def issue_book(request, book_id): + book = get_object_or_404(Book, id=book_id) + if request.method == 'POST': + form = IssueBookForm(request.POST) + if form.is_valid(): + if book.available_copies > 0: + transaction = form.save(commit=False) + transaction.book = book + transaction.save() + book.available_copies -= 1 + book.save() + return redirect('index') + else: + # Handle case where no copies are available + pass + else: + form = IssueBookForm() + context = { + 'form': form, + 'book': book, + 'project_name': 'Library', + } + return render(request, 'core/issue_book.html', context) + +def transactions(request): + transactions = Transaction.objects.all().order_by('-issue_date') + context = { + 'transactions': transactions, + 'project_name': 'Library', + } + return render(request, 'core/transactions.html', context) + +def return_book(request, transaction_id): + transaction = get_object_or_404(Transaction, id=transaction_id) + if not transaction.is_returned: + transaction.is_returned = True + transaction.return_date = timezone.now() + transaction.save() + transaction.book.available_copies += 1 + transaction.book.save() + return redirect('transactions')