Browse Source

Fix buggy finished/running Loans & use timezones

- Date checks were done relative to django startup time, not function call time
- Use propper timezone-aware datetimes instead of naive datetimes
Jocelyn Delalande 8 years ago
parent
commit
eea8c2cb30

+ 3 - 2
hardware_provisioning/admin.py

@@ -2,10 +2,11 @@
 
 from __future__ import unicode_literals
 
-from datetime import date
 
 from django.contrib import admin
 from django.contrib.auth import get_user_model
+from django.utils import timezone
+
 from .models import ItemType, Item, Loan, Storage
 
 
@@ -130,7 +131,7 @@ class LoanAdmin(admin.ModelAdmin):
 
     def end_loan(self, request, queryset):
         queryset.filter(loan_date_end=None).update(
-            loan_date_end=date.today())
+            loan_date_end=datetime.now())
     end_loan.short_description = 'Mettre fin au prêt'
 
 

+ 11 - 7
hardware_provisioning/models.py

@@ -1,9 +1,10 @@
 # -*- coding: utf-8 -*-
 
 from __future__ import unicode_literals
-from datetime import date
 from django.db import models
 from django.conf import settings
+from django.utils import timezone
+
 from .fields import MACAddressField
 
 
@@ -88,19 +89,22 @@ class Item(models.Model):
         self.storage = storage
         self.save()
         self.loans.running().update(
-            loan_date_end=date.today())
+            loan_date_end=timezone.now())
 
 
 class LoanQuerySet(models.QuerySet):
-    running_filter = (
-        models.Q(loan_date_end__gt=date.today()) |
-        models.Q(loan_date_end__isnull=True))
+
+    @staticmethod
+    def _running_filter():
+        return (
+            models.Q(loan_date_end__gt=timezone.now()) |
+            models.Q(loan_date_end__isnull=True))
 
     def running(self):
-        return self.filter(self.running_filter)
+        return self.filter(self._running_filter())
 
     def finished(self):
-        return self.exclude(self.running_filter)
+        return self.exclude(self._running_filter())
 
 
 class Loan(models.Model):

+ 37 - 1
hardware_provisioning/tests.py

@@ -1,3 +1,39 @@
+from datetime import datetime, timedelta, date
+
 from django.test import TestCase
+from django.utils import timezone
+
+from coin.members.models import Member
+from .models import Item, ItemType, Loan
+
+
+def localize(naive_dt):
+    if not timezone.is_naive(naive_dt):
+        raise ValueError('Expecting a naive datetime')
+    else:
+        return timezone.make_aware(naive_dt, timezone.get_current_timezone())
+
+
+class HardwareLoaningTestCase(TestCase):
+    def setUp(self):
+        self.member = Member.objects.create(
+            first_name='John',
+            last_name='Doe',
+            username='jdoe')
+        self.item_type = ItemType.objects.create(name='Foos')
+        self.item = Item.objects.create(
+            type=self.item_type,
+            designation='Bar Wheel',
+            buy_date=date(2012,12,5))
+
+    def test_running_(self):
+        loan_start_date = localize(datetime(2011,1,14,12,0,0))
+        loan = Loan.objects.create(
+            item=self.item, user=self.member,
+            loan_date=loan_start_date)
 
-# Create your tests here.
+        self.assertEqual(Loan.objects.running().count(), 1)
+        self.assertEqual(Loan.objects.finished().count(), 0)
+        loan.item.give_back()
+        self.assertEqual(Loan.objects.running().count(), 0)
+        self.assertEqual(Loan.objects.finished().count(), 1)

+ 2 - 1
hardware_provisioning/validators.py

@@ -3,9 +3,10 @@
 import datetime
 
 from django.core.exceptions import ValidationError
+from django.utils import timezone
 
 
 def validate_future_date(value):
-    if value <= datetime.date.today():
+    if value <= timezone.now():
         raise ValidationError(
             'La date de retour doit être dans le futur')

+ 3 - 3
hardware_provisioning/views.py

@@ -2,13 +2,13 @@
 
 from __future__ import unicode_literals
 
-import datetime
 
 from django.shortcuts import get_object_or_404, render, redirect
 from django.contrib.auth.decorators import login_required
 from django.contrib import messages
 from django.http import HttpResponseForbidden
 from django.core.urlresolvers import reverse
+from django.utils import timezone
 
 from .forms import LoanDeclareForm, LoanTransferForm, LoanReturnForm
 from .models import Item, Loan
@@ -37,7 +37,7 @@ def item_borrow(request, pk):
         if form.is_valid():
             loan = Loan.objects.create(
                 item=item,
-                loan_date=datetime.date.today(),
+                loan_date=timezone.now(),
                 loan_date_end=form.cleaned_data['loan_date_end'],
                 user=request.user,
             )
@@ -98,7 +98,7 @@ def loan_transfer(request, pk):
             old_loan.item.give_back()
             Loan.objects.create(
                 user=form.cleaned_data['target_user'],
-                loan_date=datetime.date.today(),
+                loan_date=timezone.now(),
                 item=old_loan.item)
             messages.success(
                 request,