ob-dj-store 0.0.21__py3-none-any.whl → 0.0.21.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ob_dj_store/apis/stores/filters.py +12 -0
- ob_dj_store/apis/stores/rest/serializers/serializers.py +38 -0
- ob_dj_store/apis/stores/urls.py +2 -0
- ob_dj_store/apis/stores/views.py +47 -6
- ob_dj_store/core/stores/migrations/0109_wallettransaction_cashback_type.py +27 -0
- ob_dj_store/core/stores/models/_product.py +13 -0
- ob_dj_store/core/stores/models/_wallet.py +8 -1
- {ob_dj_store-0.0.21.dist-info → ob_dj_store-0.0.21.2.dist-info}/METADATA +1 -1
- {ob_dj_store-0.0.21.dist-info → ob_dj_store-0.0.21.2.dist-info}/RECORD +11 -10
- {ob_dj_store-0.0.21.dist-info → ob_dj_store-0.0.21.2.dist-info}/WHEEL +0 -0
- {ob_dj_store-0.0.21.dist-info → ob_dj_store-0.0.21.2.dist-info}/top_level.txt +0 -0
@@ -87,6 +87,7 @@ class ProductFilter(filters.FilterSet):
|
|
87
87
|
"""Product filters"""
|
88
88
|
|
89
89
|
category = filters.CharFilter(method="by_category")
|
90
|
+
q = filters.CharFilter(method="filter_search")
|
90
91
|
|
91
92
|
class Meta:
|
92
93
|
model = Product
|
@@ -99,6 +100,17 @@ class ProductFilter(filters.FilterSet):
|
|
99
100
|
def by_category(self, queryset, name, value):
|
100
101
|
return queryset.filter(category__name__iexact=value)
|
101
102
|
|
103
|
+
def filter_search(self, queryset, name, value):
|
104
|
+
language = self.request.META.get("HTTP_LANGUAGE", "").strip().upper()
|
105
|
+
if language == "AR":
|
106
|
+
query = Q(name_arabic__icontains=value) | Q(
|
107
|
+
description_arabic__icontains=value
|
108
|
+
)
|
109
|
+
else:
|
110
|
+
query = Q(name__icontains=value) | Q(description__icontains=value)
|
111
|
+
qs = queryset.filter(query).distinct()[:5]
|
112
|
+
return qs
|
113
|
+
|
102
114
|
|
103
115
|
class VariantFilter(filters.FilterSet):
|
104
116
|
"""Variant filters"""
|
@@ -947,6 +947,44 @@ class ProductSerializer(ArabicFieldsMixin, FavoriteMixin, serializers.ModelSeria
|
|
947
947
|
return data
|
948
948
|
|
949
949
|
|
950
|
+
class ProductSearchSerializer(
|
951
|
+
ArabicFieldsMixin, FavoriteMixin, serializers.ModelSerializer
|
952
|
+
):
|
953
|
+
is_snoozed = serializers.SerializerMethodField()
|
954
|
+
is_available = serializers.SerializerMethodField()
|
955
|
+
|
956
|
+
class Meta:
|
957
|
+
model = Product
|
958
|
+
fields = (
|
959
|
+
"id",
|
960
|
+
"name",
|
961
|
+
"name_arabic",
|
962
|
+
"slug",
|
963
|
+
"description",
|
964
|
+
"description_arabic",
|
965
|
+
"is_snoozed",
|
966
|
+
"is_available",
|
967
|
+
)
|
968
|
+
|
969
|
+
def get_store_id(self):
|
970
|
+
return self.context["request"].query_params.get("store")
|
971
|
+
|
972
|
+
def get_inventory_for_store(self, store_id):
|
973
|
+
if hasattr(self, "get_inventory"):
|
974
|
+
return self.get_inventory(store_id)
|
975
|
+
return None
|
976
|
+
|
977
|
+
def get_is_snoozed(self, obj):
|
978
|
+
store_id = self.get_store_id()
|
979
|
+
inventory = self.get_inventory_for_store(store_id)
|
980
|
+
return obj.is_snoozed(store_id=store_id) if inventory else False
|
981
|
+
|
982
|
+
def get_is_available(self, obj):
|
983
|
+
store_id = self.get_store_id()
|
984
|
+
inventory = self.get_inventory_for_store(store_id)
|
985
|
+
return bool(inventory and inventory.quantity)
|
986
|
+
|
987
|
+
|
950
988
|
class ProductListSerializer(ArabicFieldsMixin, serializers.ModelSerializer):
|
951
989
|
product_images = ProductMediaSerializer(many=True, source="images")
|
952
990
|
|
ob_dj_store/apis/stores/urls.py
CHANGED
@@ -20,6 +20,7 @@ from ob_dj_store.apis.stores.views import (
|
|
20
20
|
TaxViewSet,
|
21
21
|
TransactionsViewSet,
|
22
22
|
VariantView,
|
23
|
+
WalletV2ViewSet,
|
23
24
|
WalletViewSet,
|
24
25
|
)
|
25
26
|
|
@@ -43,6 +44,7 @@ router.register(r"cart", CartView, basename="cart")
|
|
43
44
|
router.register(r"cart-item", CartItemView, basename="cart-item")
|
44
45
|
router.register(r"favorite", FavoriteViewSet, basename="favorite")
|
45
46
|
router.register(r"wallet", WalletViewSet, basename="wallet")
|
47
|
+
router.register(r"wallet_v2", WalletV2ViewSet, basename="wallet_v2")
|
46
48
|
router.register(r"payment-method", PaymentMethodViewSet, basename="payment-method")
|
47
49
|
router.register(r"order", ReorderViewSet, basename="re-order")
|
48
50
|
router.register(r"partner/auth", PartnerAuthInfoViewSet, basename="auth")
|
ob_dj_store/apis/stores/views.py
CHANGED
@@ -51,6 +51,7 @@ from ob_dj_store.apis.stores.rest.serializers.serializers import (
|
|
51
51
|
PaymentMethodSerializer,
|
52
52
|
PaymentSerializer,
|
53
53
|
ProductListSerializer,
|
54
|
+
ProductSearchSerializer,
|
54
55
|
ProductSerializer,
|
55
56
|
ProductVariantSerializer,
|
56
57
|
ReorderSerializer,
|
@@ -61,6 +62,7 @@ from ob_dj_store.apis.stores.rest.serializers.serializers import (
|
|
61
62
|
WalletSerializer,
|
62
63
|
WalletTopUpSerializer,
|
63
64
|
WalletTransactionListSerializer,
|
65
|
+
WalletTransactionSerializer,
|
64
66
|
)
|
65
67
|
from ob_dj_store.core.stores.gateway.tap.utils import TapException
|
66
68
|
from ob_dj_store.core.stores.models import (
|
@@ -575,6 +577,11 @@ class ProductView(
|
|
575
577
|
filterset_class = ProductFilter
|
576
578
|
queryset = Product.objects.active()
|
577
579
|
|
580
|
+
def get_serializer_class(self):
|
581
|
+
if self.request.query_params.get("q"):
|
582
|
+
return ProductSearchSerializer
|
583
|
+
return ProductSerializer
|
584
|
+
|
578
585
|
def apply_prefetch(self, queryset):
|
579
586
|
|
580
587
|
qs = queryset.prefetch_related(
|
@@ -1103,13 +1110,19 @@ class WalletViewSet(
|
|
1103
1110
|
methods=["GET"],
|
1104
1111
|
detail=True,
|
1105
1112
|
url_path="transactions",
|
1106
|
-
serializer_class=
|
1113
|
+
serializer_class=WalletTransactionSerializer,
|
1107
1114
|
)
|
1108
|
-
def transactions(
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1115
|
+
def transactions(
|
1116
|
+
self, request: Request, *args: typing.Any, **kwargs: typing.Any
|
1117
|
+
) -> Response:
|
1118
|
+
queryset = self.get_object().transactions.all().order_by("-created_at")
|
1119
|
+
page = self.paginate_queryset(queryset)
|
1120
|
+
if page is not None:
|
1121
|
+
serializer = self.get_serializer(page, many=True)
|
1122
|
+
return self.get_paginated_response(serializer.data)
|
1123
|
+
|
1124
|
+
serializer = self.get_serializer(queryset, many=True)
|
1125
|
+
return Response(serializer.data)
|
1113
1126
|
|
1114
1127
|
@swagger_auto_schema(
|
1115
1128
|
operation_summary="List Wallet selection images",
|
@@ -1137,6 +1150,34 @@ class WalletViewSet(
|
|
1137
1150
|
return Response(serializer.data)
|
1138
1151
|
|
1139
1152
|
|
1153
|
+
class WalletV2ViewSet(
|
1154
|
+
mixins.ListModelMixin, viewsets.GenericViewSet,
|
1155
|
+
):
|
1156
|
+
def get_queryset(self):
|
1157
|
+
return Wallet.objects.filter(
|
1158
|
+
user=self.request.user, is_active=True
|
1159
|
+
).select_related("media_image")
|
1160
|
+
|
1161
|
+
@swagger_auto_schema(
|
1162
|
+
operation_summary="List Wallet's transactions",
|
1163
|
+
operation_description="""
|
1164
|
+
list user's wallet transactions(debit,credit)
|
1165
|
+
""",
|
1166
|
+
tags=["Wallet",],
|
1167
|
+
)
|
1168
|
+
@action(
|
1169
|
+
methods=["GET"],
|
1170
|
+
detail=True,
|
1171
|
+
url_path="transactions",
|
1172
|
+
serializer_class=WalletTransactionListSerializer,
|
1173
|
+
)
|
1174
|
+
def transactions(self, request, *args, **kwargs):
|
1175
|
+
wallet = self.get_object()
|
1176
|
+
queryset = wallet.transactions.all().order_by("-created_at")
|
1177
|
+
serializer = WalletTransactionListSerializer(queryset, many=True)
|
1178
|
+
return Response({"results": serializer.data})
|
1179
|
+
|
1180
|
+
|
1140
1181
|
class PartnerAuthInfoViewSet(
|
1141
1182
|
mixins.CreateModelMixin,
|
1142
1183
|
mixins.RetrieveModelMixin,
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Generated by Django 3.2.8 on 2025-07-31 16:12
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
|
8
|
+
dependencies = [
|
9
|
+
("stores", "0108_alter_paymentmethod_payment_provider"),
|
10
|
+
]
|
11
|
+
|
12
|
+
operations = [
|
13
|
+
migrations.AddField(
|
14
|
+
model_name="wallettransaction",
|
15
|
+
name="cashback_type",
|
16
|
+
field=models.CharField(
|
17
|
+
blank=True,
|
18
|
+
choices=[
|
19
|
+
("BY_ORDER", "By Order"),
|
20
|
+
("BY_OFFER", "By Offer"),
|
21
|
+
("BY_STREAK", "By Streak"),
|
22
|
+
],
|
23
|
+
max_length=100,
|
24
|
+
null=True,
|
25
|
+
),
|
26
|
+
),
|
27
|
+
]
|
@@ -248,6 +248,19 @@ class Product(DjangoModelCleanMixin, models.Model):
|
|
248
248
|
def __str__(self):
|
249
249
|
return f"Product {self.name} (PK={self.pk})"
|
250
250
|
|
251
|
+
def get_inventory(self, store_id):
|
252
|
+
try:
|
253
|
+
inventory = self.product_variants.inventories.get(store=store_id)
|
254
|
+
except ObjectDoesNotExist:
|
255
|
+
return None
|
256
|
+
|
257
|
+
def is_snoozed(self, store_id):
|
258
|
+
try:
|
259
|
+
inventory = self.product_variants.inventories.get(store=store_id)
|
260
|
+
except ObjectDoesNotExist:
|
261
|
+
return False
|
262
|
+
return inventory.is_snoozed
|
263
|
+
|
251
264
|
|
252
265
|
# TODO: must remove, redundunt
|
253
266
|
class Attribute(DjangoModelCleanMixin, models.Model):
|
@@ -136,6 +136,11 @@ class WalletTransaction(models.Model):
|
|
136
136
|
CREDIT = "CREDIT", _("credit")
|
137
137
|
DEBIT = "DEBIT", _("debit")
|
138
138
|
|
139
|
+
class CashBackType(models.TextChoices):
|
140
|
+
BY_ORDER = "BY_ORDER", _("By Order")
|
141
|
+
BY_OFFER = "BY_OFFER", _("By Offer")
|
142
|
+
BY_STREAK = "BY_STREAK", _("By Streak")
|
143
|
+
|
139
144
|
wallet = models.ForeignKey(
|
140
145
|
"stores.Wallet", on_delete=models.CASCADE, related_name="transactions",
|
141
146
|
)
|
@@ -150,7 +155,9 @@ class WalletTransaction(models.Model):
|
|
150
155
|
is_cashback = models.BooleanField(default=False)
|
151
156
|
is_refund = models.BooleanField(default=False)
|
152
157
|
is_redeemed = models.BooleanField(default=False)
|
153
|
-
|
158
|
+
cashback_type = models.CharField(
|
159
|
+
max_length=100, choices=CashBackType.choices, blank=True, null=True
|
160
|
+
)
|
154
161
|
objects = WalletTransactionManager()
|
155
162
|
|
156
163
|
# Audit
|
@@ -1,9 +1,9 @@
|
|
1
1
|
ob_dj_store/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
ob_dj_store/apis/stores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
ob_dj_store/apis/stores/filters.py,sha256=
|
4
|
-
ob_dj_store/apis/stores/urls.py,sha256=
|
5
|
-
ob_dj_store/apis/stores/views.py,sha256=
|
6
|
-
ob_dj_store/apis/stores/rest/serializers/serializers.py,sha256=
|
3
|
+
ob_dj_store/apis/stores/filters.py,sha256=cJ7OnNLFT1N5lp3IXFUpGMgqm-jhS24g-Y8pZmEMe58,10260
|
4
|
+
ob_dj_store/apis/stores/urls.py,sha256=W9sNJ7ST9pGnfVCf7GmduDO-_zK9MGTI6ybV8n-lzSc,2111
|
5
|
+
ob_dj_store/apis/stores/views.py,sha256=cwDFNY2rtTfjl_F9PpR5zOJy2DPmGidOjIlJ9fsgSYI,42744
|
6
|
+
ob_dj_store/apis/stores/rest/serializers/serializers.py,sha256=GUsUTN4MTXq92Uriv6Ql9MzjZJsSbmFDC3lZhSmB7vE,68219
|
7
7
|
ob_dj_store/apis/tap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
ob_dj_store/apis/tap/serializers.py,sha256=KPrBK4h2-fWvEVf6vOj2ww5-USV9WqpyYicIqoHIiXI,1065
|
9
9
|
ob_dj_store/apis/tap/urls.py,sha256=bnOTv6an11kxpo_FdqlhsizlGPLVpNxBjCyKcf3_C9M,367
|
@@ -142,6 +142,7 @@ ob_dj_store/core/stores/migrations/0105_store_is_open_after_midnight.py,sha256=8
|
|
142
142
|
ob_dj_store/core/stores/migrations/0106_alter_paymentmethod_payment_provider.py,sha256=BDDfVs0fMifUnSlZ4zIct78F6PvfP5gyrVFyifrCvE4,1092
|
143
143
|
ob_dj_store/core/stores/migrations/0107_auto_20250425_2059.py,sha256=XCj2Inlw8e-_6W9wvYeVVV-bGk6lX8_n2FNI5W80XVw,848
|
144
144
|
ob_dj_store/core/stores/migrations/0108_alter_paymentmethod_payment_provider.py,sha256=abuqKAhuha8tEdxJy-Tj1RNFOMV63_z5v_qK5LLSNVI,1078
|
145
|
+
ob_dj_store/core/stores/migrations/0109_wallettransaction_cashback_type.py,sha256=XA_RtxLjnpsz-i0uKlCyYK-UWL4RR10Q_XeqVd3KX6A,691
|
145
146
|
ob_dj_store/core/stores/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
146
147
|
ob_dj_store/core/stores/models/__init__.py,sha256=VeWrDiIbw94ZDSFD-62rz9iTTW87iPdwDW5jcjxm7bs,2045
|
147
148
|
ob_dj_store/core/stores/models/_address.py,sha256=uf9W4dnlXkEFhhsK75ZsDwWq5R2JEngf7VhBiLEnIVs,2193
|
@@ -152,14 +153,14 @@ ob_dj_store/core/stores/models/_inventory.py,sha256=_rGlVL5HjOlHQVB8CI0776CPcE5r
|
|
152
153
|
ob_dj_store/core/stores/models/_order.py,sha256=_08lqX5p4brCdUilqfbT--6Ao2TMsqnzXaWoV_7IYL8,9758
|
153
154
|
ob_dj_store/core/stores/models/_partner.py,sha256=OuYvevUWn1sYHs9PcFf51EUUC1uqytQss8Bx91aMOH8,4732
|
154
155
|
ob_dj_store/core/stores/models/_payment.py,sha256=FTV-NmvQjxwwR5C5X7qYWV-ZUIZfqMMEjkBNaS-drLs,6421
|
155
|
-
ob_dj_store/core/stores/models/_product.py,sha256=
|
156
|
+
ob_dj_store/core/stores/models/_product.py,sha256=iBSXZcZdtCXFINiOFqbnaZot9rWPkFdzySXwKJO5h6I,18239
|
156
157
|
ob_dj_store/core/stores/models/_store.py,sha256=0K-CNJWuXNqeyULL1J0M9hiNcVla0UNNjdCdN_nzNEE,9833
|
157
|
-
ob_dj_store/core/stores/models/_wallet.py,sha256=
|
158
|
+
ob_dj_store/core/stores/models/_wallet.py,sha256=YvT-rvED-jrYjePLJpvdLXXoBudR6TGPu5cNE0m2fWo,5643
|
158
159
|
ob_dj_store/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
159
160
|
ob_dj_store/utils/helpers.py,sha256=o7wgypM7mI2vZqZKkhxnTcnHJC8GMQDOuYMnRwXr6tY,2058
|
160
161
|
ob_dj_store/utils/model.py,sha256=DV7hOhTaZL3gh9sptts2jTUFlTArKG3i7oPioq9HLFE,303
|
161
162
|
ob_dj_store/utils/utils.py,sha256=8UVAFB56qUSjJJ5f9vnermtw638gdFy4CFRCuMbns_M,1342
|
162
|
-
ob_dj_store-0.0.21.dist-info/METADATA,sha256=
|
163
|
-
ob_dj_store-0.0.21.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
164
|
-
ob_dj_store-0.0.21.dist-info/top_level.txt,sha256=CZG3G0ptTkzGnc0dFYN-ZD7YKdJBmm47bsmGwofD_lk,12
|
165
|
-
ob_dj_store-0.0.21.dist-info/RECORD,,
|
163
|
+
ob_dj_store-0.0.21.2.dist-info/METADATA,sha256=3N8bQGyJNEAIPzgZDu-MpfFdHHNPmEo3Uv4pTjgtK84,2850
|
164
|
+
ob_dj_store-0.0.21.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
165
|
+
ob_dj_store-0.0.21.2.dist-info/top_level.txt,sha256=CZG3G0ptTkzGnc0dFYN-ZD7YKdJBmm47bsmGwofD_lk,12
|
166
|
+
ob_dj_store-0.0.21.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|