chore: Fix most ruff issues
ignore the rest using `uvx ruff check --add-noqa`
This commit is contained in:
22 files changed
+136
-110
No files matched your search
Executable → Regular
File mode changed.
+9
-2
@@ -1,13 +1,20 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from bbs.models import *
|
from bbs.models import (
|
||||||
|
InventoryTransaction,
|
||||||
|
Order,
|
||||||
|
OrderLine,
|
||||||
|
Product,
|
||||||
|
Transaction,
|
||||||
|
UserProfile,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Product)
|
||||||
class ProductAdmin(admin.ModelAdmin):
|
class ProductAdmin(admin.ModelAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(Product, ProductAdmin)
|
|
||||||
admin.site.register(InventoryTransaction)
|
admin.site.register(InventoryTransaction)
|
||||||
admin.site.register(Order)
|
admin.site.register(Order)
|
||||||
admin.site.register(OrderLine)
|
admin.site.register(OrderLine)
|
||||||
|
|||||||
+1
-3
@@ -1,5 +1,3 @@
|
|||||||
from typing import List
|
|
||||||
|
|
||||||
import strawberry
|
import strawberry
|
||||||
|
|
||||||
|
|
||||||
@@ -19,6 +17,6 @@ class FieldError(Error):
|
|||||||
|
|
||||||
@strawberry.type
|
@strawberry.type
|
||||||
class FormErrors:
|
class FormErrors:
|
||||||
fields: List[FieldError]
|
fields: list[FieldError]
|
||||||
message: str = ""
|
message: str = ""
|
||||||
error: bool = True
|
error: bool = True
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
from typing import List
|
|
||||||
|
|
||||||
import strawberry
|
import strawberry
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
@@ -27,7 +25,7 @@ class CreateOrderSuccess:
|
|||||||
|
|
||||||
|
|
||||||
@strawberry.type
|
@strawberry.type
|
||||||
class InsufficientFunds(Error):
|
class InsufficientFunds(Error): # noqa: N818
|
||||||
amount_lacking: float
|
amount_lacking: float
|
||||||
|
|
||||||
|
|
||||||
@@ -36,7 +34,7 @@ CreateOrderResponse = strawberry.union("CreateOrderResponse", [CreateOrderSucces
|
|||||||
|
|
||||||
@strawberry.mutation
|
@strawberry.mutation
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def create_order(customer_id: ID, order_lines: List[OrderLineInput], is_external: bool = False) -> CreateOrderResponse:
|
def create_order(customer_id: ID, order_lines: list[OrderLineInput], is_external: bool = False) -> CreateOrderResponse: # noqa: FBT001
|
||||||
# clean and validate
|
# clean and validate
|
||||||
try:
|
try:
|
||||||
user = UserModel.objects.get(pk=customer_id)
|
user = UserModel.objects.get(pk=customer_id)
|
||||||
@@ -68,7 +66,8 @@ def create_order(customer_id: ID, order_lines: List[OrderLineInput], is_external
|
|||||||
|
|
||||||
if not is_external and user.profile.balance <= order_sum:
|
if not is_external and user.profile.balance <= order_sum:
|
||||||
return InsufficientFunds(
|
return InsufficientFunds(
|
||||||
message="Du har ikke nok penger på bok.", amount_lacking=abs(order_sum - user.profile.balance)
|
message="Du har ikke nok penger på bok.",
|
||||||
|
amount_lacking=abs(order_sum - user.profile.balance),
|
||||||
)
|
)
|
||||||
|
|
||||||
# create
|
# create
|
||||||
@@ -91,7 +90,7 @@ class CreateDepositSuccess:
|
|||||||
|
|
||||||
|
|
||||||
@strawberry.type
|
@strawberry.type
|
||||||
class AboveMaxSaldo(Error):
|
class AboveMaxSaldo(Error): # noqa: N818
|
||||||
max_saldo: float
|
max_saldo: float
|
||||||
above: float
|
above: float
|
||||||
|
|
||||||
@@ -118,7 +117,7 @@ def create_deposit(user_id: ID, amount: int) -> CreateDepositResponse:
|
|||||||
fields=[FieldError(field="amount", message=message)],
|
fields=[FieldError(field="amount", message=message)],
|
||||||
)
|
)
|
||||||
# 1337 is special <3
|
# 1337 is special <3
|
||||||
if amount + user.profile.balance > settings.BBS_SALDO_MAX and amount + user.profile.balance != 1337:
|
if amount + user.profile.balance > settings.BBS_SALDO_MAX and amount + user.profile.balance != 1337: # noqa: PLR2004
|
||||||
return AboveMaxSaldo(
|
return AboveMaxSaldo(
|
||||||
message="Du prøver å sette inn for mye penger",
|
message="Du prøver å sette inn for mye penger",
|
||||||
max_saldo=settings.BBS_SALDO_MAX,
|
max_saldo=settings.BBS_SALDO_MAX,
|
||||||
|
|||||||
@@ -19,9 +19,12 @@ class UserInput:
|
|||||||
|
|
||||||
@strawberry.mutation
|
@strawberry.mutation
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def register_mutation(input: UserInput) -> User:
|
def register_mutation(input: UserInput) -> User: # noqa: A002
|
||||||
user = DjangoUser.objects.create_user(
|
user = DjangoUser.objects.create_user(
|
||||||
first_name=input.first_name, last_name=input.last_name, email=input.email, username=input.email
|
first_name=input.first_name,
|
||||||
|
last_name=input.last_name,
|
||||||
|
email=input.email,
|
||||||
|
username=input.email,
|
||||||
)
|
)
|
||||||
models.UserProfile.objects.create(user=user)
|
models.UserProfile.objects.create(user=user)
|
||||||
return user
|
return user
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
from typing import List
|
|
||||||
|
|
||||||
import strawberry
|
import strawberry
|
||||||
import strawberry_django
|
import strawberry_django
|
||||||
|
|
||||||
@@ -8,4 +6,4 @@ from bbs.api.types.inventory import Transaction, TransactionOrdering
|
|||||||
|
|
||||||
@strawberry.type
|
@strawberry.type
|
||||||
class InventoryQueries:
|
class InventoryQueries:
|
||||||
transaction_list: List[Transaction] = strawberry_django.field(pagination=True, order=TransactionOrdering)
|
transaction_list: list[Transaction] = strawberry_django.field(pagination=True, order=TransactionOrdering)
|
||||||
+17
-8
@@ -1,17 +1,23 @@
|
|||||||
from typing import List
|
|
||||||
|
|
||||||
import strawberry
|
import strawberry
|
||||||
import strawberry_django
|
import strawberry_django
|
||||||
|
|
||||||
from bbs import models
|
from bbs import models
|
||||||
from bbs.api.types.shop import Order, OrderOrdering, OrderStats, OrderStatsByTime, Point, Product, ProductOrderStat
|
from bbs.api.types.shop import (
|
||||||
|
Order,
|
||||||
|
OrderOrdering,
|
||||||
|
OrderStats,
|
||||||
|
OrderStatsByTime,
|
||||||
|
Point,
|
||||||
|
Product,
|
||||||
|
ProductOrderStat,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@strawberry.type
|
@strawberry.type
|
||||||
class ShopQueries:
|
class ShopQueries:
|
||||||
all_products: List[Product] = strawberry_django.field()
|
all_products: list[Product] = strawberry_django.field()
|
||||||
all_orders: List[Order] = strawberry_django.field()
|
all_orders: list[Order] = strawberry_django.field()
|
||||||
order_list: List[Order] = strawberry_django.field(pagination=True, order=OrderOrdering)
|
order_list: list[Order] = strawberry_django.field(pagination=True, order=OrderOrdering)
|
||||||
|
|
||||||
@strawberry.field
|
@strawberry.field
|
||||||
def order_stats(self) -> OrderStats:
|
def order_stats(self) -> OrderStats:
|
||||||
@@ -26,8 +32,11 @@ class ShopQueries:
|
|||||||
)
|
)
|
||||||
|
|
||||||
@strawberry.field
|
@strawberry.field
|
||||||
def product_stats(self) -> List[ProductOrderStat]:
|
def product_stats(self) -> list[ProductOrderStat]:
|
||||||
return [
|
return [
|
||||||
ProductOrderStat(product_name=stat["product_name"], data=[Point(**p) for p in stat["data"]])
|
ProductOrderStat(
|
||||||
|
product_name=stat["product_name"],
|
||||||
|
data=[Point(**p) for p in stat["data"]],
|
||||||
|
)
|
||||||
for stat in models.OrderLine.objects.product_order_stats().as_series()
|
for stat in models.OrderLine.objects.product_order_stats().as_series()
|
||||||
]
|
]
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
from typing import List
|
|
||||||
|
|
||||||
import strawberry
|
import strawberry
|
||||||
import strawberry_django
|
import strawberry_django
|
||||||
from django.contrib.auth.models import User as DjangoUser
|
from django.contrib.auth.models import User as DjangoUser
|
||||||
@@ -10,7 +8,7 @@ from bbs.api.types.users import User
|
|||||||
|
|
||||||
@strawberry.type
|
@strawberry.type
|
||||||
class UsersQueries:
|
class UsersQueries:
|
||||||
all_users: List[User] = strawberry_django.field()
|
all_users: list[User] = strawberry_django.field()
|
||||||
|
|
||||||
@strawberry.field
|
@strawberry.field
|
||||||
def user(self, user_id: ID) -> User:
|
def user(self, user_id: ID) -> User:
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import strawberry_django
|
import strawberry_django
|
||||||
from strawberry_django import auto
|
from strawberry_django import auto
|
||||||
|
|
||||||
from bbs import models
|
from bbs import models
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
from bbs.api.types.users import User
|
from bbs.api.types.users import User
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
from typing import List
|
|
||||||
|
|
||||||
import strawberry
|
import strawberry
|
||||||
import strawberry_django
|
import strawberry_django
|
||||||
from strawberry_django import auto
|
from strawberry_django import auto
|
||||||
@@ -33,10 +31,10 @@ class OrderOrdering:
|
|||||||
@strawberry_django.type(models.Order)
|
@strawberry_django.type(models.Order)
|
||||||
class Order:
|
class Order:
|
||||||
id: auto
|
id: auto
|
||||||
customer: strawberry.LazyType["User", "bbs.api.types.users"]
|
customer: strawberry.LazyType["User", "bbs.api.types.users"] # noqa: F821
|
||||||
order_sum: auto
|
order_sum: auto
|
||||||
created: auto
|
created: auto
|
||||||
orderlines: List["OrderLine"]
|
orderlines: list["OrderLine"]
|
||||||
is_external: bool
|
is_external: bool
|
||||||
|
|
||||||
|
|
||||||
@@ -57,10 +55,10 @@ class OrderStatsByTime:
|
|||||||
|
|
||||||
@strawberry.type
|
@strawberry.type
|
||||||
class OrderStats:
|
class OrderStats:
|
||||||
yearly: List[OrderStatsByTime]
|
yearly: list[OrderStatsByTime]
|
||||||
monthly: List[OrderStatsByTime]
|
monthly: list[OrderStatsByTime]
|
||||||
daily: List[OrderStatsByTime]
|
daily: list[OrderStatsByTime]
|
||||||
hourly: List[OrderStatsByTime]
|
hourly: list[OrderStatsByTime]
|
||||||
|
|
||||||
|
|
||||||
@strawberry.type
|
@strawberry.type
|
||||||
@@ -72,4 +70,4 @@ class Point:
|
|||||||
@strawberry.type
|
@strawberry.type
|
||||||
class ProductOrderStat:
|
class ProductOrderStat:
|
||||||
product_name: str
|
product_name: str
|
||||||
data: List[Point]
|
data: list[Point]
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import List
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
import strawberry
|
import strawberry
|
||||||
@@ -29,13 +28,16 @@ class UserProfile:
|
|||||||
order_sum_total: Decimal
|
order_sum_total: Decimal
|
||||||
|
|
||||||
@strawberry.field()
|
@strawberry.field()
|
||||||
def top_months(self) -> List[TopMonth]:
|
def top_months(self) -> list[TopMonth]:
|
||||||
return [TopMonth(**month) for month in self.top_months()]
|
return [TopMonth(**month) for month in self.top_months()]
|
||||||
|
|
||||||
@strawberry.field()
|
@strawberry.field()
|
||||||
def product_order_stats(self) -> List[ProductOrderStat]:
|
def product_order_stats(self) -> list[ProductOrderStat]:
|
||||||
return [
|
return [
|
||||||
ProductOrderStat(product_name=stat["product_name"], data=[Point(**p) for p in stat["data"]])
|
ProductOrderStat(
|
||||||
|
product_name=stat["product_name"],
|
||||||
|
data=[Point(**p) for p in stat["data"]],
|
||||||
|
)
|
||||||
for stat in self.product_order_stats().as_series()
|
for stat in self.product_order_stats().as_series()
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
+8
-2
@@ -5,12 +5,18 @@ from bbs.models import InventoryTransaction, Product
|
|||||||
MAX_DIGITS = 9
|
MAX_DIGITS = 9
|
||||||
DECIMAL_PLACES = 1
|
DECIMAL_PLACES = 1
|
||||||
|
|
||||||
|
|
||||||
class InventoryTransactionForm(forms.ModelForm):
|
class InventoryTransactionForm(forms.ModelForm):
|
||||||
unit_price = forms.DecimalField(max_digits=MAX_DIGITS, decimal_places=DECIMAL_PLACES, required=True, localize=True)
|
unit_price = forms.DecimalField(
|
||||||
|
max_digits=MAX_DIGITS,
|
||||||
|
decimal_places=DECIMAL_PLACES,
|
||||||
|
required=True,
|
||||||
|
localize=True,
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
# Only show active products
|
# Only show active products
|
||||||
super(InventoryTransactionForm, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.fields["product"].queryset = Product.objects.filter(active=True)
|
self.fields["product"].queryset = Product.objects.filter(active=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ class Command(BaseCommand):
|
|||||||
def add_arguments(self, parser: CommandParser):
|
def add_arguments(self, parser: CommandParser):
|
||||||
parser.add_argument("--filename", default="schema.graphql", help="`-` prints to stdout")
|
parser.add_argument("--filename", default="schema.graphql", help="`-` prints to stdout")
|
||||||
|
|
||||||
def handle(self, *args, filename=None, **options):
|
def handle(self, *args, filename=None, **options): # noqa: ARG002
|
||||||
schema_output = print_schema(schema_symbol)
|
schema_output = print_schema(schema_symbol)
|
||||||
if filename != "-":
|
if filename != "-":
|
||||||
with Path(settings.BASE_DIR, filename).open("w+") as fp:
|
with Path(settings.BASE_DIR, filename).open("w+") as fp:
|
||||||
fp.write(schema_output)
|
fp.write(schema_output)
|
||||||
self.stdout.write(self.style.SUCCESS("OK"))
|
self.stdout.write(self.style.SUCCESS("OK"))
|
||||||
else:
|
else:
|
||||||
print(schema_output)
|
pass
|
||||||
@@ -10,11 +10,10 @@ class Command(BaseCommand):
|
|||||||
parser.add_argument("--dry-run", action="store_true")
|
parser.add_argument("--dry-run", action="store_true")
|
||||||
parser.add_argument("--force", action="store_true")
|
parser.add_argument("--force", action="store_true")
|
||||||
|
|
||||||
def handle(self, *args, dry_run=False, force=False, **options):
|
def handle(self, *args, dry_run=False, force=False, **options): # noqa: ARG002
|
||||||
for profile in UserProfile.objects.all().order_by("id"):
|
for profile in UserProfile.objects.all().order_by("id"):
|
||||||
if dry_run:
|
if dry_run:
|
||||||
print(profile.user.email, profile.image_url())
|
pass
|
||||||
else:
|
elif force or not profile.image:
|
||||||
if force or not profile.image:
|
|
||||||
profile.image = profile.image_url()
|
profile.image = profile.image_url()
|
||||||
profile.save()
|
profile.save()
|
||||||
@@ -3,7 +3,6 @@ from django.db import migrations, models
|
|||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
]
|
]
|
||||||
@@ -180,6 +179,6 @@ class Migration(migrations.Migration):
|
|||||||
),
|
),
|
||||||
migrations.AlterUniqueTogether(
|
migrations.AlterUniqueTogether(
|
||||||
name="orderline",
|
name="orderline",
|
||||||
unique_together=set([("order", "product")]),
|
unique_together={("order", "product")},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
@@ -4,7 +4,6 @@ from django.db import migrations, models
|
|||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("bbs", "0001_initial"),
|
("bbs", "0001_initial"),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -4,15 +4,14 @@ from django.db import migrations, models
|
|||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('bbs', '0002_alter_inventorytransaction_amount_and_more'),
|
("bbs", "0002_alter_inventorytransaction_amount_and_more"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='order',
|
model_name="order",
|
||||||
name='order_sum',
|
name="order_sum",
|
||||||
field=models.DecimalField(db_column='sum', decimal_places=1, max_digits=9),
|
field=models.DecimalField(db_column="sum", decimal_places=1, max_digits=9),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
+20
-17
@@ -1,8 +1,7 @@
|
|||||||
import hashlib
|
import hashlib # noqa: EXE002
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from itertools import groupby
|
|
||||||
from typing import Type
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
from itertools import groupby
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
@@ -87,21 +86,26 @@ class Product(models.Model):
|
|||||||
|
|
||||||
return _format_counts(per_user)
|
return _format_counts(per_user)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self): # noqa: DJ012
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Meta:
|
class Meta: # noqa: DJ012
|
||||||
ordering = ["name"]
|
ordering = ["name"]
|
||||||
|
|
||||||
|
|
||||||
class OrderManager(models.Manager):
|
class OrderManager(models.Manager):
|
||||||
def count_by_created(self, extract_class: Type[Extract]):
|
def count_by_created(self, extract_class: type[Extract]):
|
||||||
period = extract_class("created")
|
period = extract_class("created")
|
||||||
return self.get_queryset().annotate(period=period).values("period").annotate(count=Count("id"))
|
return self.get_queryset().annotate(period=period).values("period").annotate(count=Count("id"))
|
||||||
|
|
||||||
def count_by_created_period(self, period: str):
|
def count_by_created_period(self, period: str):
|
||||||
periods = {"yearly": ExtractYear, "monthly": ExtractMonth, "daily": ExtractIsoWeekDay, "hourly": ExtractHour}
|
periods = {
|
||||||
assert period in periods
|
"yearly": ExtractYear,
|
||||||
|
"monthly": ExtractMonth,
|
||||||
|
"daily": ExtractIsoWeekDay,
|
||||||
|
"hourly": ExtractHour,
|
||||||
|
}
|
||||||
|
assert period in periods # noqa: S101
|
||||||
return self.count_by_created(periods[period])
|
return self.count_by_created(periods[period])
|
||||||
|
|
||||||
|
|
||||||
@@ -124,7 +128,7 @@ class Order(models.Model):
|
|||||||
def reciept(self):
|
def reciept(self):
|
||||||
return ", ".join([str(ol) for ol in self.orderlines.all()])
|
return ", ".join([str(ol) for ol in self.orderlines.all()])
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self): # noqa: DJ012
|
||||||
return f"{self.customer or EXTERNAL_USER}: {self.order_sum} kr"
|
return f"{self.customer or EXTERNAL_USER}: {self.order_sum} kr"
|
||||||
|
|
||||||
|
|
||||||
@@ -163,10 +167,10 @@ class OrderLine(models.Model):
|
|||||||
def price(self):
|
def price(self):
|
||||||
return self.amount * self.unit_price
|
return self.amount * self.unit_price
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self): # noqa: DJ012
|
||||||
return f"{self.amount} {self.product} ({self.unit_price} kr per)"
|
return f"{self.amount} {self.product} ({self.unit_price} kr per)"
|
||||||
|
|
||||||
class Meta:
|
class Meta: # noqa: DJ012
|
||||||
unique_together = ("order", "product")
|
unique_together = ("order", "product")
|
||||||
|
|
||||||
|
|
||||||
@@ -206,7 +210,7 @@ class InventoryTransaction(models.Model):
|
|||||||
def price(self):
|
def price(self):
|
||||||
return self.amount * self.unit_price
|
return self.amount * self.unit_price
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self): # noqa: DJ012
|
||||||
return f"{self.id}: {self.user}: {self.product}. {self.amount:.0f} stykker ({self.unit_price} kr per)"
|
return f"{self.id}: {self.user}: {self.product}. {self.amount:.0f} stykker ({self.unit_price} kr per)"
|
||||||
|
|
||||||
|
|
||||||
@@ -220,8 +224,7 @@ class UserProfile(models.Model):
|
|||||||
|
|
||||||
def last_purchase_date(self) -> datetime:
|
def last_purchase_date(self) -> datetime:
|
||||||
last = self.last_purchase()
|
last = self.last_purchase()
|
||||||
last_p = last.created if last else datetime.min
|
return last.created if last else datetime.min # noqa: DTZ901
|
||||||
return last_p
|
|
||||||
|
|
||||||
def top_months(self, limit=5):
|
def top_months(self, limit=5):
|
||||||
return (
|
return (
|
||||||
@@ -240,16 +243,16 @@ class UserProfile(models.Model):
|
|||||||
|
|
||||||
def image_url(self) -> str:
|
def image_url(self) -> str:
|
||||||
if self.user.email:
|
if self.user.email:
|
||||||
md5_hash = hashlib.md5(self.user.email.lower().strip().encode()).hexdigest()
|
md5_hash = hashlib.md5(self.user.email.lower().strip().encode()).hexdigest() # noqa: S324
|
||||||
return f"https://www.gravatar.com/avatar/{md5_hash}?d=identicon"
|
return f"https://www.gravatar.com/avatar/{md5_hash}?d=identicon"
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(self, **kwargs): # noqa: DJ012
|
||||||
if not self.image:
|
if not self.image:
|
||||||
self.image = self.image_url()
|
self.image = self.image_url()
|
||||||
|
|
||||||
super().save(**kwargs)
|
super().save(**kwargs)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self): # noqa: DJ012
|
||||||
return f"{self.user}"
|
return f"{self.user}"
|
||||||
+11
-13
@@ -1,12 +1,13 @@
|
|||||||
# Django settings for bbs project.
|
# Django settings for bbs project. # noqa: EXE002
|
||||||
|
import contextlib
|
||||||
import os
|
import os
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # noqa: PTH120
|
||||||
|
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
|
||||||
ADMINS = (
|
ADMINS = (
|
||||||
# ('Your Name', 'your_email@example.com'),
|
# ('Your Name', 'your_email@example.com'), # noqa: ERA001
|
||||||
)
|
)
|
||||||
MANAGERS = ADMINS
|
MANAGERS = ADMINS
|
||||||
|
|
||||||
@@ -20,18 +21,17 @@ DATABASES = {
|
|||||||
TIME_ZONE = "Europe/Oslo"
|
TIME_ZONE = "Europe/Oslo"
|
||||||
LANGUAGE_CODE = "nb"
|
LANGUAGE_CODE = "nb"
|
||||||
USE_I18N = True
|
USE_I18N = True
|
||||||
USE_L10N = True
|
|
||||||
|
|
||||||
SITE_ID = 1
|
SITE_ID = 1
|
||||||
|
|
||||||
# Media and uploads
|
# Media and uploads
|
||||||
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
|
MEDIA_ROOT = os.path.join(BASE_DIR, "media") # noqa: PTH118
|
||||||
MEDIA_URL = "/media/"
|
MEDIA_URL = "/media/"
|
||||||
|
|
||||||
# Static files
|
# Static files
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
|
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") # noqa: PTH118
|
||||||
STATIC_URL = "/static/"
|
STATIC_URL = "/static/"
|
||||||
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
|
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),) # noqa: PTH118
|
||||||
|
|
||||||
STATICFILES_FINDERS = (
|
STATICFILES_FINDERS = (
|
||||||
"django.contrib.staticfiles.finders.FileSystemFinder",
|
"django.contrib.staticfiles.finders.FileSystemFinder",
|
||||||
@@ -39,13 +39,13 @@ STATICFILES_FINDERS = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Make this unique, and don't share it with anybody.
|
# Make this unique, and don't share it with anybody.
|
||||||
SECRET_KEY = "osv$uy-ea$*%lc)+xiwt5@2b7au%u*c!pa6hmh#vl)*+tp%fss"
|
SECRET_KEY = "osv$uy-ea$*%lc)+xiwt5@2b7au%u*c!pa6hmh#vl)*+tp%fss" # noqa: S105
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||||
"DIRS": [
|
"DIRS": [
|
||||||
os.path.join(BASE_DIR, "templates"),
|
os.path.join(BASE_DIR, "templates"), # noqa: PTH118
|
||||||
],
|
],
|
||||||
"APP_DIRS": True,
|
"APP_DIRS": True,
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
@@ -141,7 +141,5 @@ CORS_ALLOWED_ORIGINS = [
|
|||||||
"http://localhost:3000",
|
"http://localhost:3000",
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
with contextlib.suppress(ImportError):
|
||||||
from .local_settings import *
|
from .local_settings import * # noqa: F403
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import pytest
|
import pytest # noqa: INP001
|
||||||
from django.test import Client
|
from django.test import Client
|
||||||
from strawberry.django.test import GraphQLTestClient
|
from strawberry.django.test import GraphQLTestClient
|
||||||
|
|
||||||
@@ -7,17 +7,21 @@ from bbs.models import Order, Product
|
|||||||
|
|
||||||
@pytest.fixture(name="gql_client")
|
@pytest.fixture(name="gql_client")
|
||||||
def gql_client_fixture(client: Client):
|
def gql_client_fixture(client: Client):
|
||||||
yield GraphQLTestClient(client)
|
return GraphQLTestClient(client)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="product")
|
@pytest.fixture(name="product")
|
||||||
def product_fix(db):
|
def product_fix(db): # noqa: ARG001
|
||||||
return Product.objects.create(name="borg", sale_price_ext=35, sale_price_int=30)
|
return Product.objects.create(name="borg", sale_price_ext=35, sale_price_int=30)
|
||||||
|
|
||||||
|
|
||||||
def test_create_order(product, gql_client):
|
def test_create_order(product, gql_client):
|
||||||
assert Order.objects.count() == 0
|
assert Order.objects.count() == 0
|
||||||
variables = dict(customerId="external", isExternal=True, orderLines=[{"productId": product.id, "amount": 1}])
|
variables = {
|
||||||
|
"customerId": "external",
|
||||||
|
"isExternal": True,
|
||||||
|
"orderLines": [{"productId": product.id, "amount": 1}],
|
||||||
|
}
|
||||||
query = """
|
query = """
|
||||||
mutation CreateOrder($customerId: ID!, $isExternal: Boolean!, $orderLines: [OrderLineInput!]!) {
|
mutation CreateOrder($customerId: ID!, $isExternal: Boolean!, $orderLines: [OrderLineInput!]!) {
|
||||||
createOrder(customerId: $customerId, isExternal: $isExternal, orderLines: $orderLines) {
|
createOrder(customerId: $customerId, isExternal: $isExternal, orderLines: $orderLines) {
|
||||||
|
|||||||
+9
-5
@@ -2,7 +2,7 @@ from django.conf import settings
|
|||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.views import LoginView, LogoutView
|
from django.contrib.auth.views import LoginView, LogoutView
|
||||||
from django.urls import path, re_path
|
from django.urls import path
|
||||||
from strawberry.django.views import GraphQLView
|
from strawberry.django.views import GraphQLView
|
||||||
|
|
||||||
from bbs.api.schema import schema
|
from bbs.api.schema import schema
|
||||||
@@ -12,11 +12,15 @@ admin.autodiscover()
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# TODO: migrate reports to SPA
|
# TODO: migrate reports to SPA
|
||||||
re_path(r"^inventory/$", inventory, name="inventory"),
|
path("inventory/", inventory, name="inventory"),
|
||||||
re_path(r"^inventory/add/$", inventory_add, name="inventory-add"),
|
path("inventory/add/", inventory_add, name="inventory-add"),
|
||||||
re_path(r"^report$", report, name="report"),
|
path("report", report, name="report"),
|
||||||
path("accounts/login/", LoginView.as_view(), name="django.contrib.auth.views.login"),
|
path("accounts/login/", LoginView.as_view(), name="django.contrib.auth.views.login"),
|
||||||
path("accounts/logout/", LogoutView.as_view(), name="django.contrib.auth.views.logout"),
|
path(
|
||||||
|
"accounts/logout/",
|
||||||
|
LogoutView.as_view(),
|
||||||
|
name="django.contrib.auth.views.logout",
|
||||||
|
),
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
path("graphql/", GraphQLView.as_view(schema=schema), name="graphql"),
|
path("graphql/", GraphQLView.as_view(schema=schema), name="graphql"),
|
||||||
]
|
]
|
||||||
|
|||||||
+13
-14
@@ -10,12 +10,12 @@ from bbs.models import InventoryTransaction, Order, Product, Transaction, UserPr
|
|||||||
|
|
||||||
def report(request):
|
def report(request):
|
||||||
# FIXME: split this up in smaller pieces
|
# FIXME: split this up in smaller pieces
|
||||||
datetime_now = datetime.now()
|
datetime_now = datetime.now() # noqa: DTZ005
|
||||||
start_time = datetime.now() - timedelta(days=30)
|
start_time = datetime.now() - timedelta(days=30) # noqa: DTZ005
|
||||||
# start of day, 1 month
|
# start of day, 1 month
|
||||||
start_time = start_time.replace(hour=0, minute=0, second=0, microsecond=0)
|
start_time = start_time.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
# end of day
|
# end of day
|
||||||
end_time = datetime.now().replace(hour=23, minute=59, second=59, microsecond=999)
|
end_time = datetime.now().replace(hour=23, minute=59, second=59, microsecond=999) # noqa: DTZ005
|
||||||
|
|
||||||
if request.GET.get("start_time", False) or request.GET.get("end_time", False):
|
if request.GET.get("start_time", False) or request.GET.get("end_time", False):
|
||||||
form = DateRangeForm(request.GET)
|
form = DateRangeForm(request.GET)
|
||||||
@@ -50,14 +50,14 @@ def report(request):
|
|||||||
k: {
|
k: {
|
||||||
"name": k,
|
"name": k,
|
||||||
"transactions": group,
|
"transactions": group,
|
||||||
"transactions_sum": sum(map(lambda x: x["transactions__price"], group)),
|
"transactions_sum": sum(x["transactions__price"] for x in group),
|
||||||
"transactions_units": sum(map(lambda x: x["transactions__amount"], group)),
|
"transactions_units": sum(x["transactions__amount"] for x in group),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
itrans = InventoryTransaction.objects.filter(created__range=[start_time, end_time])
|
itrans = InventoryTransaction.objects.filter(created__range=[start_time, end_time])
|
||||||
inv_in = sum(map(lambda x: x[1].get("transactions_sum", 0), inventory_products.items()))
|
inv_in = sum(x[1].get("transactions_sum", 0) for x in inventory_products.items())
|
||||||
|
|
||||||
# out
|
# out
|
||||||
out_products = (
|
out_products = (
|
||||||
@@ -75,8 +75,8 @@ def report(request):
|
|||||||
product = {
|
product = {
|
||||||
"name": k,
|
"name": k,
|
||||||
"orderlines": group,
|
"orderlines": group,
|
||||||
"orderlines_sum": sum(map(lambda x: x["orderlines__price"], group)),
|
"orderlines_sum": sum(x["orderlines__price"] for x in group),
|
||||||
"orderlines_units": sum(map(lambda x: x["orderlines__amount"], group)),
|
"orderlines_units": sum(x["orderlines__amount"] for x in group),
|
||||||
}
|
}
|
||||||
if k in inventory_products:
|
if k in inventory_products:
|
||||||
# add diff
|
# add diff
|
||||||
@@ -88,7 +88,7 @@ def report(request):
|
|||||||
p[1]["value_diff"] = p[1].get("transactions_sum", 0) - p[1].get("orderlines_sum", 0)
|
p[1]["value_diff"] = p[1].get("transactions_sum", 0) - p[1].get("orderlines_sum", 0)
|
||||||
p[1]["units_diff"] = p[1].get("transactions_units", 0) - p[1].get("orderlines_units", 0)
|
p[1]["units_diff"] = p[1].get("transactions_units", 0) - p[1].get("orderlines_units", 0)
|
||||||
|
|
||||||
inv_out = sum(map(lambda x: x[1].get("orderlines_sum", 0), inventory_products.items()))
|
inv_out = sum(x[1].get("orderlines_sum", 0) for x in inventory_products.items())
|
||||||
|
|
||||||
inv_diff = inv_in - inv_out
|
inv_diff = inv_in - inv_out
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ def report(request):
|
|||||||
purchases_diff = purchases_end - purchases_start
|
purchases_diff = purchases_end - purchases_start
|
||||||
saldo_diff = saldo_end - saldo_start
|
saldo_diff = saldo_end - saldo_start
|
||||||
|
|
||||||
return render(request, "report.html", locals())
|
return render(request, "report.html", locals()) # noqa: DJ003
|
||||||
|
|
||||||
|
|
||||||
def inventory(request):
|
def inventory(request):
|
||||||
@@ -120,7 +120,7 @@ def inventory(request):
|
|||||||
wholesale_value = sum([p.wholesale_value for p in products_active])
|
wholesale_value = sum([p.wholesale_value for p in products_active])
|
||||||
num_products = sum(products_active.values_list("inventory_amount", flat=True))
|
num_products = sum(products_active.values_list("inventory_amount", flat=True))
|
||||||
|
|
||||||
return render(request, "inventory.html", locals())
|
return render(request, "inventory.html", locals()) # noqa: DJ003
|
||||||
|
|
||||||
|
|
||||||
def inventory_add(request):
|
def inventory_add(request):
|
||||||
@@ -133,13 +133,12 @@ def inventory_add(request):
|
|||||||
itrans.user = request.user
|
itrans.user = request.user
|
||||||
itrans.product.save()
|
itrans.product.save()
|
||||||
itrans.save()
|
itrans.save()
|
||||||
messages.success(request, "Satt inn {0} stk {1}.".format(itrans.amount, itrans.product))
|
messages.success(request, f"Satt inn {itrans.amount} stk {itrans.product}.")
|
||||||
return redirect("inventory-add")
|
return redirect("inventory-add")
|
||||||
|
|
||||||
else:
|
|
||||||
messages.error(request, "Feil med skjemaet, se under.")
|
messages.error(request, "Feil med skjemaet, se under.")
|
||||||
form = InventoryTransactionForm(data=request.POST)
|
form = InventoryTransactionForm(data=request.POST)
|
||||||
else:
|
else:
|
||||||
form = InventoryTransactionForm()
|
form = InventoryTransactionForm()
|
||||||
|
|
||||||
return render(request, "inventory_add.html", locals())
|
return render(request, "inventory_add.html", locals()) # noqa: DJ003
|
||||||
Reference in new issue
Block a user