refactor(category): replace cache usage with model property for min/max price

remove redundant cache lookups for `min_price` and `max_price` in the category model by leveraging cached properties. minimizes complexity and improves maintainability while ensuring consistent behavior.
This commit is contained in:
Egor Pavlovich Gorbunov 2026-02-25 12:19:39 +03:00
parent 7efc19e081
commit f664b088a4
9 changed files with 90 additions and 57 deletions

View file

@ -3,8 +3,7 @@ from contextlib import suppress
from typing import Any
from django.conf import settings
from django.core.cache import cache
from django.db.models import Max, Min, QuerySet
from django.db.models import QuerySet
from django.utils.translation import gettext_lazy as _
from graphene import (
UUID,
@ -279,21 +278,10 @@ class CategoryType(DjangoObjectType):
return self.filterable_attributes
def resolve_min_max_prices(self: Category, _info):
min_max_prices = cache.get(key=f"{self.name}_min_max_prices", default={})
if not min_max_prices:
price_aggregation = Product.objects.filter(category=self).aggregate(
min_price=Min("stocks__price"), max_price=Max("stocks__price")
)
min_max_prices["min_price"] = price_aggregation.get("min_price", 0.0)
min_max_prices["max_price"] = price_aggregation.get("max_price", 0.0)
cache.set(
key=f"{self.name}_min_max_prices", value=min_max_prices, timeout=86400
)
return {
"min_price": min_max_prices["min_price"],
"max_price": min_max_prices["max_price"],
"min_price": self.min_price,
"max_price": self.max_price,
}
def resolve_brands(self: Category, info) -> QuerySet[Brand]:

View file

@ -14,7 +14,7 @@ class Command(BaseCommand):
# Group stocks by (product, vendor)
stocks_by_group = defaultdict(list)
for stock in Stock.objects.all().order_by("modified"):
stocks_by_group[stock.product_pk].append(stock)
stocks_by_group[stock.product_pk].append(stock) # ty: ignore[possibly-missing-attribute]
stock_deletions: list[str] = []
for group in stocks_by_group.values():

View file

@ -386,9 +386,9 @@ class Command(BaseCommand):
if created:
if "name_ru" in prod_data:
product.name_ru_ru = prod_data["name_ru"]
product.name_ru_ru = prod_data["name_ru"] # ty: ignore[invalid-assignment]
if "description_ru" in prod_data:
product.description_ru_ru = prod_data["description_ru"]
product.description_ru_ru = prod_data["description_ru"] # ty: ignore[invalid-assignment]
product.save()
Stock.objects.create(

View file

@ -2,7 +2,7 @@ import datetime
import json
import logging
from contextlib import suppress
from typing import Any, Iterable, Self
from typing import TYPE_CHECKING, Any, Iterable, Self
from constance import config
from django.conf import settings
@ -29,6 +29,7 @@ from django.db.models import (
JSONField,
ManyToManyField,
Max,
Min,
OneToOneField,
PositiveIntegerField,
QuerySet,
@ -72,6 +73,9 @@ from engine.core.validators import validate_category_image_dimensions
from engine.payments.models import Transaction
from schon.utils.misc import create_object
if TYPE_CHECKING:
from django.db.models import Manager
logger = logging.getLogger(__name__)
@ -83,6 +87,9 @@ class AttributeGroup(NiceModel):
" This can be useful for categorizing and managing attributes more effectively in acomplex system."
)
if TYPE_CHECKING:
attributes: Manager["Attribute"]
is_publicly_visible = True
parent = ForeignKey(
"self",
@ -266,6 +273,10 @@ class Category(NiceModel, MPTTModel):
" as well as assign attributes like images, tags, or priority."
)
if TYPE_CHECKING:
products: Manager["Product"]
children: Manager["Category"]
is_publicly_visible = True
image = ImageField(
@ -450,6 +461,20 @@ class Category(NiceModel, MPTTModel):
is_active=True,
).distinct()
@cached_property
def min_price(self) -> float:
return (
self.products.filter(is_active=True).aggregate(Min("price"))["price__min"]
or 0.0
)
@cached_property
def max_price(self) -> float:
return (
self.products.filter(is_active=True).aggregate(Max("price"))["price__max"]
or 0.0
)
class Meta:
verbose_name = _("category")
verbose_name_plural = _("categories")
@ -604,6 +629,12 @@ class Product(NiceModel):
" its associated information within an application."
)
if TYPE_CHECKING:
images: Manager["ProductImage"]
stocks: Manager["Stock"]
attributes: Manager["AttributeValue"]
category_id: Any
is_publicly_visible = True
category = ForeignKey(
@ -1274,6 +1305,10 @@ class Order(NiceModel):
" Equally, functionality supports managing the products in the order lifecycle."
)
if TYPE_CHECKING:
order_products: Manager["OrderProduct"]
payments_transactions: Manager[Transaction]
is_publicly_visible = False
billing_address = ForeignKey(
@ -1442,7 +1477,8 @@ class Order(NiceModel):
if promotions.exists():
buy_price -= round(
product.price * (promotions.first().discount_percent / 100), 2
product.price * (promotions.first().discount_percent / 100), # ty: ignore[possibly-missing-attribute]
2,
)
order_product, is_created = OrderProduct.objects.get_or_create(
@ -1487,7 +1523,7 @@ class Order(NiceModel):
order_product.delete()
return self
if order_product.quantity == 1:
self.order_products.remove(order_product)
self.order_products.remove(order_product) # ty: ignore[unresolved-attribute]
order_product.delete()
else:
order_product.quantity -= 1
@ -1510,7 +1546,7 @@ class Order(NiceModel):
_("you cannot remove products from an order that is not a pending one")
)
for order_product in self.order_products.all():
self.order_products.remove(order_product)
self.order_products.remove(order_product) # ty: ignore[unresolved-attribute]
order_product.delete()
return self
@ -1522,7 +1558,7 @@ class Order(NiceModel):
try:
product = Product.objects.get(uuid=product_uuid)
order_product = self.order_products.get(product=product, order=self)
self.order_products.remove(order_product)
self.order_products.remove(order_product) # ty: ignore[unresolved-attribute]
order_product.delete()
except Product.DoesNotExist as dne:
name = "Product"
@ -1788,6 +1824,8 @@ class Order(NiceModel):
crm_links = OrderCrmLink.objects.filter(order=self)
if crm_links.exists():
crm_link = crm_links.first()
if not crm_link:
return False
crm_integration = create_object(
crm_link.crm.integration_location, crm_link.crm.name
)
@ -1894,6 +1932,9 @@ class OrderProduct(NiceModel):
"and stores a reference to them."
)
if TYPE_CHECKING:
download: "DigitalAssetDownload"
is_publicly_visible = False
buy_price = FloatField(

View file

@ -174,7 +174,7 @@ def get_top_returned_products(
p = product_by_id[pid]
img = ""
with suppress(Exception):
img = p.images.first().image_url if p.images.exists() else ""
img = p.images.first().image_url if p.images.exists() else "" # ty: ignore[possibly-missing-attribute]
result.append(
{
"name": p.name,

View file

@ -8,7 +8,7 @@ from datetime import datetime
from decimal import Decimal
from io import BytesIO
from math import ceil, log10
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, TypeVar
from constance import config
from django.conf import settings
@ -36,6 +36,8 @@ from engine.payments.errors import RatesError
from engine.payments.utils import get_rates
from schon.utils.misc import LoggingError, LogLevel
_BrandOrCategory = TypeVar("_BrandOrCategory", Brand, Category)
if TYPE_CHECKING:
from engine.core.models import OrderProduct
@ -320,8 +322,8 @@ class AbstractVendor(ABC):
@staticmethod
def _auto_resolver_helper(
model: type[Brand] | type[Category], resolving_name: str
) -> Brand | Category | None:
model: type[_BrandOrCategory], resolving_name: str
) -> _BrandOrCategory | None:
"""Internal helper for resolving Brand/Category by name with deduplication."""
queryset = model.objects.filter(name=resolving_name)
if not queryset.exists():
@ -672,6 +674,8 @@ class AbstractVendor(ABC):
.order_by("uuid")
.first()
)
if not attribute:
return None
fields_to_update: list[str] = []
if not attribute.is_active:
attribute.is_active = True

View file

@ -607,7 +607,7 @@ def dashboard_callback(request: HttpRequest, context: Context) -> Context:
product = Product.objects.filter(pk=wished_first["products"]).first()
if product:
img = (
product.images.first().image_url if product.images.exists() else ""
product.images.first().image_url if product.images.exists() else "" # ty: ignore[possibly-missing-attribute]
)
most_wished = {
"name": product.name,
@ -631,7 +631,7 @@ def dashboard_callback(request: HttpRequest, context: Context) -> Context:
if not pid or pid not in product_by_id:
continue
p = product_by_id[pid]
img = p.images.first().image_url if p.images.exists() else ""
img = p.images.first().image_url if p.images.exists() else "" # ty: ignore[possibly-missing-attribute]
most_wished_list.append(
{
"name": p.name,
@ -687,10 +687,10 @@ def dashboard_callback(request: HttpRequest, context: Context) -> Context:
.order_by("total_qty")[:5]
)
for p in products:
qty = int(p.total_qty or 0)
qty = int(p.total_qty or 0) # ty: ignore[possibly-missing-attribute]
img = ""
with suppress(Exception):
img = p.images.first().image_url if p.images.exists() else ""
img = p.images.first().image_url if p.images.exists() else "" # ty: ignore[possibly-missing-attribute]
low_stock_list.append(
{
"name": p.name,
@ -734,7 +734,7 @@ def dashboard_callback(request: HttpRequest, context: Context) -> Context:
product = Product.objects.filter(pk=popular_first["product"]).first()
if product:
img = (
product.images.first().image_url if product.images.exists() else ""
product.images.first().image_url if product.images.exists() else "" # ty: ignore[possibly-missing-attribute]
)
most_popular = {
"name": product.name,
@ -758,7 +758,7 @@ def dashboard_callback(request: HttpRequest, context: Context) -> Context:
if not pid or pid not in product_by_id:
continue
p = product_by_id[pid]
img = p.images.first().image_url if p.images.exists() else ""
img = p.images.first().image_url if p.images.exists() else "" # ty: ignore[possibly-missing-attribute]
most_popular_list.append(
{
"name": p.name,

View file

@ -22,7 +22,7 @@ dependencies = [
"django-elasticsearch-dsl==8.2",
"django-extensions==4.1",
"django-filter==25.2",
"django-health-check==4.0.4",
"django-health-check==4.0.6",
"django-import-export[all]==4.4.0",
"django-json-widget==2.1.1",
"django-model-utils==5.0.0",
@ -90,10 +90,10 @@ linting = [
"types-paramiko==4.0.0.20250822",
"types-psutil==7.2.2.20260130",
"types-pillow==10.2.0.20240822",
"types-docutils==0.22.3.20251115",
"types-docutils==0.22.3.20260223",
"types-six==1.17.0.20251009",
]
openai = ["openai==2.21.0"]
openai = ["openai==2.24.0"]
jupyter = ["jupyter==1.1.1"]
[tool.uv]

42
uv.lock
View file

@ -388,11 +388,11 @@ wheels = [
[[package]]
name = "certifi"
version = "2026.1.4"
version = "2026.2.25"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" }
sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" },
{ url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" },
]
[[package]]
@ -880,15 +880,15 @@ wheels = [
[[package]]
name = "django-health-check"
version = "4.0.4"
version = "4.0.6"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
{ name = "dnspython" },
]
sdist = { url = "https://files.pythonhosted.org/packages/dc/ea/5abd492cc9ea536edba5d436a84086f1c0fcdc66fd023a1f4cc086d39a56/django_health_check-4.0.4.tar.gz", hash = "sha256:b2349ff9d75dc52e203be20f461eabae6b203f2566e5ba888bc885168decaaa9", size = 20496, upload-time = "2026-02-18T13:08:42.442Z" }
sdist = { url = "https://files.pythonhosted.org/packages/92/fe/718725c58fd177cff0cfb8abe3010f2cad582713f2bc52eaf7120b750dec/django_health_check-4.0.6.tar.gz", hash = "sha256:03837041ba8a235e810e16218f2ef3feb372c4af72776fa3676c16435c72171c", size = 20763, upload-time = "2026-02-23T17:11:40.625Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d8/12/8f1fc3b2bd8516c4e71d988b1218543ab0ef3fd21545302bdaf91a57f50d/django_health_check-4.0.4-py3-none-any.whl", hash = "sha256:6c91efa2e3b4f4b280aa5646b6347385f57010314c395aa6af3f7c64f75cd1f8", size = 25476, upload-time = "2026-02-18T13:08:40.91Z" },
{ url = "https://files.pythonhosted.org/packages/3a/44/2fa6ec47c1c18159c094f7d00397a208b6311e8b26d603dd22ba6e79b99d/django_health_check-4.0.6-py3-none-any.whl", hash = "sha256:efba106bc4f92b1b084f3af751e9eeb0b5c1af77d0af212e432ede2ba8f1e94f", size = 25813, upload-time = "2026-02-23T17:11:39.419Z" },
]
[[package]]
@ -1920,7 +1920,7 @@ wheels = [
[[package]]
name = "jupyterlab"
version = "4.5.4"
version = "4.5.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "async-lru" },
@ -1937,9 +1937,9 @@ dependencies = [
{ name = "tornado" },
{ name = "traitlets" },
]
sdist = { url = "https://files.pythonhosted.org/packages/7c/6b/21af7c0512bdf67e0c54c121779a1f2a97a164a7657e13fced79db8fa5a0/jupyterlab-4.5.4.tar.gz", hash = "sha256:c215f48d8e4582bd2920ad61cc6a40d8ebfef7e5a517ae56b8a9413c9789fdfb", size = 23943597, upload-time = "2026-02-11T00:26:55.308Z" }
sdist = { url = "https://files.pythonhosted.org/packages/6e/2d/953a5612a34a3c799a62566a548e711d103f631672fd49650e0f2de80870/jupyterlab-4.5.5.tar.gz", hash = "sha256:eac620698c59eb810e1729909be418d9373d18137cac66637141abba613b3fda", size = 23968441, upload-time = "2026-02-23T18:57:34.339Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f5/9f/a70972ece62ead2d81acc6223188f6d18a92f665ccce17796a0cdea4fcf5/jupyterlab-4.5.4-py3-none-any.whl", hash = "sha256:cc233f70539728534669fb0015331f2a3a87656207b3bb2d07916e9289192f12", size = 12391867, upload-time = "2026-02-11T00:26:51.23Z" },
{ url = "https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl", hash = "sha256:a35694a40a8e7f2e82f387472af24e61b22adcce87b5a8ab97a5d9c486202a6d", size = 12446824, upload-time = "2026-02-23T18:57:30.398Z" },
]
[[package]]
@ -2281,7 +2281,7 @@ wheels = [
[[package]]
name = "notebook"
version = "7.5.3"
version = "7.5.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jupyter-server" },
@ -2290,9 +2290,9 @@ dependencies = [
{ name = "notebook-shim" },
{ name = "tornado" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b8/cb/cc7f4df5cee315dd126a47eb60890690a0438d5e0dd40c32d60ce16de377/notebook-7.5.3.tar.gz", hash = "sha256:393ceb269cf9fdb02a3be607a57d7bd5c2c14604f1818a17dbeb38e04f98cbfa", size = 14073140, upload-time = "2026-01-26T07:28:36.605Z" }
sdist = { url = "https://files.pythonhosted.org/packages/78/08/9d446fbb49f95de316ea6d7f25d0a4bc95117dd574e35f405895ac706f29/notebook-7.5.4.tar.gz", hash = "sha256:b928b2ba22cb63aa83df2e0e76fe3697950a0c1c4a41b84ebccf1972b1bb5771", size = 14167892, upload-time = "2026-02-24T14:13:56.116Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/96/98/9286e7f35e5584ebb79f997f2fb0cb66745c86f6c5fccf15ba32aac5e908/notebook-7.5.3-py3-none-any.whl", hash = "sha256:c997bfa1a2a9eb58c9bbb7e77d50428befb1033dd6f02c482922e96851d67354", size = 14481744, upload-time = "2026-01-26T07:28:31.867Z" },
{ url = "https://files.pythonhosted.org/packages/59/01/05e5387b53e0f549212d5eff58845886f3827617b5c9409c966ddc07cb6d/notebook-7.5.4-py3-none-any.whl", hash = "sha256:860e31782b3d3a25ca0819ff039f5cf77845d1bf30c78ef9528b88b25e0a9850", size = 14578014, upload-time = "2026-02-24T14:13:52.274Z" },
]
[[package]]
@ -2358,7 +2358,7 @@ sdist = { url = "https://files.pythonhosted.org/packages/97/73/8ade73f6749177003
[[package]]
name = "openai"
version = "2.21.0"
version = "2.24.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@ -2370,9 +2370,9 @@ dependencies = [
{ name = "tqdm" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/92/e5/3d197a0947a166649f566706d7a4c8f7fe38f1fa7b24c9bcffe4c7591d44/openai-2.21.0.tar.gz", hash = "sha256:81b48ce4b8bbb2cc3af02047ceb19561f7b1dc0d4e52d1de7f02abfd15aa59b7", size = 644374, upload-time = "2026-02-14T00:12:01.577Z" }
sdist = { url = "https://files.pythonhosted.org/packages/55/13/17e87641b89b74552ed408a92b231283786523edddc95f3545809fab673c/openai-2.24.0.tar.gz", hash = "sha256:1e5769f540dbd01cb33bc4716a23e67b9d695161a734aff9c5f925e2bf99a673", size = 658717, upload-time = "2026-02-24T20:02:07.958Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/56/0a89092a453bb2c676d66abee44f863e742b2110d4dbb1dbcca3f7e5fc33/openai-2.21.0-py3-none-any.whl", hash = "sha256:0bc1c775e5b1536c294eded39ee08f8407656537ccc71b1004104fe1602e267c", size = 1103065, upload-time = "2026-02-14T00:11:59.603Z" },
{ url = "https://files.pythonhosted.org/packages/c9/30/844dc675ee6902579b8eef01ed23917cc9319a1c9c0c14ec6e39340c96d0/openai-2.24.0-py3-none-any.whl", hash = "sha256:fed30480d7d6c884303287bde864980a4b137b60553ffbcf9ab4a233b7a73d94", size = 1120122, upload-time = "2026-02-24T20:02:05.669Z" },
]
[[package]]
@ -3440,7 +3440,7 @@ requires-dist = [
{ name = "django-elasticsearch-dsl", specifier = "==8.2" },
{ name = "django-extensions", specifier = "==4.1" },
{ name = "django-filter", specifier = "==25.2" },
{ name = "django-health-check", specifier = "==4.0.4" },
{ name = "django-health-check", specifier = "==4.0.6" },
{ name = "django-import-export", extras = ["all"], specifier = "==4.4.0" },
{ name = "django-json-widget", specifier = "==2.1.1" },
{ name = "django-md-field", specifier = "==0.1.0" },
@ -3471,7 +3471,7 @@ requires-dist = [
{ name = "graphene-file-upload", specifier = "==1.3.0" },
{ name = "httpx", specifier = "==0.28.1" },
{ name = "jupyter", marker = "extra == 'jupyter'", specifier = "==1.1.1" },
{ name = "openai", marker = "extra == 'openai'", specifier = "==2.21.0" },
{ name = "openai", marker = "extra == 'openai'", specifier = "==2.24.0" },
{ name = "opentelemetry-instrumentation-django", specifier = "==0.60b1" },
{ name = "paramiko", specifier = "==4.0.0" },
{ name = "pillow", specifier = "==12.1.1" },
@ -3490,7 +3490,7 @@ requires-dist = [
{ name = "six", specifier = "==1.17.0" },
{ name = "swapper", specifier = "==1.4.0" },
{ name = "ty", marker = "extra == 'linting'", specifier = "==0.0.16" },
{ name = "types-docutils", marker = "extra == 'linting'", specifier = "==0.22.3.20251115" },
{ name = "types-docutils", marker = "extra == 'linting'", specifier = "==0.22.3.20260223" },
{ name = "types-paramiko", marker = "extra == 'linting'", specifier = "==4.0.0.20250822" },
{ name = "types-pillow", marker = "extra == 'linting'", specifier = "==10.2.0.20240822" },
{ name = "types-psutil", marker = "extra == 'linting'", specifier = "==7.2.2.20260130" },
@ -3747,11 +3747,11 @@ wheels = [
[[package]]
name = "types-docutils"
version = "0.22.3.20251115"
version = "0.22.3.20260223"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/eb/d7/576ec24bf61a280f571e1f22284793adc321610b9bcfba1bf468cf7b334f/types_docutils-0.22.3.20251115.tar.gz", hash = "sha256:0f79ea6a7bd4d12d56c9f824a0090ffae0ea4204203eb0006392906850913e16", size = 56828, upload-time = "2025-11-15T02:59:57.371Z" }
sdist = { url = "https://files.pythonhosted.org/packages/80/33/92c0129283363e3b3ba270bf6a2b7d077d949d2f90afc4abaf6e73578563/types_docutils-0.22.3.20260223.tar.gz", hash = "sha256:e90e868da82df615ea2217cf36dff31f09660daa15fc0f956af53f89c1364501", size = 57230, upload-time = "2026-02-23T04:11:21.806Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9c/01/61ac9eb38f1f978b47443dc6fd2e0a3b0f647c2da741ddad30771f1b2b6f/types_docutils-0.22.3.20251115-py3-none-any.whl", hash = "sha256:c6e53715b65395d00a75a3a8a74e352c669bc63959e65a207dffaa22f4a2ad6e", size = 91951, upload-time = "2025-11-15T02:59:56.413Z" },
{ url = "https://files.pythonhosted.org/packages/ba/c7/a4ae6a75d5b07d63089d5c04d450a0de4a5d48ffcb84b95659b22d3885fe/types_docutils-0.22.3.20260223-py3-none-any.whl", hash = "sha256:cc2d6b7560a28e351903db0989091474aa619ad287843a018324baee9c4d9a8f", size = 91969, upload-time = "2026-02-23T04:11:20.966Z" },
]
[[package]]