sforkowany z mtyton/comfy
[WIP] trying formset attempt
rodzic
c76e6fbc12
commit
c7aa69448c
|
@ -40,12 +40,10 @@ class OutgoingMailAdmin(ModelAdmin):
|
|||
exclude_from_explorer = False
|
||||
list_display = (
|
||||
"subject",
|
||||
"to",
|
||||
"sent",
|
||||
)
|
||||
search_fields = (
|
||||
"subject",
|
||||
"to",
|
||||
)
|
||||
list_filter = (
|
||||
"subject",
|
||||
|
|
|
@ -40,26 +40,39 @@ class CustomerDataForm(forms.Form):
|
|||
)
|
||||
|
||||
|
||||
class ProductCategoryParamForm(forms.ModelForm):
|
||||
class ProductCategoryParamFormset(forms.BaseModelFormSet):
|
||||
...
|
||||
|
||||
|
||||
class ProductCategoryParamValueForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = ProductCategoryParam
|
||||
model = ProductCategoryParamValue
|
||||
fields = ("key", "value")
|
||||
readonly_fields = ("key", )
|
||||
|
||||
def __init__(self, instance, *args, **kwargs):
|
||||
super().__init__(*args, instance=instance, **kwargs)
|
||||
self.fields["key"].widget.attrs["disabled"] = True
|
||||
self.fields["value"].choices = [
|
||||
(param_value.pk, param_value.value) for param_value in instance.param_values.all()
|
||||
]
|
||||
|
||||
|
||||
key = forms.CharField(required=True)
|
||||
value = forms.ModelChoiceField(
|
||||
queryset=ProductCategoryParamValue.objects.none(),
|
||||
widget=forms.RadioSelect(attrs={"class": "form-control"})
|
||||
widget=forms.RadioSelect(attrs={"class": "btn-check", "type": "radio", "autocomplete": "off"}),
|
||||
required=True
|
||||
)
|
||||
|
||||
def _get_instace(self, key: str):
|
||||
return ProductCategoryParam.objects.get(key=key)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
key = self.initial.get("key")
|
||||
if not key:
|
||||
return
|
||||
self.cat_param = self._get_instace(key)
|
||||
self.fields["value"].choices = [
|
||||
(param_value.pk, param_value.value) for param_value in self.cat_param.param_values.all()
|
||||
]
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
return ProductCategoryParamValue.objects.get(
|
||||
param=self.instance,
|
||||
param_value = ProductCategoryParamValue.objects.get(
|
||||
param__key=str(self.cleaned_data["key"]),
|
||||
value=str(self.cleaned_data["value"])
|
||||
)
|
||||
print(param_value or "DUPSKo")
|
||||
return param_value
|
||||
|
|
|
@ -171,12 +171,22 @@ class ProductTemplateImage(BaseImageModel):
|
|||
class ProductManager(models.Manager):
|
||||
|
||||
def get_or_create_by_params(self, params: list[ProductCategoryParamValue], template: ProductTemplate):
|
||||
product = self.filter(params__in=params).first()
|
||||
products = self.filter(template=template)
|
||||
# TODO - other price
|
||||
price_proposal = products.first().price if products.first() else 4.0
|
||||
for param in params:
|
||||
products = products.filter(params__pk=param.pk)
|
||||
|
||||
# There should be only one
|
||||
if not products.count() <= 1:
|
||||
raise ValidationError("There should be only one product with given set of params")
|
||||
|
||||
product = products.first()
|
||||
if not product:
|
||||
product = self.create(
|
||||
name=f"{template.title} - AUTOGENERATED",
|
||||
template=template,
|
||||
price=...,
|
||||
price=price_proposal,
|
||||
available=False
|
||||
)
|
||||
for param in params:
|
||||
|
@ -194,6 +204,8 @@ class Product(ClusterableModel):
|
|||
price = models.FloatField()
|
||||
available = models.BooleanField(default=True)
|
||||
|
||||
objects = ProductManager()
|
||||
|
||||
panels = [
|
||||
FieldPanel("template"),
|
||||
FieldPanel("price"),
|
||||
|
|
|
@ -23,16 +23,21 @@
|
|||
<div class="container">
|
||||
<form action="" method="POST" class="mt-5">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ formset.management_form }}
|
||||
<div class="row mt-5">
|
||||
{% for form in forms %}
|
||||
{% for form in formset.forms %}
|
||||
<div class="col-6 text-center">
|
||||
<h3>{{form.instance}}</h3>
|
||||
{% for value, label in form.value.field.choices %}
|
||||
<div class="btn-group btn-group-toggle" role="group">
|
||||
<input type="radio" class="btn-check" name="{{form.key.value}}" id="{{value}}" autocomplete="off" checked>
|
||||
<label class="btn btn-outline-primary" for="{{value}}">{{label}}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<h3>{{form.cat_param}}</h3>
|
||||
{% if form.value.field.choices %}
|
||||
<input type="hidden" name="{{form.prefix}}-key" value="{{form.key.value}}">
|
||||
{% for value, label in form.value.field.choices %}
|
||||
<div class="btn-group btn-group-toggle" role="group">
|
||||
<input type="radio" class="btn-check" name="{{form.prefix}}-value" id="{{value}}" autocomplete="off" value="{{value}}" required>
|
||||
<label class="btn btn-outline-primary" for="{{value}}">{{label}}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if forloop.counter|divisibleby:"2" %} </div><div class="row mt-5">{% endif %}
|
||||
{% endfor %}
|
||||
|
|
|
@ -98,6 +98,48 @@ class ProductTestCase(TestCase):
|
|||
product.params.add(sec_param_value)
|
||||
self.assertEqual(product.params.count(), 0)
|
||||
|
||||
def test_get_or_create_by_params_success(self):
|
||||
product = factories.ProductFactory(available=True)
|
||||
value1 = factories.ProductCategoryParamValueFactory()
|
||||
value2 = factories.ProductCategoryParamValueFactory()
|
||||
product.params.add(value1)
|
||||
product.params.add(value2)
|
||||
product.save()
|
||||
prod = store_models.Product.objects.get_or_create_by_params(
|
||||
params=[value1, value2], template=product.template,
|
||||
)
|
||||
self.assertIsNotNone(prod)
|
||||
self.assertEqual(prod.pk, product.pk)
|
||||
self.assertTrue(prod.available)
|
||||
|
||||
def test_get_or_create_by_params_success_not_existing_product(self):
|
||||
product = factories.ProductFactory(available=True)
|
||||
value1 = factories.ProductCategoryParamValueFactory()
|
||||
value2 = factories.ProductCategoryParamValueFactory()
|
||||
product.params.add(value1)
|
||||
product.price = 13.0
|
||||
product.save()
|
||||
|
||||
prod = store_models.Product.objects.get_or_create_by_params(
|
||||
params=[value1, value2], template=product.template,
|
||||
)
|
||||
self.assertIsNotNone(prod)
|
||||
self.assertNotEqual(prod.pk, product.pk)
|
||||
self.assertFalse(prod.available)
|
||||
self.assertEqual(prod.price, 13.0)
|
||||
|
||||
def test_get_or_create_by_params_success_not_existing_product_no_other_products(self):
|
||||
template = factories.ProductTemplateFactory()
|
||||
value1 = factories.ProductCategoryParamValueFactory()
|
||||
value2 = factories.ProductCategoryParamValueFactory()
|
||||
|
||||
prod = store_models.Product.objects.get_or_create_by_params(
|
||||
params=[value1, value2], template=template,
|
||||
)
|
||||
self.assertIsNotNone(prod)
|
||||
self.assertFalse(prod.available)
|
||||
self.assertEqual(prod.price, 4.0)
|
||||
|
||||
|
||||
class OrderProductTestCase(TestCase):
|
||||
def setUp(self):
|
||||
|
|
|
@ -8,6 +8,7 @@ from django.shortcuts import render
|
|||
from django.urls import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.contrib import messages
|
||||
from django.forms import modelformset_factory
|
||||
from rest_framework.viewsets import ViewSet
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
|
@ -19,12 +20,14 @@ from store.serializers import (
|
|||
)
|
||||
from store.forms import (
|
||||
CustomerDataForm,
|
||||
ProductCategoryParamForm
|
||||
ProductCategoryParamValueForm,
|
||||
ProductCategoryParamFormset
|
||||
)
|
||||
from store.models import (
|
||||
Order,
|
||||
Product,
|
||||
ProductTemplate
|
||||
ProductTemplate,
|
||||
ProductCategoryParamValue
|
||||
)
|
||||
|
||||
|
||||
|
@ -96,13 +99,17 @@ class ConfigureProductView(View):
|
|||
def get_context_data(self, pk: int, **kwargs: Any) -> Dict[str, Any]:
|
||||
template = ProductTemplate.objects.get(pk=pk)
|
||||
category_params = template.category.category_params.all()
|
||||
|
||||
|
||||
formset_class = modelformset_factory(
|
||||
ProductCategoryParamValue,
|
||||
form=ProductCategoryParamValueForm,
|
||||
formset=ProductCategoryParamFormset
|
||||
)
|
||||
formset = formset_class(queryset=category_params)
|
||||
context = {
|
||||
"template": template,
|
||||
"available_variants": Product.objects.filter(template__pk=pk),
|
||||
"category_params": category_params,
|
||||
"forms": [ProductCategoryParamForm(instance=param) for param in category_params]
|
||||
"formset": formset
|
||||
}
|
||||
|
||||
return context
|
||||
|
@ -112,8 +119,42 @@ class ConfigureProductView(View):
|
|||
return render(request, self.template_name, context)
|
||||
|
||||
def post(self, request, pk: int, *args, **kwargs):
|
||||
# first select template
|
||||
template = ProductTemplate.objects.get(pk=pk)
|
||||
category_params = template.category.category_params.all()
|
||||
params_values = []
|
||||
formset_class = modelformset_factory(
|
||||
ProductCategoryParamValue,
|
||||
form=ProductCategoryParamValueForm,
|
||||
formset=ProductCategoryParamFormset
|
||||
)
|
||||
formset = formset_class(queryset=category_params, data=request.POST)
|
||||
print(request.POST)
|
||||
return HttpResponseRedirect(reverse("product-configure-summary", kwargs={"variant_pk": 1}))
|
||||
if not formset.is_valid():
|
||||
print(formset.errors)
|
||||
messages.error(request, "Niepoprawne dane")
|
||||
context = self.get_context_data(pk)
|
||||
context["formset"] = formset
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
for form in formset.forms:
|
||||
if not form.is_valid():
|
||||
messages.error(request, "Niepoprawne dane")
|
||||
context = self.get_context_data(pk)
|
||||
context["formset"] = formset
|
||||
return render(request, self.template_name, context)
|
||||
params_values.append(form.save())
|
||||
|
||||
product_variant = Product.objects.get_or_create_by_params(
|
||||
template=ProductTemplate.objects.get(pk=pk), params=params_values
|
||||
)
|
||||
if not product_variant:
|
||||
messages.error(request, "Nie udało się utworzyć wariantu produktu")
|
||||
return HttpResponseRedirect(reverse("product-configure", kwargs={"pk": pk}))
|
||||
|
||||
return HttpResponseRedirect(
|
||||
reverse("product-configure-summary", kwargs={"variant_pk": product_variant.pk})
|
||||
)
|
||||
|
||||
|
||||
class ConfigureProductSummaryView(View):
|
||||
|
@ -123,7 +164,7 @@ class ConfigureProductSummaryView(View):
|
|||
variant = Product.objects.get(pk=variant_pk)
|
||||
context = {
|
||||
"variant": variant,
|
||||
"category_params": variant.template.category.category_params.all()
|
||||
"params_values": variant.params.all()
|
||||
}
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue