Merge branch 'main' into storefront-nuxt

# Conflicts:
#	storefront/public/robots.txt
This commit is contained in:
Egor Pavlovich Gorbunov 2025-09-15 14:23:54 +03:00
commit 87b62b32e8
99 changed files with 135 additions and 14 deletions

1
.gitignore vendored
View file

@ -91,6 +91,7 @@ share/python-wheels/
pip-log.txt pip-log.txt
pip-delete-this-directory.txt pip-delete-this-directory.txt
desktop.ini desktop.ini
*.iml
# Node build artifacts # Node build artifacts
npm-debug.log* npm-debug.log*

View file

@ -81,7 +81,7 @@ class FieldsetsMixin:
meta_fields.append("sku") meta_fields.append("sku")
if any(f.name == "human_readable_id" for f in opts.fields): if any(f.name == "human_readable_id" for f in opts.fields):
meta_fields.append("sku") meta_fields.append("human_readable_id")
if meta_fields: if meta_fields:
fieldsets.append((_("metadata"), {"fields": meta_fields})) fieldsets.append((_("metadata"), {"fields": meta_fields}))

View file

@ -1,7 +1,7 @@
from django.urls import include, path from django.urls import include, path
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from core.sitemaps import BrandSitemap, CategorySitemap, ProductSitemap from core.sitemaps import BrandSitemap, CategorySitemap, ProductSitemap, StaticPagesSitemap
from core.views import ( from core.views import (
CacheOperatorView, CacheOperatorView,
ContactUsView, ContactUsView,
@ -49,6 +49,7 @@ core_router.register(r"product_tags", ProductTagViewSet, basename="product_tags"
core_router.register(r"order_products", OrderProductViewSet, basename="order_products") core_router.register(r"order_products", OrderProductViewSet, basename="order_products")
sitemaps = { sitemaps = {
"static": StaticPagesSitemap,
"products": ProductSitemap, "products": ProductSitemap,
"categories": CategorySitemap, "categories": CategorySitemap,
"brands": BrandSitemap, "brands": BrandSitemap,

View file

@ -416,18 +416,49 @@ class CategoryFilter(FilterSet):
return queryset return queryset
if field == "?": if field == "?":
parent_order = "?" order_expression = "?"
child_order = "?"
else: else:
parent_order = f"-{field}" if desc else field order_expression = f"-{field}" if desc else field
child_order = parent_order
qs = queryset.order_by(parent_order).prefetch_related(None) qs = queryset.order_by(order_expression).prefetch_related(None)
children_qs = ( def create_ordered_tree_prefetch(max_depth=10):
Category.objects.all().order_by(child_order) if child_order != "?" else Category.objects.all().order_by("?") if field == "?":
)
return qs.prefetch_related(Prefetch("children", queryset=children_qs)) def build_random_prefetch(depth):
if depth <= 0:
return None
children_qs = Category.objects.all().order_by("?")
nested_prefetch = build_random_prefetch(depth - 1)
if nested_prefetch:
children_qs = children_qs.prefetch_related(nested_prefetch)
return Prefetch("children", queryset=children_qs)
return build_random_prefetch(max_depth)
else:
def build_ordered_prefetch(depth):
if depth <= 0:
return None
children_qs = Category.objects.all().order_by(order_expression, "tree_id", "lft")
nested_prefetch = build_ordered_prefetch(depth - 1)
if nested_prefetch:
children_qs = children_qs.prefetch_related(nested_prefetch)
return Prefetch("children", queryset=children_qs)
return build_ordered_prefetch(max_depth)
tree_prefetch = create_ordered_tree_prefetch()
if tree_prefetch:
qs = qs.prefetch_related(tree_prefetch)
return qs
def filter_name(self, queryset, _name, value): def filter_name(self, queryset, _name, value):
search_results = process_query(query=value, request=self.request)["categories"] search_results = process_query(query=value, request=self.request)["categories"]

View file

@ -2338,7 +2338,7 @@ msgstr "{config.PROJECT_NAME} | طلبية تم تسليمها"
#: core/utils/emailing.py:187 #: core/utils/emailing.py:187
#, python-brace-format #, python-brace-format
msgid "{config.PROJECT_NAME} | promocode granted" msgid "{config.PROJECT_NAME} | promocode granted"
msgstr "{config.PROJECT_NAME______} | الرمز الترويجي الممنوح" msgstr "{config.PROJECT_NAME} | الرمز الترويجي الممنوح"
#: core/utils/messages.py:3 #: core/utils/messages.py:3
msgid "you do not have permission to perform this action." msgid "you do not have permission to perform this action."

View file

@ -1,9 +1,85 @@
from django.conf import settings
from django.contrib.sitemaps import Sitemap from django.contrib.sitemaps import Sitemap
from django.utils.translation import gettext_lazy as _
from core.models import Brand, Category, Product from core.models import Brand, Category, Product
from core.utils.seo_builders import any_non_digital
from evibes.settings import LANGUAGE_CODE from evibes.settings import LANGUAGE_CODE
class StaticPagesSitemap(Sitemap):
protocol = "https"
changefreq = "monthly"
priority = 0.8
limit = 1000
PAGES = [
{
"name": _("Home"),
"path": f"/{LANGUAGE_CODE}",
"lastmod": settings.RELEASE_DATE,
},
{
"name": _("Contact Us"),
"path": f"/{LANGUAGE_CODE}/contact-us",
"lastmod": settings.RELEASE_DATE,
},
{
"name": _("About Us"),
"path": f"/{LANGUAGE_CODE}/about-us",
"lastmod": settings.RELEASE_DATE,
},
{
"name": _("Payment Information"),
"path": f"/{LANGUAGE_CODE}/help/payments",
"lastmod": settings.RELEASE_DATE,
},
]
if any_non_digital():
PAGES.append(
{
"name": _("Delivery"),
"path": f"/{LANGUAGE_CODE}/help/delivery",
"lastmod": settings.RELEASE_DATE,
}
)
def items(self):
return self.PAGES
def location(self, obj):
return obj["path"]
def lastmod(self, obj):
return obj.get("lastmod")
# class FeaturedProductsSitemap(Sitemap):
# protocol = "https"
# changefreq = "daily"
# priority = 0.9
# limit = 25000
#
# def items(self):
# return (
# Product.objects.filter(
# is_active=True,
# brand__is_active=True,
# category__is_active=True,
# stocks__isnull=False,
# stocks__vendor__is_active=True,
# )
# .only("uuid", "name", "modified", "slug")
# .order_by("-modified")
# )
#
# def lastmod(self, obj):
# return obj.modified
#
# def location(self, obj):
# return f"/{LANGUAGE_CODE}/product/{obj.slug}"
class ProductSitemap(Sitemap): class ProductSitemap(Sitemap):
protocol = "https" protocol = "https"
changefreq = "daily" changefreq = "daily"

View file

@ -1,6 +1,8 @@
from constance import config from constance import config
from django.conf import settings from django.conf import settings
from core.models import Product
def org_schema(): def org_schema():
return { return {
@ -96,3 +98,7 @@ def brand_schema(brand, url, logo_url=None):
if logo_url: if logo_url:
data["logo"] = logo_url data["logo"] = logo_url
return data return data
def any_non_digital() -> bool:
return Product.objects.filter(is_digital=False).exists()

View file

@ -1,8 +1,10 @@
import logging import logging
from datetime import datetime
from os import getenv, name from os import getenv, name
from pathlib import Path from pathlib import Path
EVIBES_VERSION = "3.0.0" EVIBES_VERSION = "3.0.0"
RELEASE_DATE = datetime(2025, 9, 13)
BASE_DIR = Path(__file__).resolve().parent.parent.parent BASE_DIR = Path(__file__).resolve().parent.parent.parent

View file

@ -2,7 +2,11 @@ User-agent: *
Disallow: /admin/ Disallow: /admin/
Disallow: /static/ Disallow: /static/
Disallow: /media/ Disallow: /media/
Disallow: /profile/ Disallow: /public/wishlist/
Disallow: /public/cart/
Disallow: /public/checkout/
Disallow: /auth/sign-in/
Disallow: /auth/sign-up/
Allow: / Allow: /