2 Commits

Author SHA1 Message Date
imperosol
6709befb1f fix timezone issues 2025-11-23 01:30:44 +01:00
imperosol
ddfb88ca2a remove settings.FORM_RENDERER 2025-11-23 01:22:15 +01:00
13 changed files with 503 additions and 582 deletions

View File

@@ -1,16 +1,18 @@
from typing import Annotated
from annotated_types import MinLen
from django.db.models import Q
from ninja import FilterLookup, FilterSchema, ModelSchema
from ninja import Field, FilterSchema, ModelSchema
from club.models import Club, Membership
from core.schemas import NonEmptyStr, SimpleUserSchema
from core.schemas import SimpleUserSchema
class ClubSearchFilterSchema(FilterSchema):
search: Annotated[NonEmptyStr | None, FilterLookup("name__icontains")] = None
search: Annotated[str, MinLen(1)] | None = Field(None, q="name__icontains")
is_active: bool | None = None
parent_id: int | None = None
parent_name: str | None = Field(None, q="parent__name__icontains")
exclude_ids: set[int] | None = None
def filter_exclude_ids(self, value: set[int] | None):

View File

@@ -1,9 +1,9 @@
from datetime import datetime
from typing import Annotated
from ninja import FilterLookup, FilterSchema, ModelSchema
from ninja import FilterSchema, ModelSchema
from ninja_extra import service_resolver
from ninja_extra.context import RouteContext
from pydantic import Field
from club.schemas import ClubProfileSchema
from com.models import News, NewsDate
@@ -11,12 +11,12 @@ from core.markdown import markdown
class NewsDateFilterSchema(FilterSchema):
before: Annotated[datetime | None, FilterLookup("end_date__lt")] = None
after: Annotated[datetime | None, FilterLookup("start_date__gt")] = None
club_id: Annotated[int | None, FilterLookup("news__club_id")] = None
before: datetime | None = Field(None, q="end_date__lt")
after: datetime | None = Field(None, q="start_date__gt")
club_id: int | None = Field(None, q="news__club_id")
news_id: int | None = None
is_published: Annotated[bool | None, FilterLookup("news__is_published")] = None
title: Annotated[str | None, FilterLookup("news__title__icontains")] = None
is_published: bool | None = Field(None, q="news__is_published")
title: str | None = Field(None, q="news__title__icontains")
class NewsSchema(ModelSchema):

View File

@@ -15,8 +15,6 @@ from pydantic_core.core_schema import ValidationInfo
from core.models import Group, QuickUploadImage, SithFile, User
from core.utils import is_image
NonEmptyStr = Annotated[str, MinLen(1)]
class UploadedImage(UploadedFile):
@classmethod

View File

@@ -1,7 +1,7 @@
import json
import math
import uuid
from datetime import date
from datetime import date, datetime, timezone
from dateutil.relativedelta import relativedelta
from django import forms
@@ -489,13 +489,14 @@ class InvoiceCallForm(forms.Form):
def __init__(self, *args, month: date, **kwargs):
super().__init__(*args, **kwargs)
self.month = month
month_start = datetime(month.year, month.month, month.day, tzinfo=timezone.utc)
self.clubs = list(
Club.objects.filter(
Exists(
Selling.objects.filter(
club=OuterRef("pk"),
date__gte=month,
date__lte=month + relativedelta(months=1),
date__gte=month_start,
date__lte=month_start + relativedelta(months=1),
)
)
).annotate(

View File

@@ -1,12 +1,13 @@
from datetime import datetime
from typing import Annotated, Self
from annotated_types import MinLen
from django.urls import reverse
from ninja import FilterLookup, FilterSchema, ModelSchema, Schema
from ninja import Field, FilterSchema, ModelSchema, Schema
from pydantic import model_validator
from club.schemas import SimpleClubSchema
from core.schemas import GroupSchema, NonEmptyStr, SimpleUserSchema
from core.schemas import GroupSchema, SimpleUserSchema
from counter.models import Counter, Product, ProductType
@@ -20,7 +21,7 @@ class CounterSchema(ModelSchema):
class CounterFilterSchema(FilterSchema):
search: Annotated[NonEmptyStr | None, FilterLookup("name__icontains")] = None
search: Annotated[str, MinLen(1)] = Field(None, q="name__icontains")
class SimplifiedCounterSchema(ModelSchema):
@@ -92,18 +93,18 @@ class ProductSchema(ModelSchema):
class ProductFilterSchema(FilterSchema):
search: Annotated[
NonEmptyStr | None, FilterLookup(["name__icontains", "code__icontains"])
] = None
is_archived: Annotated[bool | None, FilterLookup("archived")] = None
buying_groups: Annotated[set[int] | None, FilterLookup("buying_groups__in")] = None
product_type: Annotated[set[int] | None, FilterLookup("product_type__in")] = None
club: Annotated[set[int] | None, FilterLookup("club__in")] = None
counter: Annotated[set[int] | None, FilterLookup("counters__in")] = None
search: Annotated[str, MinLen(1)] | None = Field(
None, q=["name__icontains", "code__icontains"]
)
is_archived: bool | None = Field(None, q="archived")
buying_groups: set[int] | None = Field(None, q="buying_groups__in")
product_type: set[int] | None = Field(None, q="product_type__in")
club: set[int] | None = Field(None, q="club__in")
counter: set[int] | None = Field(None, q="counters__in")
class SaleFilterSchema(FilterSchema):
before: Annotated[datetime | None, FilterLookup("date__lt")] = None
after: Annotated[datetime | None, FilterLookup("date__gt")] = None
counters: Annotated[set[int] | None, FilterLookup("counter__in")] = None
products: Annotated[set[int] | None, FilterLookup("product__in")] = None
before: datetime | None = Field(None, q="date__lt")
after: datetime | None = Field(None, q="date__gt")
counters: set[int] | None = Field(None, q="counter__in")
products: set[int] | None = Field(None, q="product__in")

View File

@@ -6,7 +6,7 @@ from django.contrib.auth.models import Permission
from django.core.exceptions import ValidationError
from django.test import Client
from django.urls import reverse
from django.utils.timezone import localdate
from django.utils.timezone import now
from model_bakery import baker
from pytest_django.asserts import assertRedirects
@@ -57,7 +57,7 @@ def test_invoice_call_view(client: Client, query: dict | None):
@pytest.mark.django_db
def test_invoice_call_form():
Selling.objects.all().delete()
month = localdate() - relativedelta(months=1)
month = now() - relativedelta(months=1)
clubs = baker.make(Club, _quantity=2)
recipe = sale_recipe.extend(date=month, customer=baker.make(Customer, amount=10000))
recipe.make(club=clubs[0], quantity=2, unit_price=200)

View File

@@ -12,7 +12,7 @@
# OR WITHIN THE LOCAL FILE "LICENSE"
#
#
from datetime import timedelta
from datetime import datetime, timedelta
from django.conf import settings
from django.contrib.auth.mixins import PermissionRequiredMixin, UserPassesTestMixin
@@ -23,6 +23,7 @@ from django.forms.models import modelform_factory
from django.shortcuts import get_object_or_404
from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.utils.timezone import get_current_timezone
from django.utils.translation import gettext as _
from django.views.generic import DetailView, ListView, TemplateView
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
@@ -285,7 +286,13 @@ class CounterStatView(PermissionRequiredMixin, DetailView):
def get_context_data(self, **kwargs):
"""Add stats to the context."""
counter: Counter = self.object
semester_start = get_start_of_semester()
start_date = get_start_of_semester()
semester_start = datetime(
start_date.year,
start_date.month,
start_date.day,
tzinfo=get_current_timezone(),
)
office_hours = counter.get_top_barmen()
kwargs = super().get_context_data(**kwargs)
kwargs.update(

View File

@@ -12,7 +12,7 @@
# OR WITHIN THE LOCAL FILE "LICENSE"
#
#
from datetime import datetime
from datetime import datetime, timezone
from urllib.parse import urlencode
from dateutil.relativedelta import relativedelta
@@ -63,7 +63,8 @@ class InvoiceCallView(
"""Add sums to the context."""
kwargs = super().get_context_data(**kwargs)
kwargs["months"] = Selling.objects.datetimes("date", "month", order="DESC")
start_date = self.get_month()
month = self.get_month()
start_date = datetime(month.year, month.month, month.day, tzinfo=timezone.utc)
end_date = start_date + relativedelta(months=1)
kwargs["sum_cb"] = Refilling.objects.filter(

View File

@@ -1,9 +1,9 @@
from typing import Annotated, Literal
from typing import Literal
from django.db.models import Q
from django.utils import html
from haystack.query import SearchQuerySet
from ninja import FilterLookup, FilterSchema, ModelSchema, Schema
from ninja import FilterSchema, ModelSchema, Schema
from pydantic import AliasPath, ConfigDict, Field, TypeAdapter
from pydantic.alias_generators import to_camel
@@ -114,14 +114,13 @@ class UvSchema(ModelSchema):
class UvFilterSchema(FilterSchema):
search: Annotated[str | None, FilterLookup("code__icontains")] = None
search: str | None = Field(None, q="code__icontains")
semester: set[Literal["AUTUMN", "SPRING"]] | None = None
credit_type: Annotated[
set[Literal["CS", "TM", "EC", "OM", "QC"]] | None,
FilterLookup("credit_type__in"),
] = None
credit_type: set[Literal["CS", "TM", "EC", "OM", "QC"]] | None = Field(
None, q="credit_type__in"
)
language: str = "FR"
department: Annotated[set[str] | None, FilterLookup("department__in")] = None
department: set[str] | None = Field(None, q="department__in")
def filter_search(self, value: str | None) -> Q:
"""Special filter for the search text.

View File

@@ -20,8 +20,8 @@ license = { text = "GPL-3.0-only" }
requires-python = "<4.0,>=3.12"
dependencies = [
"django>=5.2.8,<6.0.0",
"django-ninja>=1.5.0,<6.0.0",
"django-ninja-extra>=0.30.6",
"django-ninja>=1.4.5,<2.0.0",
"django-ninja-extra>=0.30.2,<1.0.0",
"Pillow>=12.0.0,<13.0.0",
"mistune>=3.1.4,<4.0.0",
"django-jinja<3.0.0,>=2.11.0",

View File

@@ -2,19 +2,20 @@ from datetime import datetime
from pathlib import Path
from typing import Annotated
from annotated_types import MinLen
from django.urls import reverse
from ninja import FilterLookup, FilterSchema, ModelSchema, Schema
from ninja import FilterSchema, ModelSchema, Schema
from pydantic import Field, NonNegativeInt
from core.schemas import NonEmptyStr, SimpleUserSchema, UserProfileSchema
from core.schemas import SimpleUserSchema, UserProfileSchema
from sas.models import Album, Picture, PictureModerationRequest
class AlbumFilterSchema(FilterSchema):
search: Annotated[NonEmptyStr | None, FilterLookup("name__icontains")] = None
before_date: Annotated[datetime | None, FilterLookup("event_date__lte")] = None
after_date: Annotated[datetime | None, FilterLookup("event_date__gte")] = None
parent_id: Annotated[int | None, FilterLookup("parent_id")] = None
search: Annotated[str, MinLen(1)] | None = Field(None, q="name__icontains")
before_date: datetime | None = Field(None, q="event_date__lte")
after_date: datetime | None = Field(None, q="event_date__gte")
parent_id: int | None = Field(None, q="parent_id")
class SimpleAlbumSchema(ModelSchema):
@@ -59,12 +60,10 @@ class AlbumAutocompleteSchema(ModelSchema):
class PictureFilterSchema(FilterSchema):
before_date: Annotated[datetime | None, FilterLookup("date__lte")] = None
after_date: Annotated[datetime | None, FilterLookup("date__gte")] = None
users_identified: Annotated[
set[int] | None, FilterLookup("people__user_id__in")
] = None
album_id: Annotated[int | None, FilterLookup("parent_id")] = None
before_date: datetime | None = Field(None, q="date__lte")
after_date: datetime | None = Field(None, q="date__gte")
users_identified: set[int] | None = Field(None, q="people__user_id__in")
album_id: int | None = Field(None, q="parent_id")
class PictureSchema(ModelSchema):

View File

@@ -216,7 +216,7 @@ TEMPLATES = [
},
},
]
FORM_RENDERER = "django.forms.renderers.DjangoDivFormRenderer"
HAYSTACK_CONNECTIONS = {
"default": {

959
uv.lock generated

File diff suppressed because it is too large Load Diff