Features: 1) None;
Fixes: 1) Correct formatting of multi-line expressions for better readability; 2) Ensure consistent use of single-line expressions where appropriate; 3) Fix minor spacing issues in text fields; 4) Adjust admin model field `general_fields` to include `priority`; Extra: Refactored several multi-line statements to improve consistency and code style.
This commit is contained in:
parent
9f703fe5e5
commit
eb68132dd3
12 changed files with 88 additions and 167 deletions
|
|
@ -14,7 +14,10 @@ class PostAdmin(SummernoteModelAdminMixin, FieldsetsMixin, BasicModelAdmin):
|
||||||
filter_horizontal = ("tags",)
|
filter_horizontal = ("tags",)
|
||||||
date_hierarchy = "created"
|
date_hierarchy = "created"
|
||||||
autocomplete_fields = ("author", "tags")
|
autocomplete_fields = ("author", "tags")
|
||||||
readonly_fields = ("uuid", "slug",)
|
readonly_fields = (
|
||||||
|
"uuid",
|
||||||
|
"slug",
|
||||||
|
)
|
||||||
|
|
||||||
summernote_fields = ("content",)
|
summernote_fields = ("content",)
|
||||||
general_fields = [
|
general_fields = [
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,7 @@ class NiceModel(Model):
|
||||||
is_active: bool = BooleanField( # type: ignore
|
is_active: bool = BooleanField( # type: ignore
|
||||||
default=True,
|
default=True,
|
||||||
verbose_name=_("is active"),
|
verbose_name=_("is active"),
|
||||||
help_text=_(
|
help_text=_("if set to false, this object can't be seen by users without needed permission"),
|
||||||
"if set to false, this object can't be seen by users without needed permission"
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
created: datetime = CreationDateTimeField( # type: ignore
|
created: datetime = CreationDateTimeField( # type: ignore
|
||||||
_("created"), help_text=_("when the object first appeared on the database")
|
_("created"), help_text=_("when the object first appeared on the database")
|
||||||
|
|
@ -30,9 +28,7 @@ class NiceModel(Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(self, **kwargs):
|
||||||
self.update_modified = kwargs.pop(
|
self.update_modified = kwargs.pop("update_modified", getattr(self, "update_modified", True))
|
||||||
"update_modified", getattr(self, "update_modified", True)
|
|
||||||
)
|
|
||||||
super().save(**kwargs)
|
super().save(**kwargs)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ class CategoryAdmin(FieldsetsMixin, DraggableMPTTAdmin, BasicModelAdmin):
|
||||||
autocomplete_fields = ["parent", "tags"]
|
autocomplete_fields = ["parent", "tags"]
|
||||||
readonly_fields = ("slug", "uuid", "modified", "created")
|
readonly_fields = ("slug", "uuid", "modified", "created")
|
||||||
|
|
||||||
general_fields = ["is_active", "name", "description", "image", "markup_percent"]
|
general_fields = ["is_active", "name", "description", "image", "markup_percent", "priority"]
|
||||||
relation_fields = ["parent", "tags"]
|
relation_fields = ["parent", "tags"]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -219,7 +219,7 @@ class BrandAdmin(FieldsetsMixin, BasicModelAdmin):
|
||||||
search_fields = ("uuid", "name", "categories__name")
|
search_fields = ("uuid", "name", "categories__name")
|
||||||
readonly_fields = ("uuid", "slug", "modified", "created")
|
readonly_fields = ("uuid", "slug", "modified", "created")
|
||||||
|
|
||||||
general_fields = ["is_active", "name", "description"]
|
general_fields = ["is_active", "name", "description", "priority"]
|
||||||
relation_fields = ["small_logo", "big_logo", "categories"]
|
relation_fields = ["small_logo", "big_logo", "categories"]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,19 +15,15 @@ SMART_FIELDS = [
|
||||||
"name^6",
|
"name^6",
|
||||||
"name.ngram^5",
|
"name.ngram^5",
|
||||||
"name.phonetic",
|
"name.phonetic",
|
||||||
|
|
||||||
"title^4",
|
"title^4",
|
||||||
"title.ngram^3",
|
"title.ngram^3",
|
||||||
"title.phonetic",
|
"title.phonetic",
|
||||||
|
|
||||||
"description^2",
|
"description^2",
|
||||||
"description.ngram",
|
"description.ngram",
|
||||||
"description.phonetic",
|
"description.phonetic",
|
||||||
|
|
||||||
"brand__name^3",
|
"brand__name^3",
|
||||||
"brand__name.ngram",
|
"brand__name.ngram",
|
||||||
"brand__name.auto",
|
"brand__name.auto",
|
||||||
|
|
||||||
"category__name^2",
|
"category__name^2",
|
||||||
"category__name.ngram",
|
"category__name.ngram",
|
||||||
"category__name.auto",
|
"category__name.auto",
|
||||||
|
|
@ -71,7 +67,6 @@ functions = [
|
||||||
"missing": 0,
|
"missing": 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
# category-level boost when searching for categories
|
# category-level boost when searching for categories
|
||||||
{
|
{
|
||||||
"filter": Q("term", **{"_index": "categories"}),
|
"filter": Q("term", **{"_index": "categories"}),
|
||||||
|
|
@ -82,7 +77,6 @@ functions = [
|
||||||
"missing": 0,
|
"missing": 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
# brand-level boost when searching for brands
|
# brand-level boost when searching for brands
|
||||||
{
|
{
|
||||||
"filter": Q("term", **{"_index": "brands"}),
|
"filter": Q("term", **{"_index": "brands"}),
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,9 @@ class _BaseDoc(ActiveOnlyMixin, Document):
|
||||||
analyzer="standard",
|
analyzer="standard",
|
||||||
fields={
|
fields={
|
||||||
"raw": fields.KeywordField(ignore_above=256),
|
"raw": fields.KeywordField(ignore_above=256),
|
||||||
"ngram": fields.TextField(
|
"ngram": fields.TextField(analyzer="name_ngram", search_analyzer="query_lc"),
|
||||||
analyzer="name_ngram", search_analyzer="query_lc"
|
|
||||||
),
|
|
||||||
"phonetic": fields.TextField(analyzer="name_phonetic"),
|
"phonetic": fields.TextField(analyzer="name_phonetic"),
|
||||||
"auto": fields.TextField(
|
"auto": fields.TextField(analyzer="autocomplete", search_analyzer="autocomplete_search"),
|
||||||
analyzer="autocomplete", search_analyzer="autocomplete_search"
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
description = fields.TextField(
|
description = fields.TextField(
|
||||||
|
|
@ -26,13 +22,9 @@ class _BaseDoc(ActiveOnlyMixin, Document):
|
||||||
analyzer="standard",
|
analyzer="standard",
|
||||||
fields={
|
fields={
|
||||||
"raw": fields.KeywordField(ignore_above=256),
|
"raw": fields.KeywordField(ignore_above=256),
|
||||||
"ngram": fields.TextField(
|
"ngram": fields.TextField(analyzer="name_ngram", search_analyzer="query_lc"),
|
||||||
analyzer="name_ngram", search_analyzer="query_lc"
|
|
||||||
),
|
|
||||||
"phonetic": fields.TextField(analyzer="name_phonetic"),
|
"phonetic": fields.TextField(analyzer="name_phonetic"),
|
||||||
"auto": fields.TextField(
|
"auto": fields.TextField(analyzer="autocomplete", search_analyzer="autocomplete_search"),
|
||||||
analyzer="autocomplete", search_analyzer="autocomplete_search"
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
slug = fields.KeywordField(attr="slug", index=False)
|
slug = fields.KeywordField(attr="slug", index=False)
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -118,11 +118,11 @@ msgstr "Наличия"
|
||||||
|
|
||||||
#: core/admin.py:139 core/models.py:1384
|
#: core/admin.py:139 core/models.py:1384
|
||||||
msgid "order product"
|
msgid "order product"
|
||||||
msgstr "Заказать товар"
|
msgstr "Заказанный товар"
|
||||||
|
|
||||||
#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385
|
#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385
|
||||||
msgid "order products"
|
msgid "order products"
|
||||||
msgstr "Заказать товары"
|
msgstr "Заказанные товары"
|
||||||
|
|
||||||
#: core/admin.py:158 core/admin.py:159
|
#: core/admin.py:158 core/admin.py:159
|
||||||
msgid "children"
|
msgid "children"
|
||||||
|
|
|
||||||
137
core/models.py
137
core/models.py
|
|
@ -92,9 +92,7 @@ class Vendor(ExportModelOperationsMixin("vendor"), NiceModel):
|
||||||
authentication: dict = JSONField( # type: ignore
|
authentication: dict = JSONField( # type: ignore
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
help_text=_(
|
help_text=_("stores credentials and endpoints required for vendor communication"),
|
||||||
"stores credentials and endpoints required for vendor communication"
|
|
||||||
),
|
|
||||||
verbose_name=_("authentication info"),
|
verbose_name=_("authentication info"),
|
||||||
)
|
)
|
||||||
markup_percent: int = IntegerField( # type: ignore
|
markup_percent: int = IntegerField( # type: ignore
|
||||||
|
|
@ -247,10 +245,7 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel):
|
||||||
def get_tree_depth(self):
|
def get_tree_depth(self):
|
||||||
if self.is_leaf_node():
|
if self.is_leaf_node():
|
||||||
return 0
|
return 0
|
||||||
return (
|
return self.get_descendants().aggregate(max_depth=Max("level"))["max_depth"] - self.get_level()
|
||||||
self.get_descendants().aggregate(max_depth=Max("level"))["max_depth"]
|
|
||||||
- self.get_level()
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("category")
|
verbose_name = _("category")
|
||||||
|
|
@ -414,9 +409,7 @@ class Product(ExportModelOperationsMixin("product"), NiceModel):
|
||||||
cache_key = f"product_feedbacks_count_{self.pk}"
|
cache_key = f"product_feedbacks_count_{self.pk}"
|
||||||
feedbacks_count = cache.get(cache_key)
|
feedbacks_count = cache.get(cache_key)
|
||||||
if feedbacks_count is None:
|
if feedbacks_count is None:
|
||||||
feedbacks_count = Feedback.objects.filter(
|
feedbacks_count = Feedback.objects.filter(order_product__product_id=self.pk).count()
|
||||||
order_product__product_id=self.pk
|
|
||||||
).count()
|
|
||||||
cache.set(cache_key, feedbacks_count, 604800)
|
cache.set(cache_key, feedbacks_count, 604800)
|
||||||
return feedbacks_count
|
return feedbacks_count
|
||||||
|
|
||||||
|
|
@ -718,9 +711,7 @@ class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel):
|
||||||
class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel):
|
class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel):
|
||||||
is_publicly_visible = True
|
is_publicly_visible = True
|
||||||
|
|
||||||
product: ForeignKey = ForeignKey(
|
product: ForeignKey = ForeignKey(to=Product, on_delete=CASCADE, related_name="documentaries")
|
||||||
to=Product, on_delete=CASCADE, related_name="documentaries"
|
|
||||||
)
|
|
||||||
document = FileField(upload_to=get_product_uuid_as_path)
|
document = FileField(upload_to=get_product_uuid_as_path)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -848,9 +839,7 @@ class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel):
|
||||||
self.discount_amount is None and self.discount_percent is None
|
self.discount_amount is None and self.discount_percent is None
|
||||||
):
|
):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_(
|
_("only one type of discount should be defined (amount or percent), but not both or neither.")
|
||||||
"only one type of discount should be defined (amount or percent), but not both or neither."
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
super().save(**kwargs)
|
super().save(**kwargs)
|
||||||
|
|
||||||
|
|
@ -871,15 +860,11 @@ class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel):
|
||||||
|
|
||||||
if self.discount_type == "percent":
|
if self.discount_type == "percent":
|
||||||
amount -= round(amount * (self.discount_percent / 100), 2)
|
amount -= round(amount * (self.discount_percent / 100), 2)
|
||||||
order.attributes.update(
|
order.attributes.update({"promocode": str(self.uuid), "final_price": amount})
|
||||||
{"promocode": str(self.uuid), "final_price": amount}
|
|
||||||
)
|
|
||||||
order.save()
|
order.save()
|
||||||
elif self.discount_type == "amount":
|
elif self.discount_type == "amount":
|
||||||
amount -= round(float(self.discount_amount), 2)
|
amount -= round(float(self.discount_amount), 2)
|
||||||
order.attributes.update(
|
order.attributes.update({"promocode": str(self.uuid), "final_price": amount})
|
||||||
{"promocode": str(self.uuid), "final_price": amount}
|
|
||||||
)
|
|
||||||
order.save()
|
order.save()
|
||||||
else:
|
else:
|
||||||
raise ValueError(_(f"invalid discount type for promocode {self.uuid}"))
|
raise ValueError(_(f"invalid discount type for promocode {self.uuid}"))
|
||||||
|
|
@ -987,8 +972,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
sum(
|
sum(
|
||||||
(
|
(
|
||||||
order_product.buy_price * order_product.quantity
|
order_product.buy_price * order_product.quantity
|
||||||
if order_product.status not in FAILED_STATUSES
|
if order_product.status not in FAILED_STATUSES and order_product.buy_price is not None
|
||||||
and order_product.buy_price is not None
|
|
||||||
else 0.0
|
else 0.0
|
||||||
)
|
)
|
||||||
for order_product in self.order_products.all()
|
for order_product in self.order_products.all()
|
||||||
|
|
@ -1012,9 +996,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
attributes = []
|
attributes = []
|
||||||
|
|
||||||
if self.status not in ["PENDING", "MOMENTAL"]:
|
if self.status not in ["PENDING", "MOMENTAL"]:
|
||||||
raise ValueError(
|
raise ValueError(_("you cannot add products to an order that is not a pending one"))
|
||||||
_("you cannot add products to an order that is not a pending one")
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
product = Product.objects.get(uuid=product_uuid)
|
product = Product.objects.get(uuid=product_uuid)
|
||||||
|
|
||||||
|
|
@ -1023,9 +1005,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
|
|
||||||
buy_price = product.price
|
buy_price = product.price
|
||||||
|
|
||||||
promotions = Promotion.objects.filter(
|
promotions = Promotion.objects.filter(is_active=True, products__in=[product]).order_by("discount_percent")
|
||||||
is_active=True, products__in=[product]
|
|
||||||
).order_by("discount_percent")
|
|
||||||
|
|
||||||
if promotions.exists():
|
if promotions.exists():
|
||||||
buy_price -= round(product.price * (promotions.first().discount_percent / 100), 2) # type: ignore
|
buy_price -= round(product.price * (promotions.first().discount_percent / 100), 2) # type: ignore
|
||||||
|
|
@ -1038,9 +1018,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
)
|
)
|
||||||
if not is_created and update_quantity:
|
if not is_created and update_quantity:
|
||||||
if product.quantity < order_product.quantity + 1:
|
if product.quantity < order_product.quantity + 1:
|
||||||
raise BadRequest(
|
raise BadRequest(_("you cannot add more products than available in stock"))
|
||||||
_("you cannot add more products than available in stock")
|
|
||||||
)
|
|
||||||
order_product.quantity += 1
|
order_product.quantity += 1
|
||||||
order_product.buy_price = product.price
|
order_product.buy_price = product.price
|
||||||
order_product.save()
|
order_product.save()
|
||||||
|
|
@ -1061,9 +1039,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
attributes = {}
|
attributes = {}
|
||||||
|
|
||||||
if self.status not in ["PENDING", "MOMENTAL"]:
|
if self.status not in ["PENDING", "MOMENTAL"]:
|
||||||
raise ValueError(
|
raise ValueError(_("you cannot remove products from an order that is not a pending one"))
|
||||||
_("you cannot remove products from an order that is not a pending one")
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
product = Product.objects.get(uuid=product_uuid)
|
product = Product.objects.get(uuid=product_uuid)
|
||||||
order_product = self.order_products.get(product=product, order=self)
|
order_product = self.order_products.get(product=product, order=self)
|
||||||
|
|
@ -1082,16 +1058,12 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
raise Http404(_(f"{name} does not exist: {product_uuid}"))
|
raise Http404(_(f"{name} does not exist: {product_uuid}"))
|
||||||
except OrderProduct.DoesNotExist:
|
except OrderProduct.DoesNotExist:
|
||||||
name = "OrderProduct"
|
name = "OrderProduct"
|
||||||
query = (
|
query = f"product: {product_uuid}, order: {self.uuid}, attributes: {attributes}"
|
||||||
f"product: {product_uuid}, order: {self.uuid}, attributes: {attributes}"
|
|
||||||
)
|
|
||||||
raise Http404(_(f"{name} does not exist with query <{query}>"))
|
raise Http404(_(f"{name} does not exist with query <{query}>"))
|
||||||
|
|
||||||
def remove_all_products(self):
|
def remove_all_products(self):
|
||||||
if self.status not in ["PENDING", "MOMENTAL"]:
|
if self.status not in ["PENDING", "MOMENTAL"]:
|
||||||
raise ValueError(
|
raise ValueError(_("you cannot remove products from an order that is not a pending one"))
|
||||||
_("you cannot remove products from an order that is not a pending one")
|
|
||||||
)
|
|
||||||
for order_product in self.order_products.all():
|
for order_product in self.order_products.all():
|
||||||
self.order_products.remove(order_product)
|
self.order_products.remove(order_product)
|
||||||
order_product.delete()
|
order_product.delete()
|
||||||
|
|
@ -1099,9 +1071,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
|
|
||||||
def remove_products_of_a_kind(self, product_uuid: str):
|
def remove_products_of_a_kind(self, product_uuid: str):
|
||||||
if self.status not in ["PENDING", "MOMENTAL"]:
|
if self.status not in ["PENDING", "MOMENTAL"]:
|
||||||
raise ValueError(
|
raise ValueError(_("you cannot remove products from an order that is not a pending one"))
|
||||||
_("you cannot remove products from an order that is not a pending one")
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
product = Product.objects.get(uuid=product_uuid)
|
product = Product.objects.get(uuid=product_uuid)
|
||||||
order_product = self.order_products.get(product=product, order=self)
|
order_product = self.order_products.get(product=product, order=self)
|
||||||
|
|
@ -1114,10 +1084,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_whole_digital(self):
|
def is_whole_digital(self):
|
||||||
return (
|
return self.order_products.count() == self.order_products.filter(product__is_digital=True).count()
|
||||||
self.order_products.count()
|
|
||||||
== self.order_products.filter(product__is_digital=True).count()
|
|
||||||
)
|
|
||||||
|
|
||||||
def apply_promocode(self, promocode_uuid: str):
|
def apply_promocode(self, promocode_uuid: str):
|
||||||
try:
|
try:
|
||||||
|
|
@ -1132,11 +1099,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
if self.is_whole_digital:
|
if self.is_whole_digital:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(_("you can only buy physical products with shipping address specified"))
|
||||||
_(
|
|
||||||
"you can only buy physical products with shipping address specified"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if billing_address_uuid and not shipping_address_uuid:
|
if billing_address_uuid and not shipping_address_uuid:
|
||||||
shipping_address = Address.objects.get(uuid=billing_address_uuid)
|
shipping_address = Address.objects.get(uuid=billing_address_uuid)
|
||||||
|
|
@ -1166,13 +1129,9 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
shipping_address: str | None = None,
|
shipping_address: str | None = None,
|
||||||
) -> Self | Transaction | None:
|
) -> Self | Transaction | None:
|
||||||
if config.DISABLED_COMMERCE:
|
if config.DISABLED_COMMERCE:
|
||||||
raise DisabledCommerceError(
|
raise DisabledCommerceError(_("you can not buy at this moment, please try again in a few minutes"))
|
||||||
_("you can not buy at this moment, please try again in a few minutes")
|
|
||||||
)
|
|
||||||
|
|
||||||
if (not force_balance and not force_payment) or (
|
if (not force_balance and not force_payment) or (force_balance and force_payment):
|
||||||
force_balance and force_payment
|
|
||||||
):
|
|
||||||
raise ValueError(_("invalid force value"))
|
raise ValueError(_("invalid force value"))
|
||||||
|
|
||||||
self.apply_addresses(billing_address, shipping_address)
|
self.apply_addresses(billing_address, shipping_address)
|
||||||
|
|
@ -1188,16 +1147,12 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
if force_payment:
|
if force_payment:
|
||||||
force = "payment"
|
force = "payment"
|
||||||
|
|
||||||
amount = (
|
amount = self.apply_promocode(promocode_uuid) if promocode_uuid else self.total_price
|
||||||
self.apply_promocode(promocode_uuid) if promocode_uuid else self.total_price
|
|
||||||
)
|
|
||||||
|
|
||||||
match force:
|
match force:
|
||||||
case "balance":
|
case "balance":
|
||||||
if self.user.payments_balance.amount < amount: # type: ignore
|
if self.user.payments_balance.amount < amount: # type: ignore
|
||||||
raise NotEnoughMoneyError(
|
raise NotEnoughMoneyError(_("insufficient funds to complete the order"))
|
||||||
_("insufficient funds to complete the order")
|
|
||||||
)
|
|
||||||
self.status = "CREATED"
|
self.status = "CREATED"
|
||||||
self.buy_time = timezone.now()
|
self.buy_time = timezone.now()
|
||||||
self.order_products.all().update(status="DELIVERING")
|
self.order_products.all().update(status="DELIVERING")
|
||||||
|
|
@ -1215,13 +1170,9 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def buy_without_registration(
|
def buy_without_registration(self, products: list, promocode_uuid: str, **kwargs) -> Transaction | None:
|
||||||
self, products: list, promocode_uuid: str, **kwargs
|
|
||||||
) -> Transaction | None:
|
|
||||||
if config.DISABLED_COMMERCE:
|
if config.DISABLED_COMMERCE:
|
||||||
raise DisabledCommerceError(
|
raise DisabledCommerceError(_("you can not buy at this moment, please try again in a few minutes"))
|
||||||
_("you can not buy at this moment, please try again in a few minutes")
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(products) < 1:
|
if len(products) < 1:
|
||||||
raise ValueError(_("you cannot purchase an empty order!"))
|
raise ValueError(_("you cannot purchase an empty order!"))
|
||||||
|
|
@ -1242,25 +1193,17 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
available_payment_methods = cache.get("payment_methods").get("payment_methods")
|
available_payment_methods = cache.get("payment_methods").get("payment_methods")
|
||||||
|
|
||||||
if payment_method not in available_payment_methods:
|
if payment_method not in available_payment_methods:
|
||||||
raise ValueError(
|
raise ValueError(_(f"invalid payment method: {payment_method} from {available_payment_methods}"))
|
||||||
_(
|
|
||||||
f"invalid payment method: {payment_method} from {available_payment_methods}"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
billing_customer_address_uuid = kwargs.get("billing_customer_address")
|
billing_customer_address_uuid = kwargs.get("billing_customer_address")
|
||||||
shipping_customer_address_uuid = kwargs.get("shipping_customer_address")
|
shipping_customer_address_uuid = kwargs.get("shipping_customer_address")
|
||||||
|
|
||||||
self.apply_addresses(
|
self.apply_addresses(billing_customer_address_uuid, shipping_customer_address_uuid)
|
||||||
billing_customer_address_uuid, shipping_customer_address_uuid
|
|
||||||
)
|
|
||||||
|
|
||||||
for product_uuid in products:
|
for product_uuid in products:
|
||||||
self.add_product(product_uuid)
|
self.add_product(product_uuid)
|
||||||
|
|
||||||
amount = (
|
amount = self.apply_promocode(promocode_uuid) if promocode_uuid else self.total_price
|
||||||
self.apply_promocode(promocode_uuid) if promocode_uuid else self.total_price
|
|
||||||
)
|
|
||||||
|
|
||||||
self.status = "CREATED"
|
self.status = "CREATED"
|
||||||
|
|
||||||
|
|
@ -1405,9 +1348,7 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel):
|
||||||
"errors": [
|
"errors": [
|
||||||
{
|
{
|
||||||
"detail": (
|
"detail": (
|
||||||
error
|
error if error else f"Something went wrong with {self.uuid} for some reason..."
|
||||||
if error
|
|
||||||
else f"Something went wrong with {self.uuid} for some reason..."
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
@ -1432,9 +1373,7 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel):
|
||||||
return self.download.url
|
return self.download.url
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def do_feedback(
|
def do_feedback(self, rating: int = 10, comment: str = "", action: str = "add") -> Optional["Feedback"]:
|
||||||
self, rating: int = 10, comment: str = "", action: str = "add"
|
|
||||||
) -> Optional["Feedback"]:
|
|
||||||
if action not in ["add", "remove"]:
|
if action not in ["add", "remove"]:
|
||||||
raise ValueError(_(f"wrong action specified for feedback: {action}"))
|
raise ValueError(_(f"wrong action specified for feedback: {action}"))
|
||||||
if action == "remove" and self.feedback:
|
if action == "remove" and self.feedback:
|
||||||
|
|
@ -1442,13 +1381,9 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel):
|
||||||
return None
|
return None
|
||||||
if action == "add" and not self.feedback:
|
if action == "add" and not self.feedback:
|
||||||
if self.order.status not in ["MOMENTAL", "PENDING"]: # type: ignore
|
if self.order.status not in ["MOMENTAL", "PENDING"]: # type: ignore
|
||||||
return Feedback.objects.create(
|
return Feedback.objects.create(rating=rating, comment=comment, order_product=self)
|
||||||
rating=rating, comment=comment, order_product=self
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(_("you cannot feedback an order which is not received"))
|
||||||
_("you cannot feedback an order which is not received")
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1468,11 +1403,11 @@ class DigitalAssetDownload(ExportModelOperationsMixin("attribute_group"), NiceMo
|
||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
if self.order_product.status != "FINISHED":
|
if self.order_product.status != "FINISHED":
|
||||||
raise ValueError(
|
raise ValueError(_("you can not download a digital asset for a non-finished order"))
|
||||||
_("you can not download a digital asset for a non-finished order")
|
|
||||||
)
|
|
||||||
|
|
||||||
return f"https://api.{config.BASE_DOMAIN}/download/{urlsafe_base64_encode(force_bytes(self.order_product.uuid))}"
|
return (
|
||||||
|
f"https://api.{config.BASE_DOMAIN}/download/{urlsafe_base64_encode(force_bytes(self.order_product.uuid))}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Feedback(ExportModelOperationsMixin("feedback"), NiceModel):
|
class Feedback(ExportModelOperationsMixin("feedback"), NiceModel):
|
||||||
|
|
@ -1489,9 +1424,7 @@ class Feedback(ExportModelOperationsMixin("feedback"), NiceModel):
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
blank=False,
|
blank=False,
|
||||||
null=False,
|
null=False,
|
||||||
help_text=_(
|
help_text=_("references the specific product in an order that this feedback is about"),
|
||||||
"references the specific product in an order that this feedback is about"
|
|
||||||
),
|
|
||||||
verbose_name=_("related order product"),
|
verbose_name=_("related order product"),
|
||||||
)
|
)
|
||||||
rating: float = FloatField( # type: ignore
|
rating: float = FloatField( # type: ignore
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ from core.views import (
|
||||||
)
|
)
|
||||||
from evibes.settings import SPECTACULAR_PLATFORM_SETTINGS
|
from evibes.settings import SPECTACULAR_PLATFORM_SETTINGS
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = (
|
||||||
|
[
|
||||||
path(r"health/", include("health_check.urls")),
|
path(r"health/", include("health_check.urls")),
|
||||||
path("prometheus/", include("django_prometheus.urls")),
|
path("prometheus/", include("django_prometheus.urls")),
|
||||||
path(
|
path(
|
||||||
|
|
@ -46,7 +47,10 @@ urlpatterns = [
|
||||||
path(r"auth/", include("vibes_auth.urls")),
|
path(r"auth/", include("vibes_auth.urls")),
|
||||||
path(r"payments/", include("payments.urls")),
|
path(r"payments/", include("payments.urls")),
|
||||||
path(r"blog/", include("blog.urls")),
|
path(r"blog/", include("blog.urls")),
|
||||||
] + i18n_patterns(path("admin/", admin.site.urls))
|
]
|
||||||
|
+ i18n_patterns(path("admin/", admin.site.urls))
|
||||||
|
+ i18n_patterns(path("admin/doc/", include("django.contrib.admindocs.urls")))
|
||||||
|
)
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ INSTALLED_APPS: list[str] = [
|
||||||
"jazzmin",
|
"jazzmin",
|
||||||
"modeltranslation",
|
"modeltranslation",
|
||||||
"django.contrib.admin",
|
"django.contrib.admin",
|
||||||
|
"django.contrib.admindocs",
|
||||||
"django.contrib.auth",
|
"django.contrib.auth",
|
||||||
"django.contrib.contenttypes",
|
"django.contrib.contenttypes",
|
||||||
"django.contrib.sessions",
|
"django.contrib.sessions",
|
||||||
|
|
|
||||||
|
|
@ -34,5 +34,5 @@ def evibes_summernote_upload_to_func(instance, filename: str) -> str:
|
||||||
filename = f"{uuid.uuid4()}.{ext}"
|
filename = f"{uuid.uuid4()}.{ext}"
|
||||||
today = datetime.now().strftime("%Y-%m-%d")
|
today = datetime.now().strftime("%Y-%m-%d")
|
||||||
if instance:
|
if instance:
|
||||||
return os.path.join('evibes-summernote', today, filename)
|
return os.path.join("evibes-summernote", today, filename)
|
||||||
return os.path.join('evibes-summernote', today)
|
return os.path.join("evibes-summernote", today)
|
||||||
|
|
|
||||||
|
|
@ -98,9 +98,7 @@ class UserSerializer(ModelSerializer):
|
||||||
"""
|
"""
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
return ProductSimpleSerializer(
|
return ProductSimpleSerializer(
|
||||||
instance=Product.objects.filter(
|
instance=Product.objects.filter(uuid__in=obj.recently_viewed, is_active=True),
|
||||||
uuid__in=obj.recently_viewed, is_active=True
|
|
||||||
),
|
|
||||||
many=True,
|
many=True,
|
||||||
).data
|
).data
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue