From 9b2e164ddb95d5f6465b312096a9c9a43a406584 Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Sun, 22 Apr 2018 08:28:46 +0200 Subject: [PATCH 1/2] add a backoffice view to approve public credit names, fixes #217 --- .../approve_public_credit_names.html | 42 +++++++++++++++++++ .../templates/backoffice_index.html | 4 ++ src/backoffice/urls.py | 1 + src/backoffice/views.py | 9 ++++ 4 files changed, 56 insertions(+) create mode 100644 src/backoffice/templates/approve_public_credit_names.html diff --git a/src/backoffice/templates/approve_public_credit_names.html b/src/backoffice/templates/approve_public_credit_names.html new file mode 100644 index 00000000..0ed6beb8 --- /dev/null +++ b/src/backoffice/templates/approve_public_credit_names.html @@ -0,0 +1,42 @@ +{% extends 'base.html' %} +{% load commonmark %} +{% load static from staticfiles %} +{% load imageutils %} +{% block extra_head %} + + +{% endblock extra_head %} +{% block content %} +
+

Approve Public Credit Names

+
+ Use this view to approve users public credit names. +
+
+
+
+ + + + + + + + + + + {% for profile in profiles %} + + + + + + + {% endfor %} + +
UsernameEmailPublic Credit NameActions
{{ profile.user.username }}{{ profile.user.email }}{{ profile.public_credit_name }} + Open In Admin +
+
+{% endblock content %} + diff --git a/src/backoffice/templates/backoffice_index.html b/src/backoffice/templates/backoffice_index.html index 4fd2dad4..ad799924 100644 --- a/src/backoffice/templates/backoffice_index.html +++ b/src/backoffice/templates/backoffice_index.html @@ -26,6 +26,10 @@

Hand Out Badges

Use this view to mark badges as handed out.

+ +

Approve Public Credit Names

+

Use this view to check and approve users Public Credit Names

+
diff --git a/src/backoffice/urls.py b/src/backoffice/urls.py index e1af8680..e366e471 100644 --- a/src/backoffice/urls.py +++ b/src/backoffice/urls.py @@ -9,5 +9,6 @@ urlpatterns = [ url(r'product_handout/$', ProductHandoutView.as_view(), name='product_handout'), url(r'badge_handout/$', BadgeHandoutView.as_view(), name='badge_handout'), url(r'ticket_checkin/$', TicketCheckinView.as_view(), name='ticket_checkin'), + url(r'public_credit_names/$', ApproveNamesView.as_view(), name='public_credit_names'), ] diff --git a/src/backoffice/views.py b/src/backoffice/views.py index dfb3de69..e08ced5f 100644 --- a/src/backoffice/views.py +++ b/src/backoffice/views.py @@ -2,6 +2,7 @@ from django.views.generic import TemplateView, ListView from django.http import HttpResponseForbidden from shop.models import OrderProductRelation from tickets.models import ShopTicket, SponsorTicket, DiscountTicket +from profiles.models import Profile from itertools import chain import logging logger = logging.getLogger("bornhack.%s" % __name__) @@ -44,3 +45,11 @@ class TicketCheckinView(StaffMemberRequiredMixin, ListView): discounttickets = DiscountTicket.objects.filter(checked_in=False) return list(chain(shoptickets, sponsortickets, discounttickets)) + +class ApproveNamesView(StaffMemberRequiredMixin, ListView): + template_name = "approve_public_credit_names.html" + context_object_name = 'profiles' + + def get_queryset(self, **kwargs): + return Profile.objects.filter(public_credit_name_approved=False).exclude(public_credit_name='') + From a25063513244a563bf8afbdca78b8480b48bd569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?= Date: Sun, 22 Apr 2018 08:31:10 +0200 Subject: [PATCH 2/2] Added the first tests to the project. Using factory_boy for great success. (#219) --- src/requirements/test.txt | 3 +++ src/shop/factories.py | 51 +++++++++++++++++++++++++++++++++++++++ src/shop/models.py | 2 +- src/shop/tests.py | 30 +++++++++++++++++++++++ src/utils/factories.py | 11 +++++++++ 5 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 src/requirements/test.txt create mode 100644 src/shop/factories.py create mode 100644 src/shop/tests.py create mode 100644 src/utils/factories.py diff --git a/src/requirements/test.txt b/src/requirements/test.txt new file mode 100644 index 00000000..a0232901 --- /dev/null +++ b/src/requirements/test.txt @@ -0,0 +1,3 @@ +-r dev.txt + +factory_boy==2.10.0 diff --git a/src/shop/factories.py b/src/shop/factories.py new file mode 100644 index 00000000..9b0c5e0c --- /dev/null +++ b/src/shop/factories.py @@ -0,0 +1,51 @@ +import factory + +from factory.django import DjangoModelFactory + +from django.utils import timezone + +from psycopg2.extras import DateTimeTZRange + +from utils.factories import UserFactory + + +class ProductCategoryFactory(DjangoModelFactory): + class Meta: + model = 'shop.ProductCategory' + + name = factory.Faker('word') + + +class ProductFactory(DjangoModelFactory): + class Meta: + model = 'shop.Product' + + name = factory.Faker('word') + slug = factory.Faker('word') + category = factory.SubFactory(ProductCategoryFactory) + description = factory.Faker('paragraph') + price = factory.Faker('pyint') + available_in = factory.LazyFunction( + lambda: + DateTimeTZRange( + lower=timezone.now(), + upper=timezone.now() + timezone.timedelta(31) + ) + ) + + +class OrderFactory(DjangoModelFactory): + class Meta: + model = 'shop.Order' + + user = factory.SubFactory(UserFactory) + + +class OrderProductRelationFactory(DjangoModelFactory): + class Meta: + model = 'shop.OrderProductRelation' + + product = factory.SubFactory(ProductFactory) + order = factory.SubFactory(OrderFactory) + quantity = 1 + handed_out = False diff --git a/src/shop/models.py b/src/shop/models.py index cca68232..a3ab1329 100644 --- a/src/shop/models.py +++ b/src/shop/models.py @@ -351,7 +351,7 @@ class Product(CreatedUpdatedModel, UUIDModel): """ now = timezone.now() time_available = now in self.available_in - stock_available = (self.stock_amount - self.left_in_stock()) > 0 + stock_available = self.left_in_stock() > 0 return time_available and stock_available def is_old(self): diff --git a/src/shop/tests.py b/src/shop/tests.py new file mode 100644 index 00000000..daca2dd5 --- /dev/null +++ b/src/shop/tests.py @@ -0,0 +1,30 @@ +from django.test import TestCase + +from .factories import ( + ProductFactory, + OrderFactory, + OrderProductRelationFactory, +) + + +class ProductAvailabilityTest(TestCase): + """ Test logic about availability of products. """ + + def test_product_available_by_stock(self): + """ If no orders have been made, the product is still available. """ + product = ProductFactory(stock_amount=10) + self.assertEqual(product.left_in_stock(), 10) + self.assertTrue(product.is_available) + + def test_product_not_available_by_stock(self): + """ If max orders have been made, the product is NOT available. """ + product = ProductFactory(stock_amount=2) + + for i in range(2): + opr = OrderProductRelationFactory(product=product) + order = opr.order + order.paid = True + order.save() + + self.assertEqual(product.left_in_stock(), 0) + self.assertFalse(product.is_available()) diff --git a/src/utils/factories.py b/src/utils/factories.py new file mode 100644 index 00000000..6cdf524e --- /dev/null +++ b/src/utils/factories.py @@ -0,0 +1,11 @@ +import factory +from factory.django import DjangoModelFactory + + +class UserFactory(DjangoModelFactory): + class Meta: + model = 'auth.User' + + username = factory.Faker('word') + email = factory.Faker('ascii_email') +