ob-dj-store 0.0.12.2__py3-none-any.whl → 0.0.12.3__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.
@@ -464,12 +464,14 @@ class CartItemSerializer(InventoryValidationMixin, serializers.ModelSerializer):
464
464
  image = serializers.SerializerMethodField()
465
465
  inventory_quantity = serializers.SerializerMethodField()
466
466
  is_uncountable = serializers.SerializerMethodField()
467
+ product_id = serializers.SerializerMethodField()
467
468
 
468
469
  class Meta:
469
470
  model = CartItem
470
471
  fields = (
471
472
  "id",
472
473
  "product_variant",
474
+ "product_id",
473
475
  "quantity",
474
476
  "store",
475
477
  "unit_price",
@@ -488,6 +490,9 @@ class CartItemSerializer(InventoryValidationMixin, serializers.ModelSerializer):
488
490
  },
489
491
  }
490
492
 
493
+ def get_product_id(self, obj):
494
+ return obj.product_variant.product.id
495
+
491
496
  def get_inventory_quantity(self, obj):
492
497
  if obj.inventory:
493
498
  return obj.inventory.quantity
@@ -980,7 +985,7 @@ def get_favorite_extras_models():
980
985
 
981
986
  class FavoriteExtraSerializer(serializers.ModelSerializer):
982
987
  content_object = GenericSerializer(read_only=True)
983
- object_id = serializers.IntegerField(min_value=1, write_only=True)
988
+ object_id = serializers.IntegerField(min_value=1)
984
989
  object_type = serializers.ChoiceField(
985
990
  write_only=True, choices=get_favorite_extras_models()
986
991
  )
@@ -1008,10 +1013,13 @@ class FavoriteExtraSerializer(serializers.ModelSerializer):
1008
1013
  class FavoriteSerializer(serializers.ModelSerializer):
1009
1014
  content_object = GenericSerializer(read_only=True)
1010
1015
  extras = FavoriteExtraSerializer(many=True)
1011
- object_id = serializers.IntegerField(min_value=1, write_only=True)
1016
+ object_id = serializers.IntegerField(min_value=1, required=False)
1012
1017
  object_type = serializers.ChoiceField(
1013
- write_only=True, choices=list(store_settings.FAVORITE_TYPES.keys())
1018
+ write_only=True,
1019
+ choices=list(store_settings.FAVORITE_TYPES.keys()),
1020
+ required=False,
1014
1021
  )
1022
+ is_available_in_store = serializers.SerializerMethodField()
1015
1023
 
1016
1024
  class Meta:
1017
1025
  model = Favorite
@@ -1022,11 +1030,27 @@ class FavoriteSerializer(serializers.ModelSerializer):
1022
1030
  "object_id",
1023
1031
  "object_type",
1024
1032
  "name",
1033
+ "is_available_in_store",
1025
1034
  )
1026
1035
  extra_kwargs = {
1027
1036
  "name": {"required": True},
1028
1037
  }
1029
1038
 
1039
+ def get_is_available_in_store(self, obj):
1040
+ store_id = self.context["request"].query_params.get("store")
1041
+ type = self.context["request"].query_params.get("type")
1042
+ if type == "Product" and store_id:
1043
+ content_type = ContentType.objects.get_for_model(ProductVariant)
1044
+ try:
1045
+ extra = obj.extras.get(content_type=content_type)
1046
+ inventory = extra.content_object.inventories.get(store=store_id)
1047
+ if inventory.is_uncountable:
1048
+ return True
1049
+ return inventory.quantity > 0
1050
+ except ObjectDoesNotExist:
1051
+ return False
1052
+ return None
1053
+
1030
1054
  def to_representation(self, instance):
1031
1055
  data = super().to_representation(instance)
1032
1056
  model_name = instance.content_type.model
@@ -1043,18 +1067,18 @@ class FavoriteSerializer(serializers.ModelSerializer):
1043
1067
  object_id=data["content_object"].id,
1044
1068
  user=self.context["request"].user,
1045
1069
  ).prefetch_related("extras")
1046
-
1047
- if not queryset.exists():
1048
- return
1049
-
1050
- for favorite in queryset:
1051
- content_objects = [
1052
- instance.content_object for instance in favorite.extras.all()
1053
- ]
1054
- if data["extras"] == content_objects:
1055
- raise serializers.ValidationError(
1056
- _(f"You cannot favorite the same item twice")
1057
- )
1070
+ if self.instance:
1071
+ queryset = queryset.exclude(pk=self.instance.pk)
1072
+
1073
+ if queryset.exists():
1074
+ for favorite in queryset:
1075
+ content_objects = [
1076
+ instance.content_object for instance in favorite.extras.all()
1077
+ ]
1078
+ if set(data["extras"]) == set(content_objects):
1079
+ raise serializers.ValidationError(
1080
+ _(f"You cannot favorite the same item twice")
1081
+ )
1058
1082
 
1059
1083
  def get_object(self, model: models.Model, id: int):
1060
1084
  try:
@@ -1068,14 +1092,22 @@ class FavoriteSerializer(serializers.ModelSerializer):
1068
1092
  def validate(self, attrs):
1069
1093
  validated_data = super().validate(attrs)
1070
1094
  extras_data = {}
1071
- name = validated_data["name"]
1072
- object_type = validated_data["object_type"]
1073
- object_type_model = import_string(
1074
- store_settings.FAVORITE_TYPES[object_type]["path"]
1075
- )
1076
- object_instance = get_object_or_404(
1077
- object_type_model, pk=validated_data["object_id"]
1078
- )
1095
+ if self.instance is None:
1096
+ object_type = validated_data["object_type"]
1097
+ object_type_model = import_string(
1098
+ store_settings.FAVORITE_TYPES[object_type]["path"]
1099
+ )
1100
+ object_instance = get_object_or_404(
1101
+ object_type_model, pk=validated_data["object_id"]
1102
+ )
1103
+ else:
1104
+ # when update
1105
+ model_name = self.instance.content_type.model
1106
+ for favorite in store_settings.FAVORITE_TYPES.keys():
1107
+ if model_name == favorite.lower():
1108
+ object_type = favorite
1109
+ object_instance = self.instance.content_object
1110
+
1079
1111
  for extra in validated_data["extras"]:
1080
1112
  if (
1081
1113
  extra["object_type"]
@@ -1111,7 +1143,7 @@ class FavoriteSerializer(serializers.ModelSerializer):
1111
1143
  validated_data = {
1112
1144
  "content_object": object_instance,
1113
1145
  "extras": extras,
1114
- "name": name,
1146
+ "name": validated_data["name"],
1115
1147
  }
1116
1148
  self._lookup_validation(validated_data)
1117
1149
  return validated_data
@@ -1128,6 +1160,16 @@ class FavoriteSerializer(serializers.ModelSerializer):
1128
1160
  raise serializers.ValidationError(detail=e.message_dict)
1129
1161
  return favorite
1130
1162
 
1163
+ def update(self, instance, validated_data):
1164
+ try:
1165
+ favorite = instance.update_favorite(
1166
+ validated_data["name"],
1167
+ validated_data["extras"],
1168
+ )
1169
+ except ValidationError as e:
1170
+ raise serializers.ValidationError(detail=e.message_dict)
1171
+ return favorite
1172
+
1131
1173
 
1132
1174
  class WalletMediaSerializer(serializers.ModelSerializer):
1133
1175
  class Meta:
@@ -23,7 +23,6 @@ from rest_framework_nested.viewsets import NestedViewSetMixin
23
23
  from config import settings as store_settings
24
24
  from ob_dj_store.apis.stores.filters import (
25
25
  CategoryFilter,
26
- FavoriteFilter,
27
26
  InventoryFilter,
28
27
  OrderFilter,
29
28
  PaymentMethodFilter,
@@ -861,6 +860,7 @@ class FavoriteViewSet(
861
860
  mixins.ListModelMixin,
862
861
  mixins.CreateModelMixin,
863
862
  mixins.DestroyModelMixin,
863
+ mixins.UpdateModelMixin,
864
864
  viewsets.GenericViewSet,
865
865
  ):
866
866
  serializer_class = FavoriteSerializer
@@ -868,11 +868,11 @@ class FavoriteViewSet(
868
868
  permissions.IsAuthenticated,
869
869
  ]
870
870
  queryset = Favorite.objects.all()
871
- filterset_class = FavoriteFilter
871
+ # filterset_class = FavoriteFilter
872
872
 
873
873
  def get_queryset(self):
874
874
  model = self.request.query_params.get("type")
875
- if self.action == "destroy":
875
+ if self.action in ["destroy", "update"]:
876
876
  return self.queryset.filter(user=self.request.user)
877
877
  if not model and model not in store_settings.FAVORITE_TYPES:
878
878
  raise ValidationError(_("You must provide the favorite type"))
@@ -894,7 +894,14 @@ class FavoriteViewSet(
894
894
  type=openapi.TYPE_STRING,
895
895
  enum=list(store_settings.FAVORITE_TYPES),
896
896
  required=True,
897
- )
897
+ ),
898
+ openapi.Parameter(
899
+ "store",
900
+ in_=openapi.IN_QUERY,
901
+ description="Store i of favorite products",
902
+ type=openapi.TYPE_INTEGER,
903
+ required=True,
904
+ ),
898
905
  ],
899
906
  tags=[
900
907
  "Favorite",
@@ -915,6 +922,18 @@ class FavoriteViewSet(
915
922
  def create(self, request, *args, **kwargs):
916
923
  return super().create(request, *args, **kwargs)
917
924
 
925
+ @swagger_auto_schema(
926
+ operation_summary="Update Item From Favorites",
927
+ operation_description="""
928
+ Update Item From Favorites
929
+ """,
930
+ tags=[
931
+ "Favorite",
932
+ ],
933
+ )
934
+ def update(self, request, *args, **kwargs):
935
+ return super().update(request, *args, **kwargs)
936
+
918
937
  @swagger_auto_schema(
919
938
  operation_summary="Remove Item From Favorites",
920
939
  operation_description="""
@@ -52,6 +52,21 @@ class Favorite(DjangoModelCleanMixin, models.Model):
52
52
  )
53
53
  return favorite
54
54
 
55
+ def update_favorite(self, name, extras=[]):
56
+ from ob_dj_store.core.stores.models._favorite import FavoriteExtra
57
+
58
+ self.name = name
59
+ self.save()
60
+ FavoriteExtra.objects.filter(favorite=self).delete()
61
+ for extra in extras:
62
+ extra_content_type = ContentType.objects.get_for_model(type(extra))
63
+ self.extras.create(
64
+ content_type=extra_content_type,
65
+ object_id=extra.id,
66
+ content_object=extra,
67
+ )
68
+ return self
69
+
55
70
 
56
71
  class FavoriteExtra(DjangoModelCleanMixin, models.Model):
57
72
  favorite = models.ForeignKey(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ob-dj-store
3
- Version: 0.0.12.2
3
+ Version: 0.0.12.3
4
4
  Summary: OBytes django application for managing ecommerce stores.
5
5
  Home-page: https://www.obytes.com/
6
6
  Author: OBytes
@@ -2,8 +2,8 @@ ob_dj_store/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
2
2
  ob_dj_store/apis/stores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  ob_dj_store/apis/stores/filters.py,sha256=18Sb8Id1mgCC0zAzTOQRfBaS7bkyD_sgM8_jAbf1ulE,6349
4
4
  ob_dj_store/apis/stores/urls.py,sha256=cPForgFpOgOGCUVAk6DZcZ7qOooMf1zpDIr1BA0L_8A,1593
5
- ob_dj_store/apis/stores/views.py,sha256=0MTOaEHAFR4nKKjOc_bdpo93sYHkp2JvkX7hRlK3GNs,31701
6
- ob_dj_store/apis/stores/rest/serializers/serializers.py,sha256=b3Gka1WflitjxN6Gp-8BD1gKlCouQDZtrZOt2crFd38,38966
5
+ ob_dj_store/apis/stores/views.py,sha256=GryrtvVY3W9EiVMTnQgTL1uXtzspB75GX6_qnrjM5S0,32301
6
+ ob_dj_store/apis/stores/rest/serializers/serializers.py,sha256=ozazsEKATnmMD2Oc9lx9oIn-DxNOX3mjeLKrpvsFtD8,40720
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
@@ -101,7 +101,7 @@ ob_dj_store/core/stores/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQe
101
101
  ob_dj_store/core/stores/models/__init__.py,sha256=fNB_sn6HM6EmTp_Z-Q7KXD8HDWVjG3qlayrWqvygvbw,1617
102
102
  ob_dj_store/core/stores/models/_address.py,sha256=qS5TQ9Z12zx_4CrrHvG8PoYVkdiOq_MtbKR14WKh3Hw,1661
103
103
  ob_dj_store/core/stores/models/_cart.py,sha256=qgjg5MXTMRIZRJJDx5BQ1pa9__ylfrnYMMRGbB2R53c,4555
104
- ob_dj_store/core/stores/models/_favorite.py,sha256=IA3p4u_-U0KcpofFMSkcuNWaI7C1hFkFdgMwQYYZGzw,2513
104
+ ob_dj_store/core/stores/models/_favorite.py,sha256=J29ECDsotIgduPpmUmieYTndymReWHkfdsZyQzz6A4g,3042
105
105
  ob_dj_store/core/stores/models/_feedback.py,sha256=eCUVgprNK5hSRKOS4M_pdR7QH2-rqhoYevlpykhCOLg,1472
106
106
  ob_dj_store/core/stores/models/_inventory.py,sha256=vAXSpCyUdYDIWgUEUUObQfhAcCcQO6j6zATrHf5dPuQ,3928
107
107
  ob_dj_store/core/stores/models/_order.py,sha256=lizkG-HEsxsC7Xasi5nnAtUnBL4riXezR48LblX-Zsk,8246
@@ -113,7 +113,7 @@ ob_dj_store/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
113
113
  ob_dj_store/utils/helpers.py,sha256=FtXXJOD2PILqZTyuf80bmf0KuWW64hxbJG6naJdxI5w,1607
114
114
  ob_dj_store/utils/model.py,sha256=DV7hOhTaZL3gh9sptts2jTUFlTArKG3i7oPioq9HLFE,303
115
115
  ob_dj_store/utils/utils.py,sha256=8UVAFB56qUSjJJ5f9vnermtw638gdFy4CFRCuMbns_M,1342
116
- ob_dj_store-0.0.12.2.dist-info/METADATA,sha256=ReVvSLpSZepJmFvkEIOo0tV9ZjtH9JoKpFvx3MDLg-Q,2827
117
- ob_dj_store-0.0.12.2.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
118
- ob_dj_store-0.0.12.2.dist-info/top_level.txt,sha256=CZG3G0ptTkzGnc0dFYN-ZD7YKdJBmm47bsmGwofD_lk,12
119
- ob_dj_store-0.0.12.2.dist-info/RECORD,,
116
+ ob_dj_store-0.0.12.3.dist-info/METADATA,sha256=_2kjr1NOwjQZVvrFct_JH1heumK1WJOv-6uBl6f0Jzs,2827
117
+ ob_dj_store-0.0.12.3.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
118
+ ob_dj_store-0.0.12.3.dist-info/top_level.txt,sha256=CZG3G0ptTkzGnc0dFYN-ZD7YKdJBmm47bsmGwofD_lk,12
119
+ ob_dj_store-0.0.12.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.38.4)
2
+ Generator: bdist_wheel (0.40.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5