🔥 Remove stat and log views
➖ Remove djangorestframework
This commit is contained in:
1 parent
d7513f389e
commit
7ba3ead688
13 files changed
+67
-609
No files matched your search
@@ -7,7 +7,7 @@ from strawberry import ID
|
|||||||
|
|
||||||
from main import models
|
from main import models
|
||||||
from main.api.errors import Error, FieldError, FormErrors
|
from main.api.errors import Error, FieldError, FormErrors
|
||||||
from main.api.types import Order, Transaction, UserProfile
|
from main.api.types import Order, Transaction
|
||||||
|
|
||||||
UserModel = get_user_model()
|
UserModel = get_user_model()
|
||||||
|
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
from django.db.models import Count, Sum
|
|
||||||
from rest_framework import serializers
|
|
||||||
from rest_framework.serializers import ModelSerializer
|
|
||||||
|
|
||||||
from main.models import Order, OrderLine, Product
|
|
||||||
|
|
||||||
|
|
||||||
class ProductSerializer(ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Product
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class ProductStatSerializer(ModelSerializer):
|
|
||||||
EXTERNAL_USER = "Ekstern"
|
|
||||||
counts = serializers.SerializerMethodField()
|
|
||||||
|
|
||||||
def _format_counts(self, per_user):
|
|
||||||
per_user = list(per_user)
|
|
||||||
for row in per_user:
|
|
||||||
first = row.pop("order__customer__first_name")
|
|
||||||
last = row.pop("order__customer__last_name")
|
|
||||||
if first is None:
|
|
||||||
who = self.EXTERNAL_USER
|
|
||||||
else:
|
|
||||||
who = "{} {}".format(first, last)
|
|
||||||
row["full_name"] = who
|
|
||||||
|
|
||||||
return per_user
|
|
||||||
|
|
||||||
def get_counts(self, obj):
|
|
||||||
name_fields = ["order__customer__first_name", "order__customer__last_name"]
|
|
||||||
per_user = OrderLine.objects.filter(product=obj)
|
|
||||||
per_user = per_user.values(*name_fields).annotate(amount_total=Sum("amount")).order_by("-amount_total")
|
|
||||||
|
|
||||||
return self._format_counts(per_user)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Product
|
|
||||||
fields = [
|
|
||||||
"id",
|
|
||||||
"name",
|
|
||||||
"description",
|
|
||||||
"image",
|
|
||||||
"inventory_amount",
|
|
||||||
"active",
|
|
||||||
"created",
|
|
||||||
"counts",
|
|
||||||
]
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
from rest_framework import mixins
|
|
||||||
from rest_framework.decorators import action
|
|
||||||
from rest_framework.response import Response
|
|
||||||
from rest_framework.viewsets import GenericViewSet
|
|
||||||
|
|
||||||
from main.api.serializers import ProductSerializer, ProductStatSerializer
|
|
||||||
from main.models import Product
|
|
||||||
|
|
||||||
|
|
||||||
class ProductViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
|
|
||||||
serializer_class = ProductSerializer
|
|
||||||
queryset = Product.objects.all()
|
|
||||||
|
|
||||||
@action(detail=False, methods=["get"])
|
|
||||||
def group_by_user(self, request):
|
|
||||||
products = self.get_queryset().filter(active=True)
|
|
||||||
serializer = ProductStatSerializer(products, many=True)
|
|
||||||
|
|
||||||
return Response(serializer.data)
|
|
||||||
@@ -2,7 +2,6 @@ import pytest
|
|||||||
from django.test import Client
|
from django.test import Client
|
||||||
from strawberry.django.test import GraphQLTestClient
|
from strawberry.django.test import GraphQLTestClient
|
||||||
|
|
||||||
from main.api.mutations import create_order
|
|
||||||
from main.models import Order, Product
|
from main.models import Order, Product
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-29
@@ -1,19 +1,9 @@
|
|||||||
from django.contrib.staticfiles.views import serve
|
from django.contrib.staticfiles.views import serve
|
||||||
from django.urls import include, path, re_path
|
from django.urls import include, path, re_path
|
||||||
from rest_framework.routers import DefaultRouter
|
|
||||||
|
|
||||||
from main.api.views import ProductViewSet
|
from main.views.general import deposit, register
|
||||||
from main.views.general import deposit, log, register
|
|
||||||
from main.views.reports import inventory, inventory_add, report
|
from main.views.reports import inventory, inventory_add, report
|
||||||
from main.views.stats import (
|
from main.views.stats import stats_products_per_user, stats_products_realtime
|
||||||
OrdersDailyView,
|
|
||||||
OrdersHourlyView,
|
|
||||||
OrdersMonthlyView,
|
|
||||||
OrdersYearlyView,
|
|
||||||
stats_list,
|
|
||||||
stats_products_per_user,
|
|
||||||
stats_products_realtime,
|
|
||||||
)
|
|
||||||
from main.views.users import create_user, profile
|
from main.views.users import create_user, profile
|
||||||
|
|
||||||
spa_kwargs = {"path": "modern/index.html"}
|
spa_kwargs = {"path": "modern/index.html"}
|
||||||
@@ -41,18 +31,6 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Stats
|
# Stats
|
||||||
urlpatterns += [
|
urlpatterns += [
|
||||||
re_path(
|
|
||||||
r"^stats/orders/hourly/$",
|
|
||||||
OrdersHourlyView.as_view(),
|
|
||||||
name="stats-orders-hourly",
|
|
||||||
),
|
|
||||||
re_path(r"^stats/orders/daily/", OrdersDailyView.as_view(), name="stats-orders-daily"),
|
|
||||||
re_path(
|
|
||||||
r"^stats/orders/monthly/",
|
|
||||||
OrdersMonthlyView.as_view(),
|
|
||||||
name="stats-orders-monthly",
|
|
||||||
),
|
|
||||||
re_path(r"^stats/orders/yearly/", OrdersYearlyView.as_view(), name="stats-orders-yearly"),
|
|
||||||
re_path(
|
re_path(
|
||||||
r"^stats/orders/products_realtime$",
|
r"^stats/orders/products_realtime$",
|
||||||
stats_products_realtime,
|
stats_products_realtime,
|
||||||
@@ -66,8 +44,3 @@ urlpatterns += [
|
|||||||
]
|
]
|
||||||
# Root level service-worker.js
|
# Root level service-worker.js
|
||||||
urlpatterns += [re_path(r"^service-worker\.js$", serve, kwargs={"path": "dist/service-worker.js"})]
|
urlpatterns += [re_path(r"^service-worker\.js$", serve, kwargs={"path": "dist/service-worker.js"})]
|
||||||
|
|
||||||
# API
|
|
||||||
router = DefaultRouter()
|
|
||||||
router.register(r"api/products", ProductViewSet)
|
|
||||||
urlpatterns += router.urls
|
|
||||||
+1
-22
@@ -10,7 +10,7 @@ from django.shortcuts import redirect, render
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from main.forms import DepositForm, OrderForm, OrderLineForm
|
from main.forms import DepositForm, OrderForm, OrderLineForm
|
||||||
from main.models import Order, OrderLine, Product, Transaction
|
from main.models import OrderLine, Product
|
||||||
from main.utils import users_format_js, users_with_perm
|
from main.utils import users_format_js, users_with_perm
|
||||||
|
|
||||||
|
|
||||||
@@ -158,24 +158,3 @@ def deposit(request):
|
|||||||
form = DepositForm()
|
form = DepositForm()
|
||||||
|
|
||||||
return render(request, "deposit.html", locals())
|
return render(request, "deposit.html", locals())
|
||||||
|
|
||||||
|
|
||||||
def log(request, limit=datetime.now() - timedelta(days=2)):
|
|
||||||
if limit:
|
|
||||||
# display last two days of orders and transactions
|
|
||||||
orders = Order.objects.filter(created__gte=limit).order_by("-created")
|
|
||||||
transactions = Transaction.objects.filter(created__gte=limit).order_by("-created")
|
|
||||||
|
|
||||||
# no action in the last two days?
|
|
||||||
# ...then display the last 5 items
|
|
||||||
if len(orders) == 0:
|
|
||||||
orders = Order.objects.all().order_by("-created")[:5]
|
|
||||||
|
|
||||||
if len(transactions) == 0:
|
|
||||||
transactions = Transaction.objects.all().order_by("-created")[:5]
|
|
||||||
else:
|
|
||||||
# display everything
|
|
||||||
orders = Order.objects.all().order_by("-created")
|
|
||||||
transactions = Transaction.objects.all().order_by("-created")
|
|
||||||
|
|
||||||
return render(request, "log.html", locals())
|
|
||||||
+1
-88
@@ -1,96 +1,9 @@
|
|||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from itertools import groupby
|
|
||||||
|
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.shortcuts import render
|
|
||||||
from django.utils import timezone
|
|
||||||
from django.views.generic import View
|
|
||||||
|
|
||||||
from main.models import Order, OrderLine, Product
|
from main.models import OrderLine
|
||||||
|
|
||||||
|
|
||||||
def stats_list(request):
|
|
||||||
products = Product.objects.filter(active=True)
|
|
||||||
order_groups = ["hourly", "daily", "monthly", "yearly"]
|
|
||||||
|
|
||||||
return render(request, "stats.html", {"products": products, "order_groups": order_groups})
|
|
||||||
|
|
||||||
|
|
||||||
class OrdersView(View):
|
|
||||||
grouping = "orders"
|
|
||||||
|
|
||||||
def get_range(self):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def get_key(self, order):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def group_by(self, orders):
|
|
||||||
orders_grouped = dict([(key, 0) for key in self.get_range()]) # init
|
|
||||||
for key, values in groupby(orders, key=self.get_key):
|
|
||||||
count = len(list(values))
|
|
||||||
orders_grouped[key] += count
|
|
||||||
|
|
||||||
return orders_grouped
|
|
||||||
|
|
||||||
def get(self, request):
|
|
||||||
orders = Order.objects.all()
|
|
||||||
if not orders.exists():
|
|
||||||
return JsonResponse({})
|
|
||||||
|
|
||||||
orders_grouped = self.group_by(orders)
|
|
||||||
data = {
|
|
||||||
"start": str(orders[0].created),
|
|
||||||
"orders": [[k, v] for k, v in orders_grouped.items()],
|
|
||||||
"total": sum(orders_grouped.values()),
|
|
||||||
"grouping": self.grouping,
|
|
||||||
}
|
|
||||||
return JsonResponse(data)
|
|
||||||
|
|
||||||
|
|
||||||
class OrdersHourlyView(OrdersView):
|
|
||||||
grouping = "hourly"
|
|
||||||
|
|
||||||
def get_range(self):
|
|
||||||
return range(0, 24)
|
|
||||||
|
|
||||||
def get_key(self, order):
|
|
||||||
return order.created.hour
|
|
||||||
|
|
||||||
|
|
||||||
class OrdersDailyView(OrdersView):
|
|
||||||
grouping = "daily"
|
|
||||||
|
|
||||||
def get_range(self):
|
|
||||||
return range(0, 7)
|
|
||||||
|
|
||||||
def get_key(self, order):
|
|
||||||
return order.created.weekday()
|
|
||||||
|
|
||||||
|
|
||||||
class OrdersMonthlyView(OrdersView):
|
|
||||||
grouping = "monthly"
|
|
||||||
|
|
||||||
def get_range(self):
|
|
||||||
return range(1, 13)
|
|
||||||
|
|
||||||
def get_key(self, order):
|
|
||||||
return order.created.month
|
|
||||||
|
|
||||||
|
|
||||||
class OrdersYearlyView(OrdersView):
|
|
||||||
grouping = "yearly"
|
|
||||||
|
|
||||||
def get_range(self):
|
|
||||||
first = Order.objects.order_by("created").first()
|
|
||||||
last = timezone.now().year
|
|
||||||
first = first.created.year if first else last
|
|
||||||
|
|
||||||
return range(first, last + 1)
|
|
||||||
|
|
||||||
def get_key(self, order):
|
|
||||||
return order.created.year
|
|
||||||
|
|
||||||
|
|
||||||
def stats_products_realtime(request):
|
def stats_products_realtime(request):
|
||||||
|
|||||||
Generated
+60
-72
@@ -1,10 +1,10 @@
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "asgiref"
|
name = "asgiref"
|
||||||
version = "3.4.1"
|
version = "3.5.0"
|
||||||
description = "ASGI specs, helper code, and adapters"
|
description = "ASGI specs, helper code, and adapters"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"]
|
tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"]
|
||||||
@@ -83,7 +83,7 @@ python-versions = ">=3.6.1"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "charset-normalizer"
|
name = "charset-normalizer"
|
||||||
version = "2.0.10"
|
version = "2.0.11"
|
||||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -121,7 +121,7 @@ python-versions = "*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django"
|
name = "django"
|
||||||
version = "3.2.11"
|
version = "3.2.12"
|
||||||
description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
|
description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -158,17 +158,6 @@ python-versions = ">=3.6"
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
Django = ">=2.2"
|
Django = ">=2.2"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "djangorestframework"
|
|
||||||
version = "3.12.4"
|
|
||||||
description = "Web APIs for Django, made easy."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.5"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
django = ">=2.2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "easy-thumbnails"
|
name = "easy-thumbnails"
|
||||||
version = "2.7.2"
|
version = "2.7.2"
|
||||||
@@ -228,11 +217,11 @@ tornado = ["tornado (>=0.2)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "identify"
|
name = "identify"
|
||||||
version = "2.4.4"
|
version = "2.4.8"
|
||||||
description = "File identification library for Python"
|
description = "File identification library for Python"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6.1"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
license = ["ukkonen"]
|
license = ["ukkonen"]
|
||||||
@@ -312,7 +301,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pillow"
|
name = "pillow"
|
||||||
version = "9.0.0"
|
version = "9.0.1"
|
||||||
description = "Python Imaging Library (Fork)"
|
description = "Python Imaging Library (Fork)"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -344,7 +333,7 @@ testing = ["pytest", "pytest-benchmark"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pre-commit"
|
name = "pre-commit"
|
||||||
version = "2.16.0"
|
version = "2.17.0"
|
||||||
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -376,7 +365,7 @@ python-versions = ">=3.5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyparsing"
|
name = "pyparsing"
|
||||||
version = "3.0.6"
|
version = "3.0.7"
|
||||||
description = "Python parsing module"
|
description = "Python parsing module"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -614,7 +603,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtualenv"
|
name = "virtualenv"
|
||||||
version = "20.13.0"
|
version = "20.13.1"
|
||||||
description = "Virtual Python Environment builder"
|
description = "Virtual Python Environment builder"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -633,12 +622,12 @@ testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)",
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.9"
|
python-versions = "^3.9"
|
||||||
content-hash = "60442762009c623d4b11858aeee04ea967f75683fd7790a3d950ef96c29ef623"
|
content-hash = "e300d4b1a6c0bf5aca9a2bf5e64a9fd0ab275777a11b79f3dba53ccd1dd87236"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
asgiref = [
|
asgiref = [
|
||||||
{file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"},
|
{file = "asgiref-3.5.0-py3-none-any.whl", hash = "sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9"},
|
||||||
{file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"},
|
{file = "asgiref-3.5.0.tar.gz", hash = "sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0"},
|
||||||
]
|
]
|
||||||
atomicwrites = [
|
atomicwrites = [
|
||||||
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
|
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
|
||||||
@@ -665,8 +654,8 @@ cfgv = [
|
|||||||
{file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
|
{file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
|
||||||
]
|
]
|
||||||
charset-normalizer = [
|
charset-normalizer = [
|
||||||
{file = "charset-normalizer-2.0.10.tar.gz", hash = "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd"},
|
{file = "charset-normalizer-2.0.11.tar.gz", hash = "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c"},
|
||||||
{file = "charset_normalizer-2.0.10-py3-none-any.whl", hash = "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455"},
|
{file = "charset_normalizer-2.0.11-py3-none-any.whl", hash = "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45"},
|
||||||
]
|
]
|
||||||
click = [
|
click = [
|
||||||
{file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"},
|
{file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"},
|
||||||
@@ -681,8 +670,8 @@ distlib = [
|
|||||||
{file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"},
|
{file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"},
|
||||||
]
|
]
|
||||||
django = [
|
django = [
|
||||||
{file = "Django-3.2.11-py3-none-any.whl", hash = "sha256:0a0a37f0b93aef30c4bf3a839c187e1175bcdeb7e177341da0cb7b8194416891"},
|
{file = "Django-3.2.12-py3-none-any.whl", hash = "sha256:9b06c289f9ba3a8abea16c9c9505f25107809fb933676f6c891ded270039d965"},
|
||||||
{file = "Django-3.2.11.tar.gz", hash = "sha256:69c94abe5d6b1b088bf475e09b7b74403f943e34da107e798465d2045da27e75"},
|
{file = "Django-3.2.12.tar.gz", hash = "sha256:9772e6935703e59e993960832d66a614cf0233a1c5123bc6224ecc6ad69e41e2"},
|
||||||
]
|
]
|
||||||
django-cors-headers = [
|
django-cors-headers = [
|
||||||
{file = "django-cors-headers-3.11.0.tar.gz", hash = "sha256:eb98389bf7a2afc5d374806af4a9149697e3a6955b5a2dc2bf049f7d33647456"},
|
{file = "django-cors-headers-3.11.0.tar.gz", hash = "sha256:eb98389bf7a2afc5d374806af4a9149697e3a6955b5a2dc2bf049f7d33647456"},
|
||||||
@@ -692,10 +681,6 @@ django-extensions = [
|
|||||||
{file = "django-extensions-3.1.5.tar.gz", hash = "sha256:28e1e1bf49f0e00307ba574d645b0af3564c981a6dfc87209d48cb98f77d0b1a"},
|
{file = "django-extensions-3.1.5.tar.gz", hash = "sha256:28e1e1bf49f0e00307ba574d645b0af3564c981a6dfc87209d48cb98f77d0b1a"},
|
||||||
{file = "django_extensions-3.1.5-py3-none-any.whl", hash = "sha256:9238b9e016bb0009d621e05cf56ea8ce5cce9b32e91ad2026996a7377ca28069"},
|
{file = "django_extensions-3.1.5-py3-none-any.whl", hash = "sha256:9238b9e016bb0009d621e05cf56ea8ce5cce9b32e91ad2026996a7377ca28069"},
|
||||||
]
|
]
|
||||||
djangorestframework = [
|
|
||||||
{file = "djangorestframework-3.12.4-py3-none-any.whl", hash = "sha256:6d1d59f623a5ad0509fe0d6bfe93cbdfe17b8116ebc8eda86d45f6e16e819aaf"},
|
|
||||||
{file = "djangorestframework-3.12.4.tar.gz", hash = "sha256:f747949a8ddac876e879190df194b925c177cdeb725a099db1460872f7c0a7f2"},
|
|
||||||
]
|
|
||||||
easy-thumbnails = [
|
easy-thumbnails = [
|
||||||
{file = "easy-thumbnails-2.7.2.tar.gz", hash = "sha256:a7dd9cf97efaf70ba5d76484a962f08ba65b31f1681bc417257743650e9e8a8a"},
|
{file = "easy-thumbnails-2.7.2.tar.gz", hash = "sha256:a7dd9cf97efaf70ba5d76484a962f08ba65b31f1681bc417257743650e9e8a8a"},
|
||||||
{file = "easy_thumbnails-2.7.2-py3-none-any.whl", hash = "sha256:9d7ed56a9b57aba7a8d0e03dc3b8507ca51aab5e0ed0bc705c3261ff1f659192"},
|
{file = "easy_thumbnails-2.7.2-py3-none-any.whl", hash = "sha256:9d7ed56a9b57aba7a8d0e03dc3b8507ca51aab5e0ed0bc705c3261ff1f659192"},
|
||||||
@@ -718,8 +703,8 @@ gunicorn = [
|
|||||||
{file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"},
|
{file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"},
|
||||||
]
|
]
|
||||||
identify = [
|
identify = [
|
||||||
{file = "identify-2.4.4-py2.py3-none-any.whl", hash = "sha256:aa68609c7454dbcaae60a01ff6b8df1de9b39fe6e50b1f6107ec81dcda624aa6"},
|
{file = "identify-2.4.8-py2.py3-none-any.whl", hash = "sha256:a55bdd671b6063eb837af938c250ec00bba6e610454265133b0d2db7ae718d0f"},
|
||||||
{file = "identify-2.4.4.tar.gz", hash = "sha256:6b4b5031f69c48bf93a646b90de9b381c6b5f560df4cbe0ed3cf7650ae741e4d"},
|
{file = "identify-2.4.8.tar.gz", hash = "sha256:97e839c1779f07011b84c92af183e1883d9745d532d83412cca1ca76d3808c1c"},
|
||||||
]
|
]
|
||||||
idna = [
|
idna = [
|
||||||
{file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
|
{file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
|
||||||
@@ -757,38 +742,41 @@ pathspec = [
|
|||||||
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
|
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
|
||||||
]
|
]
|
||||||
pillow = [
|
pillow = [
|
||||||
{file = "Pillow-9.0.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:113723312215b25c22df1fdf0e2da7a3b9c357a7d24a93ebbe80bfda4f37a8d4"},
|
{file = "Pillow-9.0.1-1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4"},
|
||||||
{file = "Pillow-9.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bb47a548cea95b86494a26c89d153fd31122ed65255db5dcbc421a2d28eb3379"},
|
{file = "Pillow-9.0.1-1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976"},
|
||||||
{file = "Pillow-9.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31b265496e603985fad54d52d11970383e317d11e18e856971bdbb86af7242a4"},
|
{file = "Pillow-9.0.1-1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc"},
|
||||||
{file = "Pillow-9.0.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d154ed971a4cc04b93a6d5b47f37948d1f621f25de3e8fa0c26b2d44f24e3e8f"},
|
{file = "Pillow-9.0.1-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd"},
|
||||||
{file = "Pillow-9.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fe92813d208ce8aa7d76da878bdc84b90809f79ccbad2a288e9bcbeac1d9bd"},
|
{file = "Pillow-9.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f"},
|
||||||
{file = "Pillow-9.0.0-cp310-cp310-win32.whl", hash = "sha256:d5dcea1387331c905405b09cdbfb34611050cc52c865d71f2362f354faee1e9f"},
|
{file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a"},
|
||||||
{file = "Pillow-9.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:52abae4c96b5da630a8b4247de5428f593465291e5b239f3f843a911a3cf0105"},
|
{file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049"},
|
||||||
{file = "Pillow-9.0.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:72c3110228944019e5f27232296c5923398496b28be42535e3b2dc7297b6e8b6"},
|
{file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a"},
|
||||||
{file = "Pillow-9.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97b6d21771da41497b81652d44191489296555b761684f82b7b544c49989110f"},
|
{file = "Pillow-9.0.1-cp310-cp310-win32.whl", hash = "sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e"},
|
||||||
{file = "Pillow-9.0.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72f649d93d4cc4d8cf79c91ebc25137c358718ad75f99e99e043325ea7d56100"},
|
{file = "Pillow-9.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b"},
|
||||||
{file = "Pillow-9.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7aaf07085c756f6cb1c692ee0d5a86c531703b6e8c9cae581b31b562c16b98ce"},
|
{file = "Pillow-9.0.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e"},
|
||||||
{file = "Pillow-9.0.0-cp37-cp37m-win32.whl", hash = "sha256:03b27b197deb4ee400ed57d8d4e572d2d8d80f825b6634daf6e2c18c3c6ccfa6"},
|
{file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360"},
|
||||||
{file = "Pillow-9.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a09a9d4ec2b7887f7a088bbaacfd5c07160e746e3d47ec5e8050ae3b2a229e9f"},
|
{file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b"},
|
||||||
{file = "Pillow-9.0.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:490e52e99224858f154975db61c060686df8a6b3f0212a678e5d2e2ce24675c9"},
|
{file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030"},
|
||||||
{file = "Pillow-9.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:500d397ddf4bbf2ca42e198399ac13e7841956c72645513e8ddf243b31ad2128"},
|
{file = "Pillow-9.0.1-cp37-cp37m-win32.whl", hash = "sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669"},
|
||||||
{file = "Pillow-9.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ebd8b9137630a7bbbff8c4b31e774ff05bbb90f7911d93ea2c9371e41039b52"},
|
{file = "Pillow-9.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092"},
|
||||||
{file = "Pillow-9.0.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd0e5062f11cb3e730450a7d9f323f4051b532781026395c4323b8ad055523c4"},
|
{file = "Pillow-9.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204"},
|
||||||
{file = "Pillow-9.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f3b4522148586d35e78313db4db0df4b759ddd7649ef70002b6c3767d0fdeb7"},
|
{file = "Pillow-9.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e"},
|
||||||
{file = "Pillow-9.0.0-cp38-cp38-win32.whl", hash = "sha256:0b281fcadbb688607ea6ece7649c5d59d4bbd574e90db6cd030e9e85bde9fecc"},
|
{file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c"},
|
||||||
{file = "Pillow-9.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:b5050d681bcf5c9f2570b93bee5d3ec8ae4cf23158812f91ed57f7126df91762"},
|
{file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5"},
|
||||||
{file = "Pillow-9.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:c2067b3bb0781f14059b112c9da5a91c80a600a97915b4f48b37f197895dd925"},
|
{file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae"},
|
||||||
{file = "Pillow-9.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2d16b6196fb7a54aff6b5e3ecd00f7c0bab1b56eee39214b2b223a9d938c50af"},
|
{file = "Pillow-9.0.1-cp38-cp38-win32.whl", hash = "sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c"},
|
||||||
{file = "Pillow-9.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98cb63ca63cb61f594511c06218ab4394bf80388b3d66cd61d0b1f63ee0ea69f"},
|
{file = "Pillow-9.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00"},
|
||||||
{file = "Pillow-9.0.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc462d24500ba707e9cbdef436c16e5c8cbf29908278af053008d9f689f56dee"},
|
{file = "Pillow-9.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838"},
|
||||||
{file = "Pillow-9.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3586e12d874ce2f1bc875a3ffba98732ebb12e18fb6d97be482bd62b56803281"},
|
{file = "Pillow-9.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28"},
|
||||||
{file = "Pillow-9.0.0-cp39-cp39-win32.whl", hash = "sha256:68e06f8b2248f6dc8b899c3e7ecf02c9f413aab622f4d6190df53a78b93d97a5"},
|
{file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c"},
|
||||||
{file = "Pillow-9.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:6579f9ba84a3d4f1807c4aab4be06f373017fc65fff43498885ac50a9b47a553"},
|
{file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b"},
|
||||||
{file = "Pillow-9.0.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:47f5cf60bcb9fbc46011f75c9b45a8b5ad077ca352a78185bd3e7f1d294b98bb"},
|
{file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7"},
|
||||||
{file = "Pillow-9.0.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fd8053e1f8ff1844419842fd474fc359676b2e2a2b66b11cc59f4fa0a301315"},
|
{file = "Pillow-9.0.1-cp39-cp39-win32.whl", hash = "sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7"},
|
||||||
{file = "Pillow-9.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c5439bfb35a89cac50e81c751317faea647b9a3ec11c039900cd6915831064d"},
|
{file = "Pillow-9.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac"},
|
||||||
{file = "Pillow-9.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95545137fc56ce8c10de646074d242001a112a92de169986abd8c88c27566a05"},
|
{file = "Pillow-9.0.1-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97"},
|
||||||
{file = "Pillow-9.0.0.tar.gz", hash = "sha256:ee6e2963e92762923956fe5d3479b1fdc3b76c83f290aad131a2f98c3df0593e"},
|
{file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56"},
|
||||||
|
{file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e"},
|
||||||
|
{file = "Pillow-9.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70"},
|
||||||
|
{file = "Pillow-9.0.1.tar.gz", hash = "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa"},
|
||||||
]
|
]
|
||||||
platformdirs = [
|
platformdirs = [
|
||||||
{file = "platformdirs-2.4.1-py3-none-any.whl", hash = "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca"},
|
{file = "platformdirs-2.4.1-py3-none-any.whl", hash = "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca"},
|
||||||
@@ -799,8 +787,8 @@ pluggy = [
|
|||||||
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
||||||
]
|
]
|
||||||
pre-commit = [
|
pre-commit = [
|
||||||
{file = "pre_commit-2.16.0-py2.py3-none-any.whl", hash = "sha256:758d1dc9b62c2ed8881585c254976d66eae0889919ab9b859064fc2fe3c7743e"},
|
{file = "pre_commit-2.17.0-py2.py3-none-any.whl", hash = "sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616"},
|
||||||
{file = "pre_commit-2.16.0.tar.gz", hash = "sha256:fe9897cac830aa7164dbd02a4e7b90cae49630451ce88464bca73db486ba9f65"},
|
{file = "pre_commit-2.17.0.tar.gz", hash = "sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a"},
|
||||||
]
|
]
|
||||||
py = [
|
py = [
|
||||||
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
|
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
|
||||||
@@ -811,8 +799,8 @@ pygments = [
|
|||||||
{file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"},
|
{file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"},
|
||||||
]
|
]
|
||||||
pyparsing = [
|
pyparsing = [
|
||||||
{file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"},
|
{file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"},
|
||||||
{file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"},
|
{file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"},
|
||||||
]
|
]
|
||||||
pytest = [
|
pytest = [
|
||||||
{file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
|
{file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
|
||||||
@@ -913,6 +901,6 @@ urllib3 = [
|
|||||||
{file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"},
|
{file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"},
|
||||||
]
|
]
|
||||||
virtualenv = [
|
virtualenv = [
|
||||||
{file = "virtualenv-20.13.0-py2.py3-none-any.whl", hash = "sha256:339f16c4a86b44240ba7223d0f93a7887c3ca04b5f9c8129da7958447d079b09"},
|
{file = "virtualenv-20.13.1-py2.py3-none-any.whl", hash = "sha256:45e1d053cad4cd453181ae877c4ffc053546ae99e7dd049b9ff1d9be7491abf7"},
|
||||||
{file = "virtualenv-20.13.0.tar.gz", hash = "sha256:d8458cf8d59d0ea495ad9b34c2599487f8a7772d796f9910858376d1600dd2dd"},
|
{file = "virtualenv-20.13.1.tar.gz", hash = "sha256:e0621bcbf4160e4e1030f05065c8834b4e93f4fcc223255db2a823440aca9c14"},
|
||||||
]
|
]
|
||||||
@@ -20,7 +20,6 @@ license = "MIT"
|
|||||||
python = "^3.9"
|
python = "^3.9"
|
||||||
django-extensions = "^3.1.3"
|
django-extensions = "^3.1.3"
|
||||||
Django = "^3.2.8"
|
Django = "^3.2.8"
|
||||||
djangorestframework = "3.12.4"
|
|
||||||
easy-thumbnails = "2.7.2"
|
easy-thumbnails = "2.7.2"
|
||||||
facebook-sdk = "3.0.0"
|
facebook-sdk = "3.0.0"
|
||||||
gunicorn = "^20.1.0"
|
gunicorn = "^20.1.0"
|
||||||
|
|||||||
@@ -1,206 +0,0 @@
|
|||||||
|
|
||||||
/* View: Stats */
|
|
||||||
|
|
||||||
var products = null;
|
|
||||||
var products_realtime_chart = null;
|
|
||||||
var products_url = '/api/products/';
|
|
||||||
var products_stat_url = '/api/products/group_by_user';
|
|
||||||
|
|
||||||
var order_base_url = '/stats/orders/{group}/';
|
|
||||||
var products_realtime_url = '/stats/orders/products_realtime';
|
|
||||||
|
|
||||||
function productFormatter() {
|
|
||||||
return '<b>'+ this.point.name +'</b>: '+ Highcharts.numberFormat(this.percentage, 1) +' %';
|
|
||||||
}
|
|
||||||
function parse_products_realtime_data(data, chart) {
|
|
||||||
for (var product in data.products) {
|
|
||||||
if (chart.get(product) === null) {
|
|
||||||
chart.addSeries({
|
|
||||||
data: [],
|
|
||||||
id: product,
|
|
||||||
name: product
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var series = chart.get(product);
|
|
||||||
_.each(data.products[product], function(point) {
|
|
||||||
if (chart.get(point[0]) === null) {
|
|
||||||
series.addPoint({
|
|
||||||
id: point[0],
|
|
||||||
x: point[0],
|
|
||||||
y: point[1]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_products_realtime_data() {
|
|
||||||
var that = this;
|
|
||||||
$.ajax( {
|
|
||||||
url: products_realtime_url,
|
|
||||||
dataType: "json",
|
|
||||||
success: function (data) {
|
|
||||||
parse_products_realtime_data(data, products_realtime_chart);
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
get_products_realtime_data();
|
|
||||||
}, 15000);
|
|
||||||
},
|
|
||||||
cache: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderProductCharts(products) {
|
|
||||||
for(var i in products) {
|
|
||||||
var render_to = 'product_chart' + products[i].id;
|
|
||||||
var series_data = products[i].counts;
|
|
||||||
series_data = _.map(series_data, function (el) { return [el.full_name, el.amount_total]; });
|
|
||||||
|
|
||||||
new Highcharts.Chart({
|
|
||||||
chart: {
|
|
||||||
renderTo: render_to,
|
|
||||||
plotBackgroundColor: null,
|
|
||||||
plotBorderWidth: null,
|
|
||||||
plotShadow: false
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
text: products[i].name
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
formatter: productFormatter
|
|
||||||
},
|
|
||||||
plotOptions: {
|
|
||||||
pie: {
|
|
||||||
allowPointSelect: true,
|
|
||||||
cursor: 'pointer',
|
|
||||||
dataLabels: {
|
|
||||||
enabled: true,
|
|
||||||
color: '#000000',
|
|
||||||
connectorColor: '#000000',
|
|
||||||
formatter: function() {
|
|
||||||
return '<b>'+ this.point.name +'</b>: ' + this.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [{
|
|
||||||
type: 'pie',
|
|
||||||
name: 'Orders',
|
|
||||||
data: series_data
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var orderFormatters = {
|
|
||||||
hourly: function() {
|
|
||||||
return this.value + ":00";
|
|
||||||
},
|
|
||||||
daily: function() {
|
|
||||||
var days = {0: 'Mandag', 1: 'Tirsdag', 2: 'Onsdag', 3: 'Torsdag', 4: 'Fredag', 5: 'Lørdag', 6: 'Søndag'};
|
|
||||||
return days[this.value];
|
|
||||||
},
|
|
||||||
monthly: function() {
|
|
||||||
var months = {
|
|
||||||
1: 'Januar', 2: 'Februar', 3: 'Mars', 4: 'April', 5: 'Mai', 6: 'Juni', 7: 'Juli',
|
|
||||||
8: 'August', 9: 'September', 10: 'Oktober', 11: 'November', 12: 'Desember'};
|
|
||||||
return months[this.value];
|
|
||||||
},
|
|
||||||
yearly: function() {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function renderOrdersGroupedChart(data) {
|
|
||||||
var grouping = data.grouping;
|
|
||||||
var render_to = 'order_chart_' + grouping;
|
|
||||||
|
|
||||||
new Highcharts.Chart({
|
|
||||||
chart: {
|
|
||||||
renderTo: render_to,
|
|
||||||
type: 'column'
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
text: 'Ordre - ' + grouping
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
formatter: function() {
|
|
||||||
return this.y + " stk";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
title: {
|
|
||||||
text: 'Ordre'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
title: {
|
|
||||||
text: 'Tid'
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
formatter: orderFormatters[grouping]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
plotOptions: {
|
|
||||||
column: {
|
|
||||||
minPointLength: 3,
|
|
||||||
colorByPoint: true
|
|
||||||
},
|
|
||||||
series: {
|
|
||||||
groupPadding: 0,
|
|
||||||
pointPadding: 0.05
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [{
|
|
||||||
name: 'Ordre',
|
|
||||||
data: data.orders
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
if( $("#stats").length > 0) {
|
|
||||||
/* TODO select data element with index 0 of each pie-chart */
|
|
||||||
|
|
||||||
/* Products */
|
|
||||||
$.getJSON(products_stat_url, function(data) {
|
|
||||||
products = data;
|
|
||||||
renderProductCharts(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Orders, grouped */
|
|
||||||
$('[data-group]').each(function () {
|
|
||||||
var url = order_base_url.replace('{group}', $(this).data('group'));
|
|
||||||
$.getJSON(url, renderOrdersGroupedChart);
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Realtime purchases */
|
|
||||||
products_realtime_chart = new Highcharts.Chart({
|
|
||||||
chart: {
|
|
||||||
renderTo: 'products_realtime_chart'
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
text: "Produkter solgt over tid"
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: "datetime"
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
title: {
|
|
||||||
text: "Antall solgt"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
plotOptions: {
|
|
||||||
series: {
|
|
||||||
marker: {
|
|
||||||
radius: 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
get_products_realtime_data();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
+2
-2
@@ -28,8 +28,8 @@
|
|||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="{% block active_register %}{% endblock %}"><a href="{% url "home" %}"><i class="glyphicon glyphicon-home white"></i> Kjøp drikke</a></li>
|
<li class="{% block active_register %}{% endblock %}"><a href="{% url "home" %}"><i class="glyphicon glyphicon-home white"></i> Kjøp drikke</a></li>
|
||||||
<li class="{% block active_deposit %}{% endblock %}"><a href="{% url "deposit" %}">Sett inn penger</a></li>
|
<li class="{% block active_deposit %}{% endblock %}"><a href="{% url "deposit" %}">Sett inn penger</a></li>
|
||||||
<li class="{% block active_log %}{% endblock %}"><a href="/log"><i class="glyphicon glyphicon-list-alt"></i> Logg</a></li>
|
<li class="{% block active_log %}{% endblock %}"><a href="{% url "log" %}"><i class="glyphicon glyphicon-list-alt"></i> Logg</a></li>
|
||||||
<li class="{% block active_stats %}{% endblock %}"><a href="/stats"><i class="glyphicon glyphicon-stats"></i> Statistikk</a></li>
|
<li class="{% block active_stats %}{% endblock %}"><a href="{% url "stats" %}"><i class="glyphicon glyphicon-stats"></i> Statistikk</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
{% if not user.is_authenticated %}
|
{% if not user.is_authenticated %}
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% block active_log %}active{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<section id="log" class="row">
|
|
||||||
{% if messages %}
|
|
||||||
<section class="row">
|
|
||||||
<div class="col-xs-4">
|
|
||||||
{% for message in messages %}
|
|
||||||
<div {% if message.tags %}class="alert alert-{{ message.tags }}"{% endif %}>{{ message }}<a class="close" data-dismiss="alert">×</a></div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{% endif %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<section id="orders">
|
|
||||||
{% if not limit %}
|
|
||||||
<h2 title="Alle registrerte ordre">Alle ordre</h2><br />
|
|
||||||
<a href="{% url 'log' %}">Vis kun siste</a>
|
|
||||||
{% else %}
|
|
||||||
<h2 title="Ordre fra de siste 2 dagene eller de 5 siste ordrene.">Siste ordre</h2><br />
|
|
||||||
<a href="{% url 'log-all' %}">Vis alle</a>
|
|
||||||
{%endif %}
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Når</th>
|
|
||||||
<th>Hvem</th>
|
|
||||||
<th>Hva</th>
|
|
||||||
<th>Sum</th>
|
|
||||||
<!--<th>Handling</th>-->
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for order in orders %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ order.created }}</td>
|
|
||||||
<td>{% if order.customer %}{% if order.customer.profile.image %}<img src="{{ order.customer.profile.image }}" class="customer" title="{{ order.customer.first_name }} {{ order.customer.last_name|slice:":1"}}" />{% else %}{{ order.customer.first_name }} {{ order.customer.last_name|slice:":1"}}{% endif %}{% else %}Ekstern{% endif %}</td>
|
|
||||||
<td>{% for line in order.orderlines.all %}
|
|
||||||
<span class="amount">{{ line.amount}}</span> <a href="#" class="product" title="{{ line.unit_price}} per">{{ line.product }}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td>
|
|
||||||
<td>{{ order.order_sum }}</td>
|
|
||||||
<!--<td><{% include "modal-delete-order.html" with order=order %}<a class="btn btn-danger" data-toggle="modal" href="#modal-order-{{order.id}}"><i class="icon-trash icon-white"></i> Slett</a></td>-->
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<section id="transactions">
|
|
||||||
{% if not limit %}
|
|
||||||
<h2 title="Alle registrerte transaksjoner">Alle transaksjoner</h2>
|
|
||||||
<br /><a href="{% url 'log' %}#transactions">Vis kun siste</a>
|
|
||||||
{% else %}
|
|
||||||
<h2 title="Transaksjoner fra de siste 2 dagene eller de 5 siste transaksjonene.">Siste transaksjoner</h2><br />
|
|
||||||
<a href="{% url 'log-all' %}#transactions">Vis alle</a>
|
|
||||||
{%endif %}
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Når</th>
|
|
||||||
<th>Hvem</th>
|
|
||||||
<th>Innskudd</th>
|
|
||||||
<!--<th>Handling</th>-->
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for t in transactions %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ t.created }}</td>
|
|
||||||
<td>{% if t.user.profile.image %}<img src="{{ t.user.profile.image }}" class="customer" title="{{ t.user.first_name }} {{ t.user.last_name|slice:":1"}}" />{% else %}{{ t.user.first_name }} {{ t.user.last_name|slice:":1"}}{% endif %}</td>
|
|
||||||
<td>{{ t.amount }}</td>
|
|
||||||
<!--<td>{% include "modal-delete-transaction.html" with t=t %}<a class="btn btn-danger" data-toggle="modal" href="#modal-trans-{{t.id}}"><i class="icon-trash icon-white"></i> Slett</a></td>-->
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% block active_stats %}active{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<section id="stats" class="row">
|
|
||||||
<section id="products_realtime" class="row">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<h2>Realtime produkter</h2>
|
|
||||||
<div id="products_realtime_chart"></div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="product" class="row">
|
|
||||||
<h2>Produkter</h2>
|
|
||||||
{% for product in products %}
|
|
||||||
<section id="product_{{ product.id }}">
|
|
||||||
<div class="col-xs-6">
|
|
||||||
<div id="product_chart{{ product.id }}"></div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{% endfor %}
|
|
||||||
</section>
|
|
||||||
<section id="order">
|
|
||||||
{% for group in order_groups %}
|
|
||||||
<section id="order_{{ group }}" class="row" data-group="{{ group }}">
|
|
||||||
<h2>{{ group|capfirst }}</h2>
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<div id="order_chart_{{ group }}"></div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{% endfor %}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
Reference in new issue
Block a user