From 7b5d9db7996fde8a5ab4f7bae1ef2c6b38bd09c5 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 25 Oct 2025 14:23:17 +0000 Subject: [PATCH] lms2 --- core/__pycache__/forms.cpython-311.pyc | Bin 0 -> 2127 bytes core/__pycache__/models.cpython-311.pyc | Bin 1029 -> 1941 bytes core/__pycache__/urls.cpython-311.pyc | Bin 348 -> 751 bytes core/__pycache__/views.cpython-311.pyc | Bin 635 -> 3602 bytes core/forms.py | 25 +++++++ core/migrations/0003_transaction.py | 25 +++++++ .../0003_transaction.cpython-311.pyc | Bin 0 -> 1504 bytes core/models.py | 12 +++- core/templates/core/add_book.html | 42 +++++++++++ core/templates/core/index.html | 22 ++++-- core/templates/core/issue_book.html | 30 ++++++++ core/templates/core/transactions.html | 58 +++++++++++++++ core/urls.py | 6 +- core/views.py | 66 +++++++++++++++++- 14 files changed, 277 insertions(+), 9 deletions(-) create mode 100644 core/__pycache__/forms.cpython-311.pyc create mode 100644 core/forms.py create mode 100644 core/migrations/0003_transaction.py create mode 100644 core/migrations/__pycache__/0003_transaction.cpython-311.pyc create mode 100644 core/templates/core/add_book.html create mode 100644 core/templates/core/issue_book.html create mode 100644 core/templates/core/transactions.html diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..743835c55721c84edbc39a722d75504489304c09 GIT binary patch literal 2127 zcmb_d-%BG$9G}_jZZ>LKy^Ge?czC@ZG_{(89<)#?{e?R^l%xu7p6m<2Wlp z?|r71xn6WFr(BGfM<|{yn(xEpG3aa(l^R49Ldg^)3wr|S1S4u{tU?y35qqSlVuh?z zRRY;!prDu;5Zu8%etM}{g~=IjGp34*@HRieZGo8ba_e09N*4W9+ym_o(1Ni2uV<7N zSM*4?EQ3B3)r5go$tTH{Rg-zs)xk{3wOrc_WZiR@92STcpDzb}uH)*qR&-V^lLu1K z);T}vLoZAeowCau`x$secU{H{nVvw=w6b0@H7)4Tw31_ZHqQGr?Q>7JBMQTS2qYky zb|5cUrfqPBVG$(mo9ph~@~Yh$Syf0GwaQJW!KA^ z>t@k&9hO~l*a~0Oi)OayFf$uQ%H--7fr$1o3~ZFl9|LT*zj}YFBGm_`{IFN#-v_U6 zKiJXsXRCAm__RNmI~>f_26OeH8{6iNv;VMK_TS0*LoW|Fy$1V192b^u!vT?-_Cg@)Y>@}@%3AoF(6lfvG>s## zv9YmDHi}HI0(?2pjX@yC`5KvkE835?f z`Wk{Ffs4A~2=|W92q{6j)gUhik)KgyM+HIo*qUzvoK=v2uTDlRtVhYaoO@>LSvy#^ zif!{w2TLqU23>@bWYCu>I2Kiv(=u_XLs(cVg5lwmTw?h`bQvJFJ1Kq-h@=`8`;%%A3W8n zv(M-JcR%q*^M|AP+GxHJ6S_03kP*+T6-qiMJ%h?1V0`hZ4(Sa+!r17BBiuW_fDoC5 z>{icG=iZotBKg!{)A5JSWN22QWq1poj5 literal 0 HcmV?d00001 diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 60a12272dc7761b3009d7f4cb269ba3ce18bdbb3..baa5259a651e17cb79d99b6741057bfd2e0c21cf 100644 GIT binary patch delta 1036 zcmZuv&rcIU6rTOjA9Pzvmx3gM_CSl9AjYK828$7?#Yp5ribR z0nb2=>}|_+c-sInB-3er8@wxVq$_rIor_$JNSw_t7{&??k_YX;f`PHIimRybaM*a}4}{Z=S?5O0JM%}~M$ zCCU$4VyqIg#Mo}?{wKa6PBg^{OPnarw8SWlM|V*}j5o!&CC1A$M?B-Ybp*~syIaMR;qFGI?nhe~W~^aqXq{7=%k^Dls@ B^e6xT delta 168 zcmbQr-^#(aoR^o20SFG<_>)n>IFV0+(PE;yIa>-#FoP!R#IA3Qnv)wD#e~>_N^Y^0 z=4BR^roLnZax^EeWOM*ZzG7U$$UC{8$%9t_D7uoNNDxRB@lSrjw2TMLWCim5G+8E} uXOmTy2FXDb09n5{Y;yBcN^?@}isXP?kg3JKlSSCw`4~7Dr9OZNuwnqORV8Eq diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 42da972829306363b61102b09d94828d264bc08d..2b28062f6d13be85c7699c3b42168effded922ea 100644 GIT binary patch literal 751 zcma)4ziZn-6uz_G>4z0HAxkL@1Va~t$$2g!lb0@DN*4_citmUOTar0RO&U66%-F3N zGn6)^9Xj+6=${~gph0vfbjoJP7CQ7!a;RH8^yvgo-}k=ny}Q$U$7v%O-@gAEzr_gs zR3CR?Es~orGI@g-Vt9%|>|u;pi)qtVsCill9)!drq3-FS;TagU5XTI-#>glAorcgy z`8H8A1_x%YWGqftdnIFYovp289B#0C|1t-}Guir6)ZMsNjk~ylnV*iYc81NiyE#YpL*~#2=+W93_=4c$$f*p^zX8x5y9qiFK!^LYMf-gFi0R z4Wjh1^4<&BE)|C2on>b#Ooerp{2S3yQKMD2Fzi~D%?|zOAl}KuG!g1ZEAk@XM@ch;=$R+dO-Aem{p!0i6;$ zS71u);p_2*mqWjRehK{=%dJNjho4{NFeqS9!k{VKKJQ&V&%rIgEx}zB_AV!1og9V* T3`-c!ZGF9UYO62Q~&)&IXqbp^nfQ;ulyHFS00JVNv|R%*4;szzu>$JV4_Bjompv diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 0581aad11774ef825a4c6cf9d4a6065dbae5cf6a..8aa66a53c74d7a3dcc928a997d39e5997344c279 100644 GIT binary patch literal 3602 zcmbtW|7#n`6`%bgX{D8|wKuWd#IY4wzE~nB-_dh|n>be*Cr5B_TM{@B1tDv;u^dV3 zn_cCLk$W!O56)pY_bAvcxz>einj?Yw=lkjYgk7^>vD6Sa`osMu2nXfp4}CK$tyi`~ z3mv4VnKy6VjNW|S=gr@GdSVEg^^boq{#`=oTRP}8zTJ6^p|gcB!dwMaxja|p^L$mv z3mn2c7Aj&jln+(I`7j%cl}J^}OVwyT3S)#rl~`5I%g_&hg7R@30oj8kki9qxGJ#_t z6)fLDnfP~f%Z%WLiB`iJaV4VRGSNz=+jmbh3;Mzm^b0yEy!Xy~-*MEIcg3IS`h8cv zONuq4STf6c4U`g9-qcCe?YU(bb*(eZaIR#QtJ;cQ(@NAqr-h&+!1whMh%IDx^zggn z+wF8h5|~Bk8H`@|npLjBVGi?8`BmPG_-fQZSZMIiV2>AcAJ*V6i}P;ec6osm$zwQn zXaSCGxbbD8vwvDE!ch|?ooJI~2*{({qFJqEL_+<#5icBuD-iThC8uF^7{10;5Nqflu58@ij}Py~hwb=?6CYW-@v3j2Idr}i5)$DS0~s#kQ8YM$B-n=yW%f?e&_DZuQ)ec(yP_7$u5rcz*3qgzlL-m z^fW8|?3Rld7bxC5P(|HvRWlcLOrl^yhCsMd*(f|HR?65Fjp75%jhnhztQ1Q6a#=H6 zrTCy&t`rw4T3bVCP(2`uq@VWBQZFLigs9Lpr~$w*NlwuTsdEC7f*}R0@h1>#s2S<~ zShr+lg@}F}^M~<-}(*pUymaf8+fY5~Jfyb#QC?^XZ)%o71+M zb=2(oY%@LKq^H(ro%s1?T>0$Qr?;NWZOpCD9jIrwKd{xbqo%ERx)p`h-^Y>OShq><}Np%YJV)Q?HA({4D@eYQI&N|Pwyr+YPxQiI15 zjy@GuLndXic7rsEHA2VINS=rM;meq10HJqvll%xIp&<+;l)%7E&QmQ*s#6|K(`pk) zE1A$MVuVeGX^+-h&-XdnOHwgH1@lDj#>=2E%OE#Glcxa3Vbd(1Wb?4pd1*zDM$@X3 zSh2Ey3Nit6)W7j92;gpc_=~$c_bfSQ%Q;8Rt<4@uw&Cp$pZ>~DWSvCzNV3JEr<)1Y zNu+l^+DlAWiHYV&>d)mrmY>(R%l62WGcvU)H^(k)%8rt3DrfhVIKk^XTv7-^-iw!Qkjl#2%b*1}7|Kq7_Dcr~mcO#PE}kH$L`~ z)636@NJ|U|C^4~iiFtSTvMpb6DeWg07tD1dlF>H2i`WBz za%sB(-XM>T;Vm@3BERk37cQDwhppp*OEx@!4KRQO^&WGF2+d5QP(jOtE9nFtPlbiY z?MH#f#aTMfSh)QdU?fbKnu<&CHReD7NYoKWeQRIM?x|T@z38YH_tmLAb!xY2tFw+e zyLS84Q2I?|`QzOWZF$C#XDo5%I9XDF)BRr$!xh101TN~ok|lpw`Hdom%3ScNG)Mpe z!i0?uUuIzM(`AF-p-FSBb(06BuqB^bfXsXf#KH=cRUk886SVx_e0R~>v6n$6G*8lS zzPldr&>PCcJTjqsx-!&eqM3D4(=d^#MyTlzUD?wW7?uusB?$(sJZA)tS9$|DqV#eB z3_7nwuR3=;vFiOUOkblWzXbsR=^y*+-0r;9f8FlC?(|<@n`_Dgj+|2nplRIJ_8bH<`hOnAx~4DsGOgx)p0X>_br43B?V z+(PsjWO$F97&VEvebmh|7}7|3ET5vi2`X5M&3IKS)=>cfF!rBbQ-{;@J2a zL`&c}u8DqXz4_BbJ<5XF+h8qA={_7bE~lkpZ?QEFaFYSBwZ2$#hvKR*}4!|2V* z50qn>ti$BV?5D{(c|VVM?Jc(4{FKz3;v!a{R1rviB}0(_h|LEiesS0UrAu>C?TSQz nT#(VlPC()VGb1D84F=^4sOScR#06CJfrX9H`~w3f0k#7G!1O(I 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 0000000000000000000000000000000000000000..4ccf2cfe758f968ba8f0305fdc3648568c4c1efa GIT binary patch literal 1504 zcmZt`J8auV^hi;ZNJ)<5IuSH9VuhfsJV=IRZ$$x1vVzu$mly%636JyLd@ z$wLct%+`#VTolpJp@YYa8BYKQR*S72|^632;dVk~tf0f^u}fQg>~lu%+6e*?~$wO8y! ztDA(vBT!Ag<>Y=wLSfzVBe07=)L zpa?lf9;IRfP+~g?Z0Zw?EXRO)&vA}inmNFR?HYaF94eadphLy) z+Es~Wjj8A8eT)nbL7JIhb8O&K{Ro{>#YNaOEb|$n*<*xzj*E2L7$chNIT$-92#4g` zH!S$7z`Acd)h%QXydhOh*PS9AGNViq`LLZ6-GIyoM&1l%5qg4W&&BrLsaw}o_rXad}tyIy8G1vP3vKNx=vMH zXX7}v5W};&{^QiJxH6|8njjk@yKf?wUlu?!t*{sm`TSx&W;EM02Rp1x9d4Q`t)YP< zG}mSc9++bkk=dr>Sjey=O6{;{&4IngN-4vUVGkTC!X8bBQS&~eT04(gJMCSnIuo?G zIKP7{J_{dO^`SFH^=WTvd(%34iux=7Tt9K}kvlQ^sLpFqzrJvF*7Sz%U3a-QImLX` zLcnj48!<+<^>~uY!cQCZ9bBRG^f9QT_DY%fj8i3%5ye{rRz9T)&Xs+#_9`*q9XE zdC~QYF3EeB1&vfTUw-LVHZS_5(wtYCex*tBt;@paq}+IM?3Wv_*GRcDFL(TMhve@w zt3=y+Df`;i#nx*`w7t2u=WBZ;{~#1KxTtZlOSI-(Yx-JbtVl}hFYfrI^*u>M-+mFeULsA;dO9Q_&Ao*dCORcR0NmWtb0S4Z45G1mz^4a%%<9b|zs!U5!7izFq zi~dfvxD~j{)TpwQhm#OCKdNDkTM12VFziG6n`oTA#SKRC-;CR1AV>&;!0IY|L4X!L em*8visV9(E1vvmW!E@Em-+RXe?>`|8WB3o`OP~z^ literal 0 HcmV?d00001 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.

+
+
@@ -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')