Features: 1) Add sku field to Product model with improvements, including unique constraint and default generation; 2) Implement migration to backfill SKUs for existing products.
Fixes: None. Extra: 1) Adjust `.po` and `.mo` files for version change to `2.9.3`; 2) Update translations with minor formatting improvements; 3) Clean up comments in locale files.
This commit is contained in:
parent
e020fe7d08
commit
ec147984ab
191 changed files with 10243 additions and 9577 deletions
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -5,9 +5,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -5,9 +5,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -5,9 +5,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-03 18:33+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
|
|||
|
|
@ -67,11 +67,22 @@ class FieldsetsMixin:
|
|||
fieldsets.append((_("relations"), {"fields": self.relation_fields}))
|
||||
opts = self.model._meta
|
||||
|
||||
meta_fields = []
|
||||
|
||||
if any(f.name == "uuid" for f in opts.fields):
|
||||
if any(f.name == "slug" for f in opts.fields):
|
||||
fieldsets.append((_("metadata"), {"fields": ["uuid", "slug"]}))
|
||||
else:
|
||||
fieldsets.append((_("metadata"), {"fields": ["uuid"]}))
|
||||
meta_fields.append("uuid")
|
||||
|
||||
if any(f.name == "slug" for f in opts.fields):
|
||||
meta_fields.append("slug")
|
||||
|
||||
if any(f.name == "sku" for f in opts.fields):
|
||||
meta_fields.append("sku")
|
||||
|
||||
if any(f.name == "human_readable_id" for f in opts.fields):
|
||||
meta_fields.append("sku")
|
||||
|
||||
if meta_fields:
|
||||
fieldsets.append((_("metadata"), {"fields": meta_fields}))
|
||||
|
||||
ts = []
|
||||
for name in ("created", "modified"):
|
||||
|
|
@ -243,8 +254,8 @@ class ProductAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type:
|
|||
# noinspection PyClassVar
|
||||
model = Product # type: ignore [misc]
|
||||
list_display = (
|
||||
"sku",
|
||||
"name",
|
||||
"partnumber",
|
||||
"is_active",
|
||||
"category",
|
||||
"brand",
|
||||
|
|
@ -269,6 +280,7 @@ class ProductAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type:
|
|||
"category__slug",
|
||||
"uuid",
|
||||
"slug",
|
||||
"sku",
|
||||
)
|
||||
readonly_fields = ("slug", "uuid", "modified", "created")
|
||||
autocomplete_fields = ("category", "brand", "tags")
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ CATEGORY_SCHEMA = {
|
|||
responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS},
|
||||
),
|
||||
"seo": extend_schema(
|
||||
summary=_("SEO Meta Snapshot"),
|
||||
summary=_("SEO Meta snapshot"),
|
||||
description=_("returns a snapshot of the category's SEO meta data"),
|
||||
parameters=[
|
||||
OpenApiParameter(
|
||||
|
|
@ -550,7 +550,7 @@ PRODUCT_SCHEMA = {
|
|||
},
|
||||
),
|
||||
"seo": extend_schema(
|
||||
summary=_("SEO Meta Snapshot"),
|
||||
summary=_("SEO Meta snapshot"),
|
||||
description=_("returns a snapshot of the product's SEO meta data"),
|
||||
parameters=[
|
||||
OpenApiParameter(
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ class ProductFilter(FilterSet):
|
|||
method="filter_include_personal_ordered",
|
||||
label=_("Include personal ordered"),
|
||||
)
|
||||
sku = CharFilter(field_name="sku", lookup_expr="iexact", label=_("SKU"))
|
||||
|
||||
order_by = OrderingFilter(
|
||||
fields=(
|
||||
|
|
@ -88,6 +89,7 @@ class ProductFilter(FilterSet):
|
|||
("created", "created"),
|
||||
("modified", "modified"),
|
||||
("price_order", "price"),
|
||||
("sku", "sku"),
|
||||
("?", "random"),
|
||||
),
|
||||
initial="uuid",
|
||||
|
|
@ -107,6 +109,7 @@ class ProductFilter(FilterSet):
|
|||
"is_active",
|
||||
"tags",
|
||||
"slug",
|
||||
"sku",
|
||||
"min_price",
|
||||
"max_price",
|
||||
"brand",
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ class AttributeGroupType(DjangoObjectType):
|
|||
|
||||
class BrandType(DjangoObjectType):
|
||||
categories = List(lambda: CategoryType, description=_("categories"))
|
||||
seo_meta = Field(SEOMetaType, description=_("SEO meta snapshot"))
|
||||
seo_meta = Field(SEOMetaType, description=_("SEO Meta snapshot"))
|
||||
|
||||
class Meta:
|
||||
model = Brand
|
||||
|
|
@ -204,7 +204,7 @@ class CategoryType(DjangoObjectType):
|
|||
)
|
||||
tags = DjangoFilterConnectionField(lambda: CategoryTagType, description=_("tags for this category"))
|
||||
products = DjangoFilterConnectionField(lambda: ProductType, description=_("products in this category"))
|
||||
seo_meta = Field(SEOMetaType, description=_("SEO meta snapshot"))
|
||||
seo_meta = Field(SEOMetaType, description=_("SEO Meta snapshot"))
|
||||
|
||||
class Meta:
|
||||
model = Category
|
||||
|
|
@ -500,7 +500,7 @@ class ProductType(DjangoObjectType):
|
|||
quantity = Float(description=_("quantity"))
|
||||
feedbacks_count = Int(description=_("number of feedbacks"))
|
||||
personal_orders_only = Boolean(description=_("only available for personal orders"))
|
||||
seo_meta = Field(SEOMetaType, description=_("SEO meta snapshot"))
|
||||
seo_meta = Field(SEOMetaType, description=_("SEO Meta snapshot"))
|
||||
|
||||
class Meta:
|
||||
model = Product
|
||||
|
|
|
|||
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
25
core/migrations/0037_product_sku.py
Normal file
25
core/migrations/0037_product_sku.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 5.2 on 2025-09-01 17:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("core", "0036_vendor_b2b_auth_token_vendor_users"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="product",
|
||||
name="sku",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
default=None,
|
||||
help_text="stock keeping unit for this product",
|
||||
max_length=8,
|
||||
null=True,
|
||||
verbose_name="SKU",
|
||||
),
|
||||
),
|
||||
]
|
||||
44
core/migrations/0038_backfill_product_sku.py
Normal file
44
core/migrations/0038_backfill_product_sku.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
from django.db import migrations, transaction, IntegrityError
|
||||
|
||||
|
||||
def generate_unique_sku(Product, make_candidate, taken):
|
||||
while True:
|
||||
candidate = make_candidate()
|
||||
if candidate in taken:
|
||||
continue
|
||||
if not Product.objects.filter(sku=candidate).exists():
|
||||
taken.add(candidate)
|
||||
return candidate
|
||||
|
||||
|
||||
def backfill_sku(apps, schema_editor):
|
||||
Product = apps.get_model("core", "Product")
|
||||
from core.utils import generate_human_readable_id as make_candidate
|
||||
|
||||
taken = set(Product.objects.exclude(sku__isnull=True).values_list("sku", flat=True))
|
||||
|
||||
qs = Product.objects.filter(sku__isnull=True)
|
||||
BATCH = 500
|
||||
|
||||
start = 0
|
||||
count = qs.count()
|
||||
while start < count:
|
||||
with transaction.atomic():
|
||||
for product in qs.order_by("pk")[start : start + BATCH]:
|
||||
product.sku = generate_unique_sku(Product, make_candidate, taken)
|
||||
product.save(update_fields=["sku"])
|
||||
start += BATCH
|
||||
|
||||
|
||||
def noop(apps, schema_editor):
|
||||
pass
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("core", "0037_product_sku"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(backfill_sku, reverse_code=noop),
|
||||
]
|
||||
25
core/migrations/0039_alter_product_sku.py
Normal file
25
core/migrations/0039_alter_product_sku.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 5.2 on 2025-09-01 17:36
|
||||
|
||||
import core.utils
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("core", "0038_backfill_product_sku"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="product",
|
||||
name="sku",
|
||||
field=models.CharField(
|
||||
default=core.utils.generate_human_readable_id,
|
||||
help_text="stock keeping unit for this product",
|
||||
max_length=8,
|
||||
unique=True,
|
||||
verbose_name="SKU",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
@ -4,8 +4,6 @@ import logging
|
|||
from typing import Any, Optional, Self
|
||||
|
||||
from constance import config
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.gis.db.models import PointField
|
||||
from django.contrib.postgres.indexes import GinIndex
|
||||
from django.core.cache import cache
|
||||
|
|
@ -32,8 +30,6 @@ from django.db.models import (
|
|||
PositiveIntegerField,
|
||||
QuerySet,
|
||||
TextField,
|
||||
UUIDField,
|
||||
URLField,
|
||||
)
|
||||
from django.db.models.indexes import Index
|
||||
from django.http import Http404
|
||||
|
|
@ -680,6 +676,13 @@ class Product(ExportModelOperationsMixin("product"), NiceModel): # type: ignore
|
|||
null=True,
|
||||
verbose_name=_("Slug"),
|
||||
)
|
||||
sku = CharField(
|
||||
help_text=_("stock keeping unit for this product"),
|
||||
verbose_name=_("SKU"),
|
||||
max_length=8,
|
||||
unique=True,
|
||||
default=generate_human_readable_id,
|
||||
)
|
||||
|
||||
objects: ProductManager = ProductManager()
|
||||
|
||||
|
|
@ -2017,20 +2020,3 @@ class Feedback(ExportModelOperationsMixin("feedback"), NiceModel): # type: igno
|
|||
class Meta:
|
||||
verbose_name = _("feedback")
|
||||
verbose_name_plural = _("feedbacks")
|
||||
|
||||
|
||||
class SeoMeta(NiceModel):
|
||||
uuid = None
|
||||
content_type = ForeignKey(ContentType, on_delete=CASCADE)
|
||||
object_id = UUIDField()
|
||||
content_object = GenericForeignKey("content_type", "object_id")
|
||||
|
||||
meta_title = CharField(max_length=70, blank=True)
|
||||
meta_description = CharField(max_length=180, blank=True)
|
||||
canonical_override = URLField(blank=True)
|
||||
robots = CharField(max_length=40, blank=True, default="index,follow")
|
||||
social_image = ImageField(upload_to="seo/", blank=True, null=True)
|
||||
extras = JSONField(blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = ("content_type", "object_id")
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ def send_order_created_email(order_pk: str) -> tuple[bool, str]:
|
|||
except Order.DoesNotExist:
|
||||
return False, f"Order not found with the given pk: {order_pk}"
|
||||
|
||||
if not order.user:
|
||||
if not any([order.user, order.attributes.get("email", None), order.attributes.get("customer_email", None)]):
|
||||
return False, f"Order's user not found with the given pk: {order_pk}"
|
||||
|
||||
activate(order.user.language)
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-18 08:39+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
@ -113,23 +113,23 @@ msgstr "كيان لتخزين بيانات الإعلانات"
|
|||
msgid "An entity for storing analytics data"
|
||||
msgstr "كيان لتخزين بيانات التحليلات"
|
||||
|
||||
#: evibes/settings/constance.py:54
|
||||
#: evibes/settings/constance.py:55
|
||||
msgid "General Options"
|
||||
msgstr "الخيارات العامة"
|
||||
|
||||
#: evibes/settings/constance.py:62
|
||||
#: evibes/settings/constance.py:63
|
||||
msgid "Email Options"
|
||||
msgstr "خيارات البريد الإلكتروني"
|
||||
|
||||
#: evibes/settings/constance.py:71
|
||||
#: evibes/settings/constance.py:72
|
||||
msgid "Payment Gateway Options"
|
||||
msgstr "خيارات بوابة الدفع"
|
||||
|
||||
#: evibes/settings/constance.py:78
|
||||
#: evibes/settings/constance.py:79
|
||||
msgid "Features Options"
|
||||
msgstr "خيارات الميزات"
|
||||
|
||||
#: evibes/settings/constance.py:85
|
||||
#: evibes/settings/constance.py:86
|
||||
msgid "SEO Options"
|
||||
msgstr "خيارات تحسين محركات البحث"
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-18 08:39+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
@ -113,23 +113,23 @@ msgstr "Subjekt pro ukládání dat inzerátů"
|
|||
msgid "An entity for storing analytics data"
|
||||
msgstr "Subjekt pro ukládání analytických dat"
|
||||
|
||||
#: evibes/settings/constance.py:54
|
||||
#: evibes/settings/constance.py:55
|
||||
msgid "General Options"
|
||||
msgstr "Obecné možnosti"
|
||||
|
||||
#: evibes/settings/constance.py:62
|
||||
#: evibes/settings/constance.py:63
|
||||
msgid "Email Options"
|
||||
msgstr "Možnosti e-mailu"
|
||||
|
||||
#: evibes/settings/constance.py:71
|
||||
#: evibes/settings/constance.py:72
|
||||
msgid "Payment Gateway Options"
|
||||
msgstr "Možnosti platební brány"
|
||||
|
||||
#: evibes/settings/constance.py:78
|
||||
#: evibes/settings/constance.py:79
|
||||
msgid "Features Options"
|
||||
msgstr "Možnosti funkcí"
|
||||
|
||||
#: evibes/settings/constance.py:85
|
||||
#: evibes/settings/constance.py:86
|
||||
msgid "SEO Options"
|
||||
msgstr "Možnosti SEO"
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-18 08:39+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
@ -113,23 +113,23 @@ msgstr "En enhed til lagring af annonceringsdata"
|
|||
msgid "An entity for storing analytics data"
|
||||
msgstr "En enhed til lagring af analysedata"
|
||||
|
||||
#: evibes/settings/constance.py:54
|
||||
#: evibes/settings/constance.py:55
|
||||
msgid "General Options"
|
||||
msgstr "Generelle indstillinger"
|
||||
|
||||
#: evibes/settings/constance.py:62
|
||||
#: evibes/settings/constance.py:63
|
||||
msgid "Email Options"
|
||||
msgstr "Indstillinger for e-mail"
|
||||
|
||||
#: evibes/settings/constance.py:71
|
||||
#: evibes/settings/constance.py:72
|
||||
msgid "Payment Gateway Options"
|
||||
msgstr "Muligheder for betalingsgateway"
|
||||
|
||||
#: evibes/settings/constance.py:78
|
||||
#: evibes/settings/constance.py:79
|
||||
msgid "Features Options"
|
||||
msgstr "Funktioner Indstillinger"
|
||||
|
||||
#: evibes/settings/constance.py:85
|
||||
#: evibes/settings/constance.py:86
|
||||
msgid "SEO Options"
|
||||
msgstr "SEO-muligheder"
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-18 08:39+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
@ -113,23 +113,23 @@ msgstr "Eine Einheit zur Speicherung von Werbedaten"
|
|||
msgid "An entity for storing analytics data"
|
||||
msgstr "Eine Einheit zur Speicherung von Analysedaten"
|
||||
|
||||
#: evibes/settings/constance.py:54
|
||||
#: evibes/settings/constance.py:55
|
||||
msgid "General Options"
|
||||
msgstr "Allgemeine Optionen"
|
||||
|
||||
#: evibes/settings/constance.py:62
|
||||
#: evibes/settings/constance.py:63
|
||||
msgid "Email Options"
|
||||
msgstr "E-Mail-Optionen"
|
||||
|
||||
#: evibes/settings/constance.py:71
|
||||
#: evibes/settings/constance.py:72
|
||||
msgid "Payment Gateway Options"
|
||||
msgstr "Zahlungs-Gateway-Optionen"
|
||||
|
||||
#: evibes/settings/constance.py:78
|
||||
#: evibes/settings/constance.py:79
|
||||
msgid "Features Options"
|
||||
msgstr "Merkmale Optionen"
|
||||
|
||||
#: evibes/settings/constance.py:85
|
||||
#: evibes/settings/constance.py:86
|
||||
msgid "SEO Options"
|
||||
msgstr "SEO-Optionen"
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -2,12 +2,12 @@
|
|||
# Copyright (C) 2025 EGOR <FUREUNOIR> GORBUNOV
|
||||
# This file is distributed under the same license as the EVIBES package.
|
||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
||||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-18 08:39+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
@ -117,23 +117,23 @@ msgstr "An entity for storing advertisiment data"
|
|||
msgid "An entity for storing analytics data"
|
||||
msgstr "An entity for storing analytics data"
|
||||
|
||||
#: evibes/settings/constance.py:54
|
||||
#: evibes/settings/constance.py:55
|
||||
msgid "General Options"
|
||||
msgstr "General Options"
|
||||
|
||||
#: evibes/settings/constance.py:62
|
||||
#: evibes/settings/constance.py:63
|
||||
msgid "Email Options"
|
||||
msgstr "Email Options"
|
||||
|
||||
#: evibes/settings/constance.py:71
|
||||
#: evibes/settings/constance.py:72
|
||||
msgid "Payment Gateway Options"
|
||||
msgstr "Payment Gateway Options"
|
||||
|
||||
#: evibes/settings/constance.py:78
|
||||
#: evibes/settings/constance.py:79
|
||||
msgid "Features Options"
|
||||
msgstr "Features Options"
|
||||
|
||||
#: evibes/settings/constance.py:85
|
||||
#: evibes/settings/constance.py:86
|
||||
msgid "SEO Options"
|
||||
msgstr "SEO Options"
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-18 08:39+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
@ -113,23 +113,23 @@ msgstr "An entity for storing advertisiment data"
|
|||
msgid "An entity for storing analytics data"
|
||||
msgstr "An entity for storing analytics data"
|
||||
|
||||
#: evibes/settings/constance.py:54
|
||||
#: evibes/settings/constance.py:55
|
||||
msgid "General Options"
|
||||
msgstr "General Options"
|
||||
|
||||
#: evibes/settings/constance.py:62
|
||||
#: evibes/settings/constance.py:63
|
||||
msgid "Email Options"
|
||||
msgstr "Email Options"
|
||||
|
||||
#: evibes/settings/constance.py:71
|
||||
#: evibes/settings/constance.py:72
|
||||
msgid "Payment Gateway Options"
|
||||
msgstr "Payment Gateway Options"
|
||||
|
||||
#: evibes/settings/constance.py:78
|
||||
#: evibes/settings/constance.py:79
|
||||
msgid "Features Options"
|
||||
msgstr "Features Options"
|
||||
|
||||
#: evibes/settings/constance.py:85
|
||||
#: evibes/settings/constance.py:86
|
||||
msgid "SEO Options"
|
||||
msgstr "SEO Options"
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-18 08:39+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
@ -113,23 +113,23 @@ msgstr "Una entidad para almacenar datos publicitarios"
|
|||
msgid "An entity for storing analytics data"
|
||||
msgstr "Una entidad para almacenar datos analíticos"
|
||||
|
||||
#: evibes/settings/constance.py:54
|
||||
#: evibes/settings/constance.py:55
|
||||
msgid "General Options"
|
||||
msgstr "Opciones generales"
|
||||
|
||||
#: evibes/settings/constance.py:62
|
||||
#: evibes/settings/constance.py:63
|
||||
msgid "Email Options"
|
||||
msgstr "Opciones de correo electrónico"
|
||||
|
||||
#: evibes/settings/constance.py:71
|
||||
#: evibes/settings/constance.py:72
|
||||
msgid "Payment Gateway Options"
|
||||
msgstr "Opciones de pasarela de pago"
|
||||
|
||||
#: evibes/settings/constance.py:78
|
||||
#: evibes/settings/constance.py:79
|
||||
msgid "Features Options"
|
||||
msgstr "Características Opciones"
|
||||
|
||||
#: evibes/settings/constance.py:85
|
||||
#: evibes/settings/constance.py:86
|
||||
msgid "SEO Options"
|
||||
msgstr "Opciones SEO"
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-18 08:39+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
@ -113,23 +113,23 @@ msgstr "Une entité pour stocker des données publicitaires"
|
|||
msgid "An entity for storing analytics data"
|
||||
msgstr "Une entité pour stocker des données analytiques"
|
||||
|
||||
#: evibes/settings/constance.py:54
|
||||
#: evibes/settings/constance.py:55
|
||||
msgid "General Options"
|
||||
msgstr "Options générales"
|
||||
|
||||
#: evibes/settings/constance.py:62
|
||||
#: evibes/settings/constance.py:63
|
||||
msgid "Email Options"
|
||||
msgstr "Options de courrier électronique"
|
||||
|
||||
#: evibes/settings/constance.py:71
|
||||
#: evibes/settings/constance.py:72
|
||||
msgid "Payment Gateway Options"
|
||||
msgstr "Options de passerelle de paiement"
|
||||
|
||||
#: evibes/settings/constance.py:78
|
||||
#: evibes/settings/constance.py:79
|
||||
msgid "Features Options"
|
||||
msgstr "Caractéristiques Options"
|
||||
|
||||
#: evibes/settings/constance.py:85
|
||||
#: evibes/settings/constance.py:86
|
||||
msgid "SEO Options"
|
||||
msgstr "Options de référencement"
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -2,12 +2,12 @@
|
|||
# Copyright (C) 2025 EGOR <FUREUNOIR> GORBUNOV
|
||||
# This file is distributed under the same license as the EVIBES package.
|
||||
# EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>, 2025.
|
||||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: EVIBES 2.9.2\n"
|
||||
"Project-Id-Version: EVIBES 2.9.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-07-18 08:39+0300\n"
|
||||
"POT-Creation-Date: 2025-09-01 20:37+0300\n"
|
||||
"PO-Revision-Date: 2025-06-16 08:59+0100\n"
|
||||
"Last-Translator: EGOR GORBUNOV <CONTACT@FUREUNOIR.COM>\n"
|
||||
"Language-Team: LANGUAGE <CONTACT@FUREUNOIR.COM>\n"
|
||||
|
|
@ -116,23 +116,23 @@ msgstr ""
|
|||
msgid "An entity for storing analytics data"
|
||||
msgstr ""
|
||||
|
||||
#: evibes/settings/constance.py:54
|
||||
#: evibes/settings/constance.py:55
|
||||
msgid "General Options"
|
||||
msgstr ""
|
||||
|
||||
#: evibes/settings/constance.py:62
|
||||
#: evibes/settings/constance.py:63
|
||||
msgid "Email Options"
|
||||
msgstr ""
|
||||
|
||||
#: evibes/settings/constance.py:71
|
||||
#: evibes/settings/constance.py:72
|
||||
msgid "Payment Gateway Options"
|
||||
msgstr ""
|
||||
|
||||
#: evibes/settings/constance.py:78
|
||||
#: evibes/settings/constance.py:79
|
||||
msgid "Features Options"
|
||||
msgstr ""
|
||||
|
||||
#: evibes/settings/constance.py:85
|
||||
#: evibes/settings/constance.py:86
|
||||
msgid "SEO Options"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue