ob-dj-store 0.0.12.1__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
@@ -970,17 +975,17 @@ class GenericSerializer(serializers.Serializer):
970
975
  )
971
976
 
972
977
 
973
- class FavoriteExtraSerializer(serializers.ModelSerializer):
974
- def get_favorite_extras_models():
975
- extras_list = []
978
+ def get_favorite_extras_models():
979
+ extras_list = []
980
+ for key, value in settings.FAVORITE_TYPES.items():
981
+ if "extras" in value:
982
+ extras_list.extend(value["extras"].keys())
983
+ return extras_list
976
984
 
977
- for key, value in settings.FAVORITE_TYPES.items():
978
- if "extras" in value:
979
- extras_list.extend(value["extras"].keys())
980
- return extras_list
981
985
 
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
  )
@@ -994,14 +999,27 @@ class FavoriteExtraSerializer(serializers.ModelSerializer):
994
999
  "object_type",
995
1000
  )
996
1001
 
1002
+ def to_representation(self, instance):
1003
+ data = super().to_representation(instance)
1004
+ extras = get_favorite_extras_models()
1005
+ model_name = instance.content_type.model
1006
+ for extra in extras:
1007
+ if model_name == extra.lower():
1008
+ data["object_type"] = extra
1009
+ break
1010
+ return data
1011
+
997
1012
 
998
1013
  class FavoriteSerializer(serializers.ModelSerializer):
999
1014
  content_object = GenericSerializer(read_only=True)
1000
1015
  extras = FavoriteExtraSerializer(many=True)
1001
- object_id = serializers.IntegerField(min_value=1, write_only=True)
1016
+ object_id = serializers.IntegerField(min_value=1, required=False)
1002
1017
  object_type = serializers.ChoiceField(
1003
- 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,
1004
1021
  )
1022
+ is_available_in_store = serializers.SerializerMethodField()
1005
1023
 
1006
1024
  class Meta:
1007
1025
  model = Favorite
@@ -1012,11 +1030,36 @@ class FavoriteSerializer(serializers.ModelSerializer):
1012
1030
  "object_id",
1013
1031
  "object_type",
1014
1032
  "name",
1033
+ "is_available_in_store",
1015
1034
  )
1016
1035
  extra_kwargs = {
1017
1036
  "name": {"required": True},
1018
1037
  }
1019
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
+
1054
+ def to_representation(self, instance):
1055
+ data = super().to_representation(instance)
1056
+ model_name = instance.content_type.model
1057
+ for favorite in store_settings.FAVORITE_TYPES.keys():
1058
+ if model_name == favorite.lower():
1059
+ data["object_type"] = favorite
1060
+ break
1061
+ return data
1062
+
1020
1063
  def _lookup_validation(self, data):
1021
1064
  content_type = ContentType.objects.get_for_model(data["content_object"])
1022
1065
  queryset = Favorite.objects.filter(
@@ -1024,18 +1067,18 @@ class FavoriteSerializer(serializers.ModelSerializer):
1024
1067
  object_id=data["content_object"].id,
1025
1068
  user=self.context["request"].user,
1026
1069
  ).prefetch_related("extras")
1027
-
1028
- if not queryset.exists():
1029
- return
1030
-
1031
- for favorite in queryset:
1032
- content_objects = [
1033
- instance.content_object for instance in favorite.extras.all()
1034
- ]
1035
- if data["extras"] == content_objects:
1036
- raise serializers.ValidationError(
1037
- _(f"You cannot favorite the same item twice")
1038
- )
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
+ )
1039
1082
 
1040
1083
  def get_object(self, model: models.Model, id: int):
1041
1084
  try:
@@ -1049,14 +1092,22 @@ class FavoriteSerializer(serializers.ModelSerializer):
1049
1092
  def validate(self, attrs):
1050
1093
  validated_data = super().validate(attrs)
1051
1094
  extras_data = {}
1052
- name = validated_data["name"]
1053
- object_type = validated_data["object_type"]
1054
- object_type_model = import_string(
1055
- store_settings.FAVORITE_TYPES[object_type]["path"]
1056
- )
1057
- object_instance = get_object_or_404(
1058
- object_type_model, pk=validated_data["object_id"]
1059
- )
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
+
1060
1111
  for extra in validated_data["extras"]:
1061
1112
  if (
1062
1113
  extra["object_type"]
@@ -1092,7 +1143,7 @@ class FavoriteSerializer(serializers.ModelSerializer):
1092
1143
  validated_data = {
1093
1144
  "content_object": object_instance,
1094
1145
  "extras": extras,
1095
- "name": name,
1146
+ "name": validated_data["name"],
1096
1147
  }
1097
1148
  self._lookup_validation(validated_data)
1098
1149
  return validated_data
@@ -1109,6 +1160,16 @@ class FavoriteSerializer(serializers.ModelSerializer):
1109
1160
  raise serializers.ValidationError(detail=e.message_dict)
1110
1161
  return favorite
1111
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
+
1112
1173
 
1113
1174
  class WalletMediaSerializer(serializers.ModelSerializer):
1114
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.1
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=YUnGJeEg63hB2jIag9CqN5xBkRC9n093wTvVv2n_42g,38299
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.1.dist-info/METADATA,sha256=t2LJ9I_9WBYY2LmP438sKFBdIuL_QCzr1CGRKwmJ9nM,2827
117
- ob_dj_store-0.0.12.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
118
- ob_dj_store-0.0.12.1.dist-info/top_level.txt,sha256=CZG3G0ptTkzGnc0dFYN-ZD7YKdJBmm47bsmGwofD_lk,12
119
- ob_dj_store-0.0.12.1.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