Browse Source

Allow members to declare item borrowing

Jocelyn Delande 9 years ago
parent
commit
e859e7fa18

+ 12 - 0
coin/static/css/local.css

@@ -208,6 +208,10 @@ table .actions {
 table .actions .button {
 table .actions .button {
 	width: 100%;
 	width: 100%;
 }
 }
+
+.pre-table-action {
+	float: right;
+}
 /* Footer */
 /* Footer */
 
 
 #footer {
 #footer {
@@ -356,6 +360,14 @@ tr.inactive {
     border: 2px solid #C0C0C0;
     border: 2px solid #C0C0C0;
 }
 }
 
 
+form .helptext {
+	position: relative;
+	top: -1em;
+	margin: 0em 1em 0em 1em;
+	font-style: italic;
+	font-size: small;
+}
+
 /* Feeds */
 /* Feeds */
 .feed {
 .feed {
     font-size:80%;
     font-size:80%;

+ 12 - 0
hardware_provisioning/forms.py

@@ -6,10 +6,22 @@ from django.db.models import Q
 from django import forms
 from django import forms
 
 
 from .models import Storage
 from .models import Storage
+from .validators import validate_future_date
 
 
 User = get_user_model()
 User = get_user_model()
 
 
 
 
+class LoanDeclareForm(forms.Form):
+    loan_date_end = forms.DateField(
+        label='Date de retour prévue',
+        required=False,
+        validators=[validate_future_date],
+        input_formats=['%d/%m/%Y'],
+        help_text='laisser vide si non planifié',
+        widget=forms.TextInput(
+            attrs={'type': 'date', 'placeholder': 'JJ/MM/AAAA'}))
+
+
 class LoanReturnForm(forms.Form):
 class LoanReturnForm(forms.Form):
     storage = forms.ModelChoiceField(
     storage = forms.ModelChoiceField(
         label='Dans quel lieu de stockage ai-je remis le matériel ?',
         label='Dans quel lieu de stockage ai-je remis le matériel ?',

+ 14 - 0
hardware_provisioning/templates/hardware_provisioning/item_borrow.html

@@ -0,0 +1,14 @@
+{% extends 'base.html' %}
+
+{% block content %}
+
+<p>Je déclare emprunter le matériel <strong>{{item }} ({{ item.type }}</strong>) à compter de ce jour.</p>
+
+
+<form method='post'>{% csrf_token %}
+{{ form.as_p }}
+    <input class="success button" type="submit"
+           value="Oui oui, c'est bien ça."/>
+</form>
+
+{% endblock %}

+ 38 - 0
hardware_provisioning/templates/hardware_provisioning/item_list.html

@@ -0,0 +1,38 @@
+{% extends "base.html" %}
+
+{% block content %}
+<h2>J'emprunte à l'association…</h2>
+
+<table>
+    <thead>
+        <tr>
+            <th>Type de matériel</th>
+            <th>Désignation</th>
+            <th>Dépôt</th>
+            <th>Addr. MAC</th>
+            <th>Num. de série</th>
+            <th>Actions</th>
+        </tr>
+    </thead>
+
+    <tbody>
+       {% for i in items %}
+        <tr>
+            <td>{{ i.type }}</td>
+            <td>{{ i.designation }}</td>
+            <td>{{ i.storage|default:'inconnu' }}</td>
+            <td>{{ i.mac_address|default:'n/a' }}</td>
+            <td>{{ i.serial|default:'n/a' }}</td>
+            <td class="actions">
+                <div class="button-group">
+                  <a href="{% url 'hardware_provisioning:item-borrow' pk=i.pk %}" class="small button">
+                     <i class="fa fa-exchange"></i>&nbsp;Déclarer l'emprunt
+                 </a>
+                </div>
+            </td>
+        </tr>
+        {% endfor %}
+    </tbody>
+
+</table>
+{% endblock %}

+ 7 - 0
hardware_provisioning/templates/hardware_provisioning/list.html

@@ -10,6 +10,13 @@
 <div class="message {{ message.tags }}">{{ message }}</div>
 <div class="message {{ message.tags }}">{{ message }}</div>
 {% endfor %}
 {% endfor %}
 
 
+<p>
+    <a href="{% url 'hardware_provisioning:item-list' %}"
+       class="button pre-table-action success">
+        <i class="fa fa-plus"></i> Déclarer un emprunt
+    </a>
+</p>
+
 <table id="member_loans" class="full-width">
 <table id="member_loans" class="full-width">
     <thead>
     <thead>
         <tr>
         <tr>

+ 2 - 0
hardware_provisioning/urls.py

@@ -7,6 +7,8 @@ from . import views
 
 
 urlpatterns = [
 urlpatterns = [
     url(r'^$', views.loan_list, name='loan-list'),
     url(r'^$', views.loan_list, name='loan-list'),
+    url(r'^items/list$', views.item_list, name='item-list'),
+    url(r'^items/(?P<pk>[0-9]+)/borrow$', views.item_borrow, name='item-borrow'),
     url(r'^(?P<pk>[0-9]+)/return$', views.loan_return, name='loan-return'),
     url(r'^(?P<pk>[0-9]+)/return$', views.loan_return, name='loan-return'),
     url(r'^(?P<pk>[0-9]+)/transfer$', views.loan_transfer, name='loan-transfer'),
     url(r'^(?P<pk>[0-9]+)/transfer$', views.loan_transfer, name='loan-transfer'),
     url(r'^(?P<pk>[0-9]+)$', views.loan_detail, name='loan-detail'),
     url(r'^(?P<pk>[0-9]+)$', views.loan_detail, name='loan-detail'),

+ 11 - 0
hardware_provisioning/validators.py

@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+
+import datetime
+
+from django.core.exceptions import ValidationError
+
+
+def validate_future_date(value):
+    if value <= datetime.date.today():
+        raise ValidationError(
+            'La date de retour doit être dans le futur')

+ 46 - 2
hardware_provisioning/views.py

@@ -4,17 +4,61 @@ from __future__ import unicode_literals
 
 
 import datetime
 import datetime
 
 
-from django.shortcuts import render, redirect
+from django.shortcuts import get_object_or_404, render, redirect
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.decorators import login_required
 from django.contrib import messages
 from django.contrib import messages
 from django.http import HttpResponseForbidden
 from django.http import HttpResponseForbidden
 from django.core.urlresolvers import reverse
 from django.core.urlresolvers import reverse
 
 
-from .forms import LoanTransferForm, LoanReturnForm
+from .forms import LoanDeclareForm, LoanTransferForm, LoanReturnForm
 from .models import Item, Loan
 from .models import Item, Loan
 
 
 
 
 @login_required
 @login_required
+def item_list(request):
+    items = Item.objects.all().order_by('storage', 'type', 'designation')
+
+    # FIXME: suboptimal
+    items = [i for i in items.filter() if i.is_available()]
+    return render(request, 'hardware_provisioning/item_list.html', {
+        'items': items,
+    })
+
+
+@login_required
+def item_borrow(request, pk):
+    item = get_object_or_404(Item, pk=pk)
+
+    if not item.is_available():
+        return HttpResponseForbidden('Item non disponible')
+
+    if request.method == 'POST':
+        form = LoanDeclareForm(request.POST)
+        if form.is_valid():
+            loan = Loan.objects.create(
+                item=item,
+                loan_date=datetime.date.today(),
+                loan_date_end=form.cleaned_data['loan_date_end'],
+                user=request.user,
+            )
+            messages.success(
+                request, "Emprunt de {} ({}) enregistré".format(
+                    item.designation, item.type))
+            if not loan.loan_date_end:
+                messages.warning(
+                    request,
+                    "N'oubliez pas de notifier le retour de l'objet le temps venu")
+            return redirect(reverse('hardware_provisioning:loan-list'))
+    else:
+        form = LoanDeclareForm()
+
+    return render(request, 'hardware_provisioning/item_borrow.html', {
+        'item': item,
+        'form': form,
+    })
+
+
+@login_required
 def loan_return(request, pk):
 def loan_return(request, pk):
     loan = get_object_or_404(Loan, pk=pk)
     loan = get_object_or_404(Loan, pk=pk)