Merge remote-tracking branch 'upstream/main'
ci/woodpecker/tag/build Pipeline was successful Szczegóły
ci/woodpecker/tag/test Pipeline was successful Szczegóły
ci/woodpecker/tag/push Pipeline was successful Szczegóły

main 0.0.5
Mi Klo 2023-08-22 21:56:41 +00:00
commit 1ad080d9a0
12 zmienionych plików z 237 dodań i 197 usunięć

1
.gitignore vendored
Wyświetl plik

@ -143,3 +143,4 @@ artel/static/
# media # media
artel/media/* artel/media/*
artel/store/data/*

Wyświetl plik

@ -20,8 +20,8 @@ class ProductCategoryAdmin(ModelAdmin):
list_display = ("name", ) list_display = ("name", )
class ProductCategoryParamAdmin(ModelAdmin): class ProductTemplateParamAdmin(ModelAdmin):
model = models.ProductCategoryParam model = models.ProductTemplateParam
list_display = ("key", "param_type") list_display = ("key", "param_type")
@ -59,7 +59,7 @@ class StoreAdminGroup(ModelAdminGroup):
items = ( items = (
ProductAuthorAdmin, ProductAuthorAdmin,
ProductCategoryAdmin, ProductCategoryAdmin,
ProductCategoryParamAdmin, ProductTemplateParamAdmin,
ProductTemplateAdmin, ProductTemplateAdmin,
ProductAdmin, ProductAdmin,
DocumentTemplateAdmin, DocumentTemplateAdmin,

Wyświetl plik

@ -5,7 +5,7 @@ from django.db.models import Model
from store.models import ( from store.models import (
ProductTemplate, ProductTemplate,
ProductCategoryParamValue, ProductTemplateParamValue,
Product, Product,
PaymentMethod, PaymentMethod,
DeliveryMethod DeliveryMethod
@ -71,11 +71,16 @@ class ButtonToggleSelect(forms.RadioSelect):
class ProductTemplateConfigForm(forms.Form): class ProductTemplateConfigForm(forms.Form):
def _create_dynamic_fields(self, template: ProductTemplate): def _create_dynamic_fields(self, template: ProductTemplate):
category_params = template.category.category_params.all() template_params = template.template_params.all()
for param in category_params: for param in template_params:
queryset = ProductTemplateParamValue.objects.filter(param=param)
if queryset.count() >= 4:
widget = forms.Select(attrs={"class": "form-select"})
else:
widget = ButtonToggleSelect(attrs={"class": "btn-group btn-group-toggle"})
self.fields[param.key] = forms.ModelChoiceField( self.fields[param.key] = forms.ModelChoiceField(
queryset=ProductCategoryParamValue.objects.filter(param=param), queryset=queryset,
widget=ButtonToggleSelect(attrs={"class": "btn-group btn-group-toggle"}), widget=widget,
) )
def __init__( def __init__(

Wyświetl plik

@ -1,12 +1,14 @@
import logging import logging
import time
import requests import requests
import pandas as pd import pandas as pd
from django.core import files from django.core.files.base import ContentFile
from django.conf import settings
from store.models import ( from store.models import (
ProductTemplate, ProductTemplate,
ProductCategoryParamValue, ProductTemplateParam,
ProductTemplateParamValue,
Product, Product,
ProductImage ProductImage
) )
@ -29,36 +31,46 @@ class TemplateLoader(BaseLoader):
class ProductLoader(BaseLoader): class ProductLoader(BaseLoader):
def _get_images(self, row) -> list[files.ContentFile]: def _clear(self):
urls = row["images"] Product.objects.all().delete()
def __init__(self, path, param_names, clear=False):
super().__init__(path)
self.param_names = param_names
if clear:
self._clear()
def _get_images(self, row) -> list[ContentFile]:
url = row["images"]
images = [] images = []
for url in urls: response = requests.get(
response = requests.get(url, stream=True) url+"/preview", stream=True
if response.status_code == 200: )
data = response.raw if response.status_code == 200:
file_name = url.split("/")[-1] data = response.content
image = files.ContentFile(data, name=file_name) image = ContentFile(data, name=row["template"])
images.append(image) images.append(image)
return images return images
def _process_row(self, row): def _process_row(self, row):
template = ProductTemplate.objects.get(code=row["template"]) template = ProductTemplate.objects.get(code=row["template"])
price = float(row["price"]) price = float(row["price"].strip("").replace(",", "."))
name = row["name"] name = row["name"]
available = bool(row["available"]) available = bool(row["available"])
params = [] params = []
for param in row["params"]: for key in self.param_names:
key, value = param value = row[key]
param = ProductCategoryParamValue.objects.get(param__key=key, value=value) param, _ = ProductTemplateParam.objects.get_or_create(key=key, template=template)
params.append(param) param_value, _ = ProductTemplateParamValue.objects.get_or_create(param=param, value=value)
params.append(param_value)
product = Product.objects.get_or_create_by_params(template=template, params=params) product = Product.objects.get_or_create_by_params(template=template, params=params)
product.price = price product.price = price
product.name = name product.name = name
product.available = available product.available = available
# NOTE - temporary solution
images = self._get_images(row) # images = self._get_images(row)
for i, image in enumerate(images): # for i, image in enumerate(images):
ProductImage.objects.create(product=product, image=image, is_main=bool(i==0)) # ProductImage.objects.create(product=product, image=image, is_main=bool(i==0))
product.save() product.save()
return product return product
@ -66,6 +78,7 @@ class ProductLoader(BaseLoader):
data = self.load_data() data = self.load_data()
products = [] products = []
for _, row in data.iterrows(): for _, row in data.iterrows():
time.sleep(5)
try: try:
product = self._process_row(row) product = self._process_row(row)
except Exception as e: except Exception as e:

Wyświetl plik

@ -9,5 +9,5 @@ class Command(BaseCommand):
help = "Load products from csv file" help = "Load products from csv file"
def handle(self, *args, **options): def handle(self, *args, **options):
loader = ProductLoader(settings.PRODUCTS_CSV_PATH) loader = ProductLoader(settings.PRODUCTS_CSV_PATH, ["mocowanie", "format", "wykonanie"], True)
loader.process() loader.process()

Wyświetl plik

@ -0,0 +1,62 @@
# Generated by Django 4.1.10 on 2023-08-15 10:44
from django.db import migrations, models
import django.db.models.deletion
import modelcluster.fields
class Migration(migrations.Migration):
dependencies = [
("store", "0012_deliverymethod_order_uuid_product_uuid_and_more"),
]
operations = [
migrations.CreateModel(
name="ProductTemplateParam",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("key", models.CharField(max_length=200)),
(
"param_type",
models.CharField(choices=[("int", "Int"), ("str", "String"), ("float", "Float")], max_length=200),
),
(
"template",
modelcluster.fields.ParentalKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="template_params",
to="store.producttemplate",
),
),
],
options={
"abstract": False,
},
),
migrations.AlterField(
model_name="product",
name="params",
field=models.ManyToManyField(
blank=True,
limit_choices_to=models.Q(("param__template", models.F("product__template"))),
through="store.ProductParam",
to="store.productcategoryparamvalue",
),
),
migrations.RenameModel(
old_name="ProductCategoryParamValue",
new_name="ProductTemplateParamValue",
),
migrations.DeleteModel(
name="ProductCategoryParam",
),
migrations.AlterField(
model_name="producttemplateparamvalue",
name="param",
field=modelcluster.fields.ParentalKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="param_values",
to="store.producttemplateparam",
),
),
]

Wyświetl plik

@ -90,59 +90,16 @@ class ProductCategory(ClusterableModel):
return self.name return self.name
panels = [ panels = [
FieldPanel("name"), FieldPanel("name")
InlinePanel("category_params")
] ]
class CategoryParamTypeChoices(models.TextChoices):
INT = "int"
STRING = "str"
FLOAT = "float"
class ProductCategoryParam(ClusterableModel):
category = ParentalKey(ProductCategory, on_delete=models.CASCADE, related_name="category_params")
key = models.CharField(max_length=200)
param_type = models.CharField(max_length=200, choices=CategoryParamTypeChoices.choices)
def __str__(self):
return self.key
panels = [
FieldPanel("category"),
FieldPanel("key"),
FieldPanel("param_type"),
InlinePanel("param_values")
]
def get_available_values(self) -> Iterator[any]:
for elem in self.param_values.all():
yield elem.get_value()
class ProductCategoryParamValue(ClusterableModel):
param = ParentalKey(ProductCategoryParam, on_delete=models.CASCADE, related_name="param_values")
value = models.CharField(max_length=255)
def get_value(self):
try:
func = getattr(builtins, self.param.param_type)
return func(self.value)
except ValueError:
return
def __str__(self):
return f"{self.param.key}: {self.value}"
class ProductTemplate(ClusterableModel): class ProductTemplate(ClusterableModel):
category = models.ForeignKey(ProductCategory, on_delete=models.CASCADE) category = models.ForeignKey(ProductCategory, on_delete=models.CASCADE)
author = models.ForeignKey(ProductAuthor, on_delete=models.CASCADE) author = models.ForeignKey(ProductAuthor, on_delete=models.CASCADE)
title = models.CharField(max_length=255) title = models.CharField(max_length=255)
code = models.CharField(max_length=255) code = models.CharField(max_length=255)
description = models.TextField(blank=True) description = models.TextField(blank=True)
# TODO - add mechanism for enabling params
tags = TaggableManager() tags = TaggableManager()
@ -164,6 +121,7 @@ class ProductTemplate(ClusterableModel):
FieldPanel('description'), FieldPanel('description'),
InlinePanel("template_images", label="Template Images"), InlinePanel("template_images", label="Template Images"),
FieldPanel("tags"), FieldPanel("tags"),
InlinePanel("template_params")
] ]
@ -175,9 +133,50 @@ class ProductTemplateImage(BaseImageModel):
is_main = models.BooleanField(default=False) is_main = models.BooleanField(default=False)
class TemplateParamValueChoices(models.TextChoices):
INT = "int"
STRING = "str"
FLOAT = "float"
class ProductTemplateParam(ClusterableModel):
template = ParentalKey(ProductTemplate, on_delete=models.CASCADE, related_name="template_params")
key = models.CharField(max_length=200)
param_type = models.CharField(max_length=200, choices=TemplateParamValueChoices.choices)
def __str__(self):
return self.key
panels = [
FieldPanel("template"),
FieldPanel("key"),
FieldPanel("param_type"),
InlinePanel("param_values")
]
def get_available_values(self) -> Iterator[any]:
for elem in self.param_values.all():
yield elem.get_value()
class ProductTemplateParamValue(ClusterableModel):
param = ParentalKey(ProductTemplateParam, on_delete=models.CASCADE, related_name="param_values")
value = models.CharField(max_length=255)
def get_value(self):
try:
func = getattr(builtins, self.param.param_type)
return func(self.value)
except ValueError:
return
def __str__(self):
return f"{self.param.key}: {self.value}"
class ProductManager(models.Manager): class ProductManager(models.Manager):
def get_or_create_by_params(self, params: list[ProductCategoryParamValue], template: ProductTemplate): def get_or_create_by_params(self, params: list[ProductTemplateParam], template: ProductTemplate):
products = self.filter(template=template) products = self.filter(template=template)
for param in params: for param in params:
@ -208,8 +207,8 @@ class Product(ClusterableModel):
name = models.CharField(max_length=255, blank=True) name = models.CharField(max_length=255, blank=True)
template = models.ForeignKey(ProductTemplate, on_delete=models.CASCADE, related_name="products") template = models.ForeignKey(ProductTemplate, on_delete=models.CASCADE, related_name="products")
params = models.ManyToManyField( params = models.ManyToManyField(
ProductCategoryParamValue, blank=True, through="ProductParam", ProductTemplateParamValue, blank=True, through="ProductParam",
limit_choices_to=models.Q(param__category=models.F("product__template__category")) limit_choices_to=models.Q(param__template=models.F("product__template"))
) )
price = models.FloatField() price = models.FloatField()
available = models.BooleanField(default=True) available = models.BooleanField(default=True)
@ -260,7 +259,7 @@ class ProductImage(BaseImageModel):
class ProductParam(models.Model): class ProductParam(models.Model):
product = ParentalKey(Product, on_delete=models.CASCADE, related_name="product_params") product = ParentalKey(Product, on_delete=models.CASCADE, related_name="product_params")
param_value = models.ForeignKey(ProductCategoryParamValue, on_delete=models.CASCADE) param_value = models.ForeignKey(ProductTemplateParamValue, on_delete=models.CASCADE)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.full_clean() self.full_clean()
@ -277,8 +276,8 @@ def validate_param(sender, **kwargs):
errors = [] errors = []
for pk in pk_set: for pk in pk_set:
try: try:
param = ProductCategoryParamValue.objects.get(pk=pk).param param = ProductTemplateParamValue.objects.get(pk=pk).param
except ProductCategoryParamValue.DoesNotExist as e: except ProductTemplateParamValue.DoesNotExist as e:
logger.exception(f"Product param validation failed with exception: {str(e)}") logger.exception(f"Product param validation failed with exception: {str(e)}")
count = product_instance.params.filter(productparam__param_value__param=param).count() count = product_instance.params.filter(productparam__param_value__param=param).count()
if count >= 1: if count >= 1:

Wyświetl plik

@ -10,19 +10,3 @@
{% endfor %} {% endfor %}
</div> </div>
{% endwith %} {% endwith %}
<!--
{% with id=widget.attrs.id %}
<div{% if id %} id="{{ id }}"{% endif %}
{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}
>
{% for group, options, index in widget.optgroups %}
{% if group %}
<div><label>{{ group }}</label>{% endif %}{% for option in options %}<div>
{% include option.template_name with widget=option %}</div>{% endfor %}{% if group %}
</div>
{% endif %}
{% endfor %}
</div>
{% endwith %}
-->

Wyświetl plik

@ -31,23 +31,6 @@ class ProductCategoryFactory(DjangoModelFactory):
name = Faker('name') name = Faker('name')
class ProductCategoryParamFactory(DjangoModelFactory):
class Meta:
model = 'store.ProductCategoryParam'
key = Faker('name')
category = SubFactory(ProductCategoryFactory)
param_type = 'str'
class ProductCategoryParamValueFactory(DjangoModelFactory):
class Meta:
model = 'store.ProductCategoryParamValue'
param = SubFactory(ProductCategoryParamFactory)
value = Faker('name')
class ProductTemplateFactory(DjangoModelFactory): class ProductTemplateFactory(DjangoModelFactory):
class Meta: class Meta:
model = 'store.ProductTemplate' model = 'store.ProductTemplate'
@ -59,6 +42,23 @@ class ProductTemplateFactory(DjangoModelFactory):
category = SubFactory(ProductCategoryFactory) category = SubFactory(ProductCategoryFactory)
class ProductTemplateParamFactory(DjangoModelFactory):
class Meta:
model = 'store.ProductTemplateParam'
key = Faker('name')
template = SubFactory(ProductTemplateFactory)
param_type = 'str'
class ProductTemplateParamValueFactory(DjangoModelFactory):
class Meta:
model = 'store.ProductTemplateParamValue'
param = SubFactory(ProductTemplateParamFactory)
value = Faker('name')
class ProductFactory(DjangoModelFactory): class ProductFactory(DjangoModelFactory):
class Meta: class Meta:
model = 'store.Product' model = 'store.Product'
@ -74,7 +74,7 @@ class ProductParamFactory(DjangoModelFactory):
model = 'store.ProductParam' model = 'store.ProductParam'
product = SubFactory(ProductFactory) product = SubFactory(ProductFactory)
param = SubFactory(ProductCategoryParamFactory) param = SubFactory(ProductTemplateParamValueFactory)
class PaymentMethodFactory(DjangoModelFactory): class PaymentMethodFactory(DjangoModelFactory):

Wyświetl plik

@ -10,23 +10,21 @@ class TestProductLoader(TestCase):
def setUp(self) -> None: def setUp(self) -> None:
self.category = factories.ProductCategoryFactory() self.category = factories.ProductCategoryFactory()
self.template = factories.ProductTemplateFactory(category=self.category) self.template = factories.ProductTemplateFactory(category=self.category)
self.category_params = [factories.ProductCategoryParamFactory(category=self.category) for _ in range(3)] self.template_params = [factories.ProductTemplateParamFactory(template=self.template) for _ in range(3)]
self.category_param_values = [factories.ProductCategoryParamValueFactory(param=param) for param in self.category_params] self.templat_params_values = [factories.ProductTemplateParamValueFactory(param=param) for param in self.template_params]
def test_load_products_single_product_success(self): def test_load_products_single_product_success(self):
fake_df = pd.DataFrame({ fake_df = pd.DataFrame({
"template": [self.template.code], "template": [self.template.code],
"price": [10.0], "price": str(10.0),
"name": ["Test product"], "name": ["Test product"],
"available": [True], "available": [True],
"params": [[ self.template_params[0].key: self.templat_params_values[0].value,
(self.category_params[0].key, self.category_param_values[0].value), self.template_params[1].key: self.templat_params_values[1].value,
(self.category_params[1].key, self.category_param_values[1].value), self.template_params[2].key: self.templat_params_values[2].value
(self.category_params[2].key, self.category_param_values[2].value),
]]
}) })
with patch("store.loader.BaseLoader.load_data", return_value=fake_df): with patch("store.loader.BaseLoader.load_data", return_value=fake_df):
loader = ProductLoader("fake_path") loader = ProductLoader("fake_path", [p.key for p in self.template_params])
loader.process() loader.process()
self.assertEqual(self.template.products.count(), 1) self.assertEqual(self.template.products.count(), 1)
@ -42,14 +40,12 @@ class TestProductLoader(TestCase):
"price": ["FASDSADQAW"], "price": ["FASDSADQAW"],
"name": ["Test product"], "name": ["Test product"],
"available": [True], "available": [True],
"params": [[ self.template_params[0].key: self.templat_params_values[0].value,
(self.category_params[0].key, self.category_param_values[0].value), self.template_params[1].key: self.templat_params_values[1].value,
(self.category_params[1].key, self.category_param_values[1].value), self.template_params[2].key: self.templat_params_values[2].value
(self.category_params[2].key, self.category_param_values[2].value),
]]
}) })
with patch("store.loader.BaseLoader.load_data", return_value=fake_df): with patch("store.loader.BaseLoader.load_data", return_value=fake_df):
loader = ProductLoader("fake_path") loader = ProductLoader("fake_path", [p.key for p in self.template_params])
loader.process() loader.process()
self.assertEqual(self.template.products.count(), 0) self.assertEqual(self.template.products.count(), 0)
@ -59,39 +55,17 @@ class TestProductLoader(TestCase):
def test_load_no_existing_template_code_failure(self, mock_logger): def test_load_no_existing_template_code_failure(self, mock_logger):
fake_df = pd.DataFrame({ fake_df = pd.DataFrame({
"template": ["NOTEEXISTINGTEMPLATE"], "template": ["NOTEEXISTINGTEMPLATE"],
"price": [10.0], "price": str(10.0),
"name": ["Test product"], "name": ["Test product"],
"available": [True], "available": [True],
"params": [[ self.template_params[0].key: self.templat_params_values[0].value,
(self.category_params[0].key, self.category_param_values[0].value), self.template_params[1].key: self.templat_params_values[1].value,
(self.category_params[1].key, self.category_param_values[1].value), self.template_params[2].key: self.templat_params_values[2].value
(self.category_params[2].key, self.category_param_values[2].value),
]]
}) })
with patch("store.loader.BaseLoader.load_data", return_value=fake_df): with patch("store.loader.BaseLoader.load_data", return_value=fake_df):
loader = ProductLoader("fake_path") loader = ProductLoader("fake_path", [p.key for p in self.template_params])
loader.process() loader.process()
self.assertEqual(self.template.products.count(), 0) self.assertEqual(self.template.products.count(), 0)
mock_logger.exception.assert_called_with("ProductTemplate matching query does not exist.") mock_logger.exception.assert_called_with("ProductTemplate matching query does not exist.")
@patch("store.loader.logger")
def test_not_existing_params_key_value_pairs_failure(self, mock_logger):
fake_df = pd.DataFrame({
"template": [self.template.code],
"price": [10.0],
"name": ["Test product"],
"available": [True],
"params": [[
(self.category_params[0].key, self.category_param_values[2].value),
(self.category_params[1].key, self.category_param_values[0].value),
(self.category_params[2].key, self.category_param_values[1].value),
]]
})
with patch("store.loader.BaseLoader.load_data", return_value=fake_df):
loader = ProductLoader("fake_path")
loader.process()
self.assertEqual(self.template.products.count(), 0)
mock_logger.exception.assert_called_with("ProductCategoryParamValue matching query does not exist.")

Wyświetl plik

@ -15,8 +15,9 @@ class ProductCategoryParamTestCase(TestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.category = factories.ProductCategoryFactory() self.category = factories.ProductCategoryFactory()
self.param = factories.ProductCategoryParamFactory( self.template = factories.ProductTemplateFactory(category=self.category)
category=self.category, self.param = factories.ProductTemplateParamFactory(
template=self.template,
param_type="int", param_type="int",
key="test_param" key="test_param"
) )
@ -26,72 +27,73 @@ class ProductCategoryParamTestCase(TestCase):
self.assertEqual(available_values, []) self.assertEqual(available_values, [])
def test_get_available_values_one_value_success(self): def test_get_available_values_one_value_success(self):
factories.ProductCategoryParamValueFactory(param=self.param, value="23") factories.ProductTemplateParamValueFactory(param=self.param, value="23")
available_values = [v for v in self.param.get_available_values()] available_values = [v for v in self.param.get_available_values()]
self.assertEqual(available_values, [23]) self.assertEqual(available_values, [23])
self.assertEqual(len(available_values), 1) self.assertEqual(len(available_values), 1)
def test_get_available_values_multiple_values_success(self): def test_get_available_values_multiple_values_success(self):
factories.ProductCategoryParamValueFactory(param=self.param, value="23") factories.ProductTemplateParamValueFactory(param=self.param, value="23")
factories.ProductCategoryParamValueFactory(param=self.param, value="24") factories.ProductTemplateParamValueFactory(param=self.param, value="24")
factories.ProductCategoryParamValueFactory(param=self.param, value="25") factories.ProductTemplateParamValueFactory(param=self.param, value="25")
available_values = [v for v in self.param.get_available_values()] available_values = [v for v in self.param.get_available_values()]
self.assertEqual(available_values, [23, 24, 25]) self.assertEqual(available_values, [23, 24, 25])
self.assertEqual(len(available_values), 3) self.assertEqual(len(available_values), 3)
class ProductCategoryParamValueTestCase(TestCase): class ProductTemplateParamValueTestCase(TestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.category = factories.ProductCategoryFactory() self.category = factories.ProductCategoryFactory()
self.template = factories.ProductTemplateFactory(category=self.category)
def test_get_value_success(self): def test_get_value_success(self):
param = factories.ProductCategoryParamFactory( param = factories.ProductTemplateParamFactory(
category=self.category, template=self.template,
param_type="int", param_type="int",
key="test_param" key="test_param"
) )
param_value = factories.ProductCategoryParamValueFactory(param=param, value="23") param_value = factories.ProductTemplateParamValueFactory(param=param, value="23")
proper_value = param_value.get_value() proper_value = param_value.get_value()
self.assertEqual(proper_value, 23) self.assertEqual(proper_value, 23)
def test_get_value_failure_wrong_value(self): def test_get_value_failure_wrong_value(self):
param = factories.ProductCategoryParamFactory( param = factories.ProductTemplateParamFactory(
category=self.category, template=self.template,
param_type="int", param_type="int",
key="test_param" key="test_param"
) )
param_value = factories.ProductCategoryParamValueFactory(param=param, value="wrong_value") param_value = factories.ProductTemplateParamValueFactory(param=param, value="wrong_value")
proper_value = param_value.get_value() proper_value = param_value.get_value()
self.assertEqual(proper_value, None) self.assertEqual(proper_value, None)
class ProductTestCase(TestCase): class ProductTestCase(TestCase):
def test_category_params_one_value_success(self): def test_template_params_one_value_success(self):
product = factories.ProductFactory() product = factories.ProductFactory()
param = factories.ProductCategoryParamFactory( param = factories.ProductTemplateParamFactory(
category=product.template.category, template=product.template,
param_type="int", param_type="int",
key="test_param" key="test_param"
) )
param_value = factories.ProductCategoryParamValueFactory(param=param, value="23") param_value = factories.ProductTemplateParamValueFactory(param=param, value="23")
with transaction.atomic(): with transaction.atomic():
product.params.add(param_value) product.params.add(param_value)
product.save() product.save()
self.assertEqual(product.params.count(), 1) self.assertEqual(product.params.count(), 1)
self.assertEqual(product.params.first().get_value(), 23) self.assertEqual(product.params.first().get_value(), 23)
def test_category_params_multiple_values_failure(self): def test_template_params_multiple_values_failure(self):
product = factories.ProductFactory() product = factories.ProductFactory()
param = factories.ProductCategoryParamFactory( param = factories.ProductTemplateParamFactory(
category=product.template.category, template=product.template,
param_type="int", param_type="int",
key="test_param" key="test_param"
) )
param_value = factories.ProductCategoryParamValueFactory(param=param, value="23") param_value = factories.ProductTemplateParamValueFactory(param=param, value="23")
sec_param_value = factories.ProductCategoryParamValueFactory(param=param, value="24") sec_param_value = factories.ProductTemplateParamValueFactory(param=param, value="24")
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
with transaction.atomic(): with transaction.atomic():
product.params.add(param_value) product.params.add(param_value)
@ -100,8 +102,8 @@ class ProductTestCase(TestCase):
def test_get_or_create_by_params_success(self): def test_get_or_create_by_params_success(self):
product = factories.ProductFactory(available=True) product = factories.ProductFactory(available=True)
value1 = factories.ProductCategoryParamValueFactory() value1 = factories.ProductTemplateParamValueFactory()
value2 = factories.ProductCategoryParamValueFactory() value2 = factories.ProductTemplateParamValueFactory()
product.params.add(value1) product.params.add(value1)
product.params.add(value2) product.params.add(value2)
product.save() product.save()
@ -114,8 +116,8 @@ class ProductTestCase(TestCase):
def test_get_or_create_by_params_success_not_existing_product(self): def test_get_or_create_by_params_success_not_existing_product(self):
product = factories.ProductFactory(available=True) product = factories.ProductFactory(available=True)
value1 = factories.ProductCategoryParamValueFactory() value1 = factories.ProductTemplateParamValueFactory()
value2 = factories.ProductCategoryParamValueFactory() value2 = factories.ProductTemplateParamValueFactory()
product.params.add(value1) product.params.add(value1)
product.price = 13.0 product.price = 13.0
product.save() product.save()
@ -130,8 +132,8 @@ class ProductTestCase(TestCase):
def test_get_or_create_by_params_success_not_existing_product_no_other_products(self): def test_get_or_create_by_params_success_not_existing_product_no_other_products(self):
template = factories.ProductTemplateFactory() template = factories.ProductTemplateFactory()
value1 = factories.ProductCategoryParamValueFactory() value1 = factories.ProductTemplateParamValueFactory()
value2 = factories.ProductCategoryParamValueFactory() value2 = factories.ProductTemplateParamValueFactory()
prod = store_models.Product.objects.get_or_create_by_params( prod = store_models.Product.objects.get_or_create_by_params(
params=[value1, value2], template=template, params=[value1, value2], template=template,

Wyświetl plik

@ -2,15 +2,15 @@ from django.test import TestCase
from django.shortcuts import reverse from django.shortcuts import reverse
from store.models import ( from store.models import (
ProductCategoryParam, ProductTemplateParam,
ProductCategoryParamValue, ProductTemplateParamValue,
CategoryParamTypeChoices TemplateParamValueChoices
) )
from store.tests.factories import ( from store.tests.factories import (
ProductTemplateFactory, ProductTemplateFactory,
ProductCategoryFactory, ProductCategoryFactory,
ProductFactory, ProductFactory,
ProductCategoryParamValueFactory ProductTemplateParamValueFactory
) )
@ -21,18 +21,18 @@ class ConfigureProductViewTestCase(TestCase):
self.category = ProductCategoryFactory() self.category = ProductCategoryFactory()
self.product_template = ProductTemplateFactory(category=self.category) self.product_template = ProductTemplateFactory(category=self.category)
# create template params and values for those params # create template params and values for those params
self.param1 = ProductCategoryParam.objects.create( self.param1 = ProductTemplateParam.objects.create(
key="Mocowanie", category=self.category, key="Mocowanie", template=self.product_template,
param_type=CategoryParamTypeChoices.STRING param_type=TemplateParamValueChoices.STRING
) )
self.param1_value1 = ProductCategoryParamValueFactory(param=self.param1) self.param1_value1 = ProductTemplateParamValueFactory(param=self.param1)
self.param1_value2 = ProductCategoryParamValueFactory(param=self.param1) self.param1_value2 = ProductTemplateParamValueFactory(param=self.param1)
self.param2 = ProductCategoryParam.objects.create( self.param2 = ProductTemplateParam.objects.create(
key="Format", category=self.category, key="Format", template=self.product_template,
param_type=CategoryParamTypeChoices.STRING param_type=TemplateParamValueChoices.STRING
) )
self.param2_value1 = ProductCategoryParamValueFactory(param=self.param2) self.param2_value1 = ProductTemplateParamValueFactory(param=self.param2)
self.param2_value2 = ProductCategoryParamValueFactory(param=self.param2) self.param2_value2 = ProductTemplateParamValueFactory(param=self.param2)
# create product variant # create product variant
self.variant1 = ProductFactory( self.variant1 = ProductFactory(
template=self.product_template template=self.product_template