mirror of
https://github.com/ae-utbm/sith.git
synced 2025-11-23 13:16:57 +00:00
Compare commits
1 Commits
fix-warnin
...
fix/produc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b60bd3a42b |
@@ -1,7 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
import uuid
|
import uuid
|
||||||
from datetime import date, datetime, timezone
|
from datetime import date
|
||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from django import forms
|
from django import forms
|
||||||
@@ -235,6 +235,19 @@ class ScheduledProductActionForm(forms.ModelForm):
|
|||||||
)
|
)
|
||||||
return super().clean()
|
return super().clean()
|
||||||
|
|
||||||
|
def set_product(self, product: Product):
|
||||||
|
"""Set the product to which this form's instance is linked.
|
||||||
|
|
||||||
|
When this form is linked to a ProductForm in the case of a product's creation,
|
||||||
|
the product doesn't exist yet, so saving this form as is will result
|
||||||
|
in having `{"product_id": null}` in the action kwargs.
|
||||||
|
For the creation to be useful, it may be needed to inject the newly created
|
||||||
|
product into this form, before saving the latter.
|
||||||
|
"""
|
||||||
|
self.product = product
|
||||||
|
kwargs = json.loads(self.instance.kwargs) | {"product_id": self.product.id}
|
||||||
|
self.instance.kwargs = json.dumps(kwargs)
|
||||||
|
|
||||||
|
|
||||||
class BaseScheduledProductActionFormSet(BaseModelFormSet):
|
class BaseScheduledProductActionFormSet(BaseModelFormSet):
|
||||||
def __init__(self, *args, product: Product, **kwargs):
|
def __init__(self, *args, product: Product, **kwargs):
|
||||||
@@ -321,11 +334,19 @@ class ProductForm(forms.ModelForm):
|
|||||||
def is_valid(self):
|
def is_valid(self):
|
||||||
return super().is_valid() and self.action_formset.is_valid()
|
return super().is_valid() and self.action_formset.is_valid()
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs) -> Product:
|
||||||
ret = super().save(*args, **kwargs)
|
product = super().save(*args, **kwargs)
|
||||||
self.instance.counters.set(self.cleaned_data["counters"])
|
product.counters.set(self.cleaned_data["counters"])
|
||||||
|
for form in self.action_formset:
|
||||||
|
# if it's a creation, the product given in the formset
|
||||||
|
# wasn't a persisted instance.
|
||||||
|
# So if we tried to persist the scheduled actions in the current state,
|
||||||
|
# they would be linked to no product, thus be completely useless
|
||||||
|
# To make it work, we have to replace
|
||||||
|
# the initial product with a persisted one
|
||||||
|
form.set_product(product)
|
||||||
self.action_formset.save()
|
self.action_formset.save()
|
||||||
return ret
|
return product
|
||||||
|
|
||||||
|
|
||||||
class ReturnableProductForm(forms.ModelForm):
|
class ReturnableProductForm(forms.ModelForm):
|
||||||
@@ -369,7 +390,6 @@ class EticketForm(forms.ModelForm):
|
|||||||
class CloseCustomerAccountForm(forms.Form):
|
class CloseCustomerAccountForm(forms.Form):
|
||||||
user = forms.ModelChoiceField(
|
user = forms.ModelChoiceField(
|
||||||
label=_("Refound this account"),
|
label=_("Refound this account"),
|
||||||
help_text=None,
|
|
||||||
required=True,
|
required=True,
|
||||||
widget=AutoCompleteSelectUser,
|
widget=AutoCompleteSelectUser,
|
||||||
queryset=User.objects.all(),
|
queryset=User.objects.all(),
|
||||||
@@ -489,14 +509,13 @@ class InvoiceCallForm(forms.Form):
|
|||||||
def __init__(self, *args, month: date, **kwargs):
|
def __init__(self, *args, month: date, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.month = month
|
self.month = month
|
||||||
month_start = datetime(month.year, month.month, month.day, tzinfo=timezone.utc)
|
|
||||||
self.clubs = list(
|
self.clubs = list(
|
||||||
Club.objects.filter(
|
Club.objects.filter(
|
||||||
Exists(
|
Exists(
|
||||||
Selling.objects.filter(
|
Selling.objects.filter(
|
||||||
club=OuterRef("pk"),
|
club=OuterRef("pk"),
|
||||||
date__gte=month_start,
|
date__gte=month,
|
||||||
date__lte=month_start + relativedelta(months=1),
|
date__lte=month + relativedelta(months=1),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).annotate(
|
).annotate(
|
||||||
|
|||||||
@@ -11,8 +11,12 @@ from model_bakery import baker
|
|||||||
|
|
||||||
from core.models import Group, User
|
from core.models import Group, User
|
||||||
from counter.baker_recipes import counter_recipe, product_recipe
|
from counter.baker_recipes import counter_recipe, product_recipe
|
||||||
from counter.forms import ScheduledProductActionForm, ScheduledProductActionFormSet
|
from counter.forms import (
|
||||||
from counter.models import ScheduledProductAction
|
ProductForm,
|
||||||
|
ScheduledProductActionForm,
|
||||||
|
ScheduledProductActionFormSet,
|
||||||
|
)
|
||||||
|
from counter.models import Product, ScheduledProductAction
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@@ -34,6 +38,39 @@ def test_edit_product(client: Client):
|
|||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_create_actions_alongside_product():
|
||||||
|
"""The form should work when the product and the actions are created alongside."""
|
||||||
|
# non-persisted instance
|
||||||
|
product: Product = product_recipe.prepare(_save_related=True)
|
||||||
|
trigger_at = now() + timedelta(minutes=10)
|
||||||
|
form = ProductForm(
|
||||||
|
data={
|
||||||
|
"name": "foo",
|
||||||
|
"description": "bar",
|
||||||
|
"product_type": product.product_type_id,
|
||||||
|
"club": product.club_id,
|
||||||
|
"code": "FOO",
|
||||||
|
"purchase_price": 1.0,
|
||||||
|
"selling_price": 1.0,
|
||||||
|
"special_selling_price": 1.0,
|
||||||
|
"limit_age": 0,
|
||||||
|
"form-TOTAL_FORMS": "2",
|
||||||
|
"form-INITIAL_FORMS": "0",
|
||||||
|
"form-0-task": "counter.tasks.archive_product",
|
||||||
|
"form-0-trigger_at": trigger_at,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert form.is_valid()
|
||||||
|
product = form.save()
|
||||||
|
action = ScheduledProductAction.objects.last()
|
||||||
|
assert action.clocked.clocked_time == trigger_at
|
||||||
|
assert action.enabled is True
|
||||||
|
assert action.one_off is True
|
||||||
|
assert action.task == "counter.tasks.archive_product"
|
||||||
|
assert action.kwargs == json.dumps({"product_id": product.id})
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
class TestProductActionForm:
|
class TestProductActionForm:
|
||||||
def test_single_form_archive(self):
|
def test_single_form_archive(self):
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from django.contrib.auth.models import Permission
|
|||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.test import Client
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import localdate
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
from pytest_django.asserts import assertRedirects
|
from pytest_django.asserts import assertRedirects
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ def test_invoice_call_view(client: Client, query: dict | None):
|
|||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_invoice_call_form():
|
def test_invoice_call_form():
|
||||||
Selling.objects.all().delete()
|
Selling.objects.all().delete()
|
||||||
month = now() - relativedelta(months=1)
|
month = localdate() - relativedelta(months=1)
|
||||||
clubs = baker.make(Club, _quantity=2)
|
clubs = baker.make(Club, _quantity=2)
|
||||||
recipe = sale_recipe.extend(date=month, customer=baker.make(Customer, amount=10000))
|
recipe = sale_recipe.extend(date=month, customer=baker.make(Customer, amount=10000))
|
||||||
recipe.make(club=clubs[0], quantity=2, unit_price=200)
|
recipe.make(club=clubs[0], quantity=2, unit_price=200)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
# OR WITHIN THE LOCAL FILE "LICENSE"
|
# OR WITHIN THE LOCAL FILE "LICENSE"
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
from datetime import datetime, timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin, UserPassesTestMixin
|
from django.contrib.auth.mixins import PermissionRequiredMixin, UserPassesTestMixin
|
||||||
@@ -23,7 +23,6 @@ from django.forms.models import modelform_factory
|
|||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.timezone import get_current_timezone
|
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.generic import DetailView, ListView, TemplateView
|
from django.views.generic import DetailView, ListView, TemplateView
|
||||||
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
|
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
|
||||||
@@ -286,13 +285,7 @@ class CounterStatView(PermissionRequiredMixin, DetailView):
|
|||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Add stats to the context."""
|
"""Add stats to the context."""
|
||||||
counter: Counter = self.object
|
counter: Counter = self.object
|
||||||
start_date = get_start_of_semester()
|
semester_start = 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()
|
office_hours = counter.get_top_barmen()
|
||||||
kwargs = super().get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs.update(
|
kwargs.update(
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
# OR WITHIN THE LOCAL FILE "LICENSE"
|
# OR WITHIN THE LOCAL FILE "LICENSE"
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
@@ -63,8 +63,7 @@ class InvoiceCallView(
|
|||||||
"""Add sums to the context."""
|
"""Add sums to the context."""
|
||||||
kwargs = super().get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
kwargs["months"] = Selling.objects.datetimes("date", "month", order="DESC")
|
kwargs["months"] = Selling.objects.datetimes("date", "month", order="DESC")
|
||||||
month = self.get_month()
|
start_date = self.get_month()
|
||||||
start_date = datetime(month.year, month.month, month.day, tzinfo=timezone.utc)
|
|
||||||
end_date = start_date + relativedelta(months=1)
|
end_date = start_date + relativedelta(months=1)
|
||||||
|
|
||||||
kwargs["sum_cb"] = Refilling.objects.filter(
|
kwargs["sum_cb"] = Refilling.objects.filter(
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ TEMPLATES = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
FORM_RENDERER = "django.forms.renderers.DjangoDivFormRenderer"
|
||||||
|
|
||||||
HAYSTACK_CONNECTIONS = {
|
HAYSTACK_CONNECTIONS = {
|
||||||
"default": {
|
"default": {
|
||||||
|
|||||||
Reference in New Issue
Block a user