Add loan tables
Add two views for loans : - inventory:ongoing_loans - inventory:all_loans (permission inventory.can_see_loan_details required)
This commit is contained in:
parent
d8551052fd
commit
00148cd5ca
15 changed files with 156 additions and 6 deletions
|
@ -26,6 +26,7 @@ INSTALLED_APPS = [
|
|||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"django_cas_ng",
|
||||
"django_tables2",
|
||||
"markdownx",
|
||||
"haystack",
|
||||
"website",
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# Generated by Django 4.2.8 on 2024-05-06 14:23
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0003_gameloan'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='category',
|
||||
options={'ordering': ['name'], 'verbose_name': 'étagère'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='gameloan',
|
||||
options={'ordering': ['borrow_date'], 'permissions': [('can_see_loan_details', 'Can see loan details')], 'verbose_name': 'emprunt', 'verbose_name_plural': 'emprunts'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='gameloan',
|
||||
name='borrow_date',
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name='Date d’emprunt'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='gameloan',
|
||||
name='return_date',
|
||||
field=models.DateTimeField(null=True, verbose_name='Date de retour'),
|
||||
),
|
||||
]
|
|
@ -162,3 +162,5 @@ class GameLoan(AbstractLoan):
|
|||
|
||||
class Meta(AbstractLoan.Meta):
|
||||
abstract = False
|
||||
permissions = [("can_see_loan_details", "Can see loan details")]
|
||||
|
||||
|
|
33
inventory/tables.py
Normal file
33
inventory/tables.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
import django_tables2 as tables
|
||||
from django.utils.html import format_html
|
||||
from django.urls import reverse
|
||||
from .models import GameLoan
|
||||
|
||||
class LoanTable(tables.Table):
|
||||
next_pattern = "inventory:all_loans"
|
||||
|
||||
class Meta:
|
||||
model = GameLoan
|
||||
sequence = ("lent_object", "borrow_date", "return_date", "mail")
|
||||
exclude = ("id",)
|
||||
slug = tables.Column(verbose_name="Actions", orderable=False)
|
||||
|
||||
def render_lent_object(self, value, record):
|
||||
return format_html("<a href='{}'>{}</a>",
|
||||
reverse("inventory:game", args=[record.lent_object.slug]), value)
|
||||
|
||||
def render_slug(self, value, record):
|
||||
res = ""
|
||||
if record.return_date == None:
|
||||
res = format_html("<a class='button' href='{}?next={}'>Rendre le jeu</a>",
|
||||
reverse("inventory:return_game", args=[value]),
|
||||
reverse(self.next_pattern))
|
||||
return res
|
||||
|
||||
|
||||
class OngoingLoansTable(LoanTable):
|
||||
next_pattern = "inventory:ongoing_loans"
|
||||
|
||||
class Meta(LoanTable.Meta):
|
||||
exclude = ("return_date", "mail", "id")
|
||||
|
|
@ -11,6 +11,9 @@
|
|||
|
||||
<hr/>
|
||||
|
||||
<a class="button" href="{% url "inventory:ongoing_loans" %}">
|
||||
Emprunts en cours
|
||||
</a>
|
||||
<a class="button" href="{% url "inventory:category_list" %}">
|
||||
Liste des étagères
|
||||
<p class="helptext">
|
||||
|
|
9
inventory/templates/inventory/loans/loans_table.html
Normal file
9
inventory/templates/inventory/loans/loans_table.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
{% extends "base.html" %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block "content" %}
|
||||
<h1>Liste des emprunts</h1>
|
||||
{% render_table table %}
|
||||
{% endblock %}
|
||||
|
||||
{% block "main_attributes" %}class="wide-main"{% endblock %}
|
7
inventory/templates/inventory/loans/ongoing.html
Normal file
7
inventory/templates/inventory/loans/ongoing.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block "content" %}
|
||||
<h1>Emprunts en cours</h1>
|
||||
{% render_table table %}
|
||||
{% endblock %}
|
|
@ -13,6 +13,8 @@ from .views import (
|
|||
GameLoanView,
|
||||
BorrowGameView,
|
||||
ReturnGameView,
|
||||
OngoingLoansView,
|
||||
DetailLoanView,
|
||||
)
|
||||
|
||||
app_name = "inventory"
|
||||
|
@ -34,7 +36,9 @@ urlpatterns = [
|
|||
name="modify_game_comment",
|
||||
),
|
||||
path("search/", InventorySearchView.as_view(), name="search"),
|
||||
path("loans/<slug>/", GameLoanView.as_view(), name="game_loan"),
|
||||
path("loans/game/<slug>/", GameLoanView.as_view(), name="game_loan"),
|
||||
path("loans/return/<slug>/", ReturnGameView.as_view(), name="return_game"),
|
||||
path("loans/borrow/<slug>/", BorrowGameView.as_view(), name="borrow_game"),
|
||||
path("loans/ongoing/", OngoingLoansView.as_view(), name="ongoing_loans"),
|
||||
path("loans/all/", DetailLoanView.as_view(), name="all_loans"),
|
||||
]
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
from django.views.generic import TemplateView, ListView, DetailView
|
||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||
from haystack.generic_views import SearchView
|
||||
from haystack.forms import SearchForm
|
||||
from haystack.query import SearchQuerySet
|
||||
from django_tables2.views import SingleTableView
|
||||
from comments.views import AddCommentView, ModifyCommentView
|
||||
from loans.views import BorrowView, ReturnView, DetailLoanView
|
||||
from .models import Category, Tag, Game, GameComment, GameLoan
|
||||
from .forms import BorrowGameForm
|
||||
from .tables import LoanTable, OngoingLoansTable
|
||||
|
||||
|
||||
class InventoryView(TemplateView):
|
||||
|
@ -67,6 +70,7 @@ class ModifyGameCommentView(ModifyCommentView):
|
|||
template_name = "inventory/game.html"
|
||||
success_pattern_name = "inventory:game"
|
||||
|
||||
|
||||
class BorrowGameView(BorrowView):
|
||||
model = Game
|
||||
loan_model = GameLoan
|
||||
|
@ -74,12 +78,27 @@ class BorrowGameView(BorrowView):
|
|||
form_class = BorrowGameForm
|
||||
success_pattern_name = "inventory:game_loan"
|
||||
|
||||
|
||||
class ReturnGameView(ReturnView):
|
||||
model = GameLoan
|
||||
pattern_name = "inventory:game_loan"
|
||||
|
||||
|
||||
class GameLoanView(DetailLoanView):
|
||||
model = Game
|
||||
loan_model = GameLoan
|
||||
template_name = "inventory/loans/game_loan.html"
|
||||
|
||||
|
||||
class OngoingLoansView(SingleTableView):
|
||||
queryset = GameLoan.ongoing_loans()
|
||||
table_class = OngoingLoansTable
|
||||
template_name = "inventory/loans/ongoing.html"
|
||||
|
||||
|
||||
class DetailLoanView(PermissionRequiredMixin, SingleTableView):
|
||||
permission_required = "inventory.can_see_loan_details"
|
||||
model = GameLoan
|
||||
table_class = LoanTable
|
||||
template_name = "inventory/loans/loans_table.html"
|
||||
|
||||
|
|
|
@ -5,8 +5,9 @@ from django.utils.timezone import now
|
|||
class AbstractLoan(models.Model):
|
||||
lent_object = None # Fill this with a foreign key in subclasses
|
||||
slug = AutoSlugField(unique=True, populate_from="lent_object")
|
||||
borrow_date = models.DateTimeField(auto_now_add=True)
|
||||
return_date = models.DateTimeField(null=True)
|
||||
borrow_date = models.DateTimeField(
|
||||
auto_now_add=True, verbose_name="Date d’emprunt")
|
||||
return_date = models.DateTimeField(null=True, verbose_name="Date de retour")
|
||||
mail = models.EmailField()
|
||||
|
||||
lent_object_slug_field = "slug"
|
||||
|
|
|
@ -21,6 +21,8 @@ class ReturnView(SingleObjectMixin, RedirectView):
|
|||
kwargs[self.redirect_slug_field] = getattr(loan.lent_object,
|
||||
loan.lent_object_slug_field)
|
||||
messages.success(self.request, "Rendu effectué.")
|
||||
if "next" in self.request.GET:
|
||||
return self.request.GET["next"]
|
||||
return super().get_redirect_url(*args, **kwargs)
|
||||
|
||||
|
||||
|
|
|
@ -7,3 +7,4 @@ Pillow
|
|||
django-cas-ng
|
||||
django-haystack
|
||||
Whoosh
|
||||
django-tables2
|
||||
|
|
|
@ -31,7 +31,6 @@ body {
|
|||
}
|
||||
|
||||
main {
|
||||
max-width: $page_width;
|
||||
width: 100%;
|
||||
padding: 20px 40px;
|
||||
margin: 0 auto 50px;
|
||||
|
@ -48,6 +47,10 @@ main {
|
|||
}
|
||||
}
|
||||
|
||||
main:not(.wide-main){
|
||||
max-width: $page_width;
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: $footer_bg_color;
|
||||
font-size: 0.7em;
|
||||
|
@ -153,6 +156,24 @@ table {
|
|||
th {
|
||||
border-bottom-width: 2px;
|
||||
}
|
||||
|
||||
th.asc::before {
|
||||
display: inline;
|
||||
font-family: FontAwesome;
|
||||
content: '\f0de'; // Sort up symbol
|
||||
}
|
||||
|
||||
th.desc::before {
|
||||
display: inline;
|
||||
font-family: FontAwesome;
|
||||
content: '\f0dd'; // Sort down symbol
|
||||
}
|
||||
|
||||
th.orderable:not(.asc, .desc)::before {
|
||||
display: inline;
|
||||
font-family: FontAwesome;
|
||||
content: '\f0dc'; // Sort up/down symbol
|
||||
}
|
||||
}
|
||||
|
||||
iframe {
|
||||
|
|
|
@ -277,9 +277,7 @@ body {
|
|||
@media (max-width: 700px) {
|
||||
body {
|
||||
font-size: 12pt; } }
|
||||
|
||||
main {
|
||||
max-width: 850px;
|
||||
width: 100%;
|
||||
padding: 20px 40px;
|
||||
margin: 0 auto 50px;
|
||||
|
@ -291,6 +289,9 @@ main {
|
|||
main.small_page {
|
||||
max-width: 550px; }
|
||||
|
||||
main:not(.wide-main) {
|
||||
max-width: 850px; }
|
||||
|
||||
footer {
|
||||
background-color: #6bb8c4;
|
||||
font-size: 0.7em;
|
||||
|
@ -403,6 +404,18 @@ table {
|
|||
text-align: left; }
|
||||
table th {
|
||||
border-bottom-width: 2px; }
|
||||
table th.asc::before {
|
||||
display: inline;
|
||||
font-family: FontAwesome;
|
||||
content: '\f0de'; }
|
||||
table th.desc::before {
|
||||
display: inline;
|
||||
font-family: FontAwesome;
|
||||
content: '\f0dd'; }
|
||||
table th.orderable:not(.asc, .desc)::before {
|
||||
display: inline;
|
||||
font-family: FontAwesome;
|
||||
content: '\f0dc'; }
|
||||
|
||||
iframe {
|
||||
width: 100%;
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
<a {% if url_name == "home" %}class="current"{% endif %} href="{% url "website:home" %}"><i class="fa fa-home" aria-hidden="true"></i></a>
|
||||
<a {% if url_name == "inventory" %}class="current"{% endif %} href="{% url "inventory:inventory" %}">Inventaire</a>
|
||||
<a {% if url_name == "suggestions" %}class="current"{% endif %} href="{% url "suggestions:suggestions" %}">Suggestions</a>
|
||||
{% if perms.inventory.can_see_loan_details %}
|
||||
<a href={% url "inventory:all_loans" %}>Gestion des emprunts</a>
|
||||
{% endif %}
|
||||
{% if request.user.is_staff %}
|
||||
<a href="{% url "admin:index" %}">Admin</a>
|
||||
{% endif %}
|
||||
|
|
Loading…
Add table
Reference in a new issue