Skip to content

Commit

Permalink
Mypy errors fix (#373)
Browse files Browse the repository at this point in the history
* mypy errors fix

* Updated mypy settings
  • Loading branch information
Domejko authored May 21, 2024
1 parent 41b07e1 commit 83a04dc
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 16 deletions.
2 changes: 1 addition & 1 deletion backend/api/invoices/create/services/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
@require_http_methods(["POST"])
def add_service(request: HtmxHttpRequest):
context: dict = {}
existing_service = request.POST.get("existing_service", "")
existing_service = request.POST.get("existing_service", 0)

try:
existing_service_obj = InvoiceProduct.objects.get(user=request.user, id=existing_service)
Expand Down
33 changes: 20 additions & 13 deletions backend/models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from __future__ import annotations

import typing
from datetime import datetime
from decimal import Decimal
from typing import Literal
from typing import NoReturn
from typing import Literal, Union
from uuid import uuid4

from django.contrib.auth.hashers import check_password
Expand Down Expand Up @@ -358,7 +358,7 @@ def dynamic_payment_status(self):
return self.payment_status

@property
def get_to_details(self) -> tuple[str, dict[str, str]] | tuple[str, Client]:
def get_to_details(self) -> tuple[str, dict[str, str | None]] | tuple[str, Client]:
"""
Returns the client details for the invoice
"client" and Client object if client_to
Expand All @@ -378,13 +378,13 @@ def get_subtotal(self) -> Decimal:
subtotal += item.get_total_price()
return Decimal(round(subtotal, 2))

def get_tax(self, amount: Decimal = 0.00) -> Decimal:
def get_tax(self, amount: Decimal = Decimal(0.00)) -> Decimal:
amount = amount or self.get_subtotal()
if self.vat_number:
return Decimal(round(amount * Decimal(0.2), 2))
return Decimal(0)

def get_percentage_amount(self, subtotal: float = 0.00) -> Decimal:
def get_percentage_amount(self, subtotal: Decimal = Decimal(0.00)) -> Decimal:
total = subtotal or self.get_subtotal()

if self.discount_percentage > 0:
Expand All @@ -401,7 +401,7 @@ def get_total_price(self) -> Decimal:
total -= discount_amount

if 0 > total:
total = 0
total = Decimal(0)
else:
total -= self.get_tax(total)

Expand Down Expand Up @@ -649,6 +649,7 @@ def __str__(self):
return self.name

def get_quota_limit(self, user: User, quota_limit: QuotaLimit | None = None):
user_quota_override: QuotaOverrides | QuotaLimit
try:
if quota_limit:
user_quota_override = quota_limit
Expand All @@ -669,6 +670,8 @@ def get_period_usage(self, user: User):
return "Not available"

def strict_goes_above_limit(self, user: User, extra: str | int | None = None, add: int = 0) -> bool:
current: Union[int, None, QuerySet[QuotaUsage], Literal["Not Available"]]

current = self.strict_get_quotas(user, extra)
current = current.count() if current != "Not Available" else None
return current + add >= self.get_quota_limit(user) if current else False
Expand All @@ -681,35 +684,39 @@ def strict_get_quotas(
:return: QuerySet of quota usages OR "Not Available" if utilisation isn't available (e.g. per invoice you can't get in total)
"""
current = None
quota_limit = quota_limit.quota_usage if quota_limit else QuotaUsage.objects.filter(user=user, quota_limit=self)
if quota_limit is not None:
quota_lim = quota_limit.quota_usage
else:
quota_lim = QuotaUsage.objects.filter(user=user, quota_limit=self) # type: ignore[assignment]

if self.limit_type == "forever":
current = self.quota_usage.filter(user=user, quota_limit=self)
elif self.limit_type == "per_month":
current_month = timezone.now().month
current_year = timezone.now().year
current = quota_limit.filter(created_at__year=current_year, created_at__month=current_month)
current = quota_lim.filter(created_at__year=current_year, created_at__month=current_month)
elif self.limit_type == "per_day":
current_day = timezone.now().day
current_month = timezone.now().month
current_year = timezone.now().year
current = quota_limit.filter(created_at__year=current_year, created_at__month=current_month, created_at__day=current_day)
current = quota_lim.filter(created_at__year=current_year, created_at__month=current_month, created_at__day=current_day)
elif self.limit_type in ["per_client", "per_invoice", "per_team", "per_receipt", "per_quota"] and extra:
current = quota_limit.filter(extra_data=extra)
current = quota_lim.filter(extra_data=extra)
else:
return "Not Available"
return current

@classmethod
def delete_quota_usage(cls, quota_limit: str | QuotaLimit, user: User, extra, timestamp=None) -> NoReturn:
@typing.no_type_check
def delete_quota_usage(cls, quota_limit: str | QuotaLimit, user: User, extra, timestamp=None):
quota_limit = cls.objects.get(slug=quota_limit) if isinstance(quota_limit, str) else quota_limit

all_usages = quota_limit.strict_get_quotas(user, extra)
closest_obj = None

if all_usages.count() > 1 and timestamp:
earliest: QuotaUsage = all_usages.filter(created_at__gte=timestamp).order_by("created_at").first()
latest: QuotaUsage = all_usages.filter(created_at__lte=timestamp).order_by("created_at").last()
earliest: QuotaUsage | None = all_usages.filter(created_at__gte=timestamp).order_by("created_at").first()
latest: QuotaUsage | None = all_usages.filter(created_at__lte=timestamp).order_by("created_at").last()

if earliest and latest:
time_until_soonest_obj = abs(earliest.created_at - timestamp)
Expand Down
2 changes: 1 addition & 1 deletion backend/views/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
from .auth import login
from .settings import view as settings_view, teams
from .invoices import dashboard as invoices_dashboard, create, view as invoices_view, manage_access
from .clients import dashboard as clients_dashboard, create
from .clients import dashboard as clients_dashboard, create as create_client
from .receipts import dashboard as receipts_dashboard
2 changes: 1 addition & 1 deletion backend/views/core/auth/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def login_manual(request: HtmxAnyHttpRequest): # HTMX POST
messages.error(request, "Incorrect email or password")
return render_toast_message(request)

if user.awaiting_email_verification and ARE_EMAILS_ENABLED: # type: ignore[union-attr]
if user.awaiting_email_verification and ARE_EMAILS_ENABLED: # type: ignore[attr-defined]
messages.error(request, "You must verify your email before logging in.")
return render_toast_message(request)

Expand Down
13 changes: 13 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,19 @@ plugins = [
"mypy_django_plugin.main",
"mypy_drf_plugin.main"
]
disable_error_code = ["annotation-unchecked"]
explicit_package_bases = true
incremental = false
exclude = [
"venv",
".venv",
"env",
"ENV",
"ENV_DIR",
"env.bak",
"venv.bak",
"media"
]

[tool.django-stubs]
django_settings_module = "settings.settings"
Expand Down

0 comments on commit 83a04dc

Please sign in to comment.