Coverage for django_napse/api/spaces/serializers/space_serializers.py: 42%
84 statements
« prev ^ index » next coverage.py v7.4.3, created at 2024-03-12 13:49 +0000
« prev ^ index » next coverage.py v7.4.3, created at 2024-03-12 13:49 +0000
1import uuid
2from json import loads
4from rest_framework import serializers
6from django_napse.api.fleets.serializers import FleetSerializer
7from django_napse.api.wallets.serializers.wallet_serializers import WalletSerializer
8from django_napse.core.models import ExchangeAccount, NapseSpace, SpaceHistory
11class SpaceSerializer(serializers.ModelSerializer):
12 exchange_account = serializers.CharField(source="exchange_account.uuid")
13 delta = serializers.SerializerMethodField(read_only=True)
15 class Meta:
16 model = NapseSpace
17 fields = [
18 "name",
19 "description",
20 "exchange_account",
21 # read-only
22 "uuid",
23 "testing",
24 "value",
25 "delta",
26 ]
27 read_only_fields = [
28 "uuid",
29 "testing",
30 "value",
31 "delta",
32 ]
34 def get_delta(self, instance) -> float:
35 """Delta on the last 30 days."""
36 try:
37 history = SpaceHistory.objects.get(owner=instance)
38 except SpaceHistory.DoesNotExist:
39 return 0
40 return history.get_delta()
42 def create(self, validated_data):
43 try:
44 uuid.UUID(str(validated_data["exchange_account"]["uuid"]))
45 except ValueError:
46 error_msg: str = "Invalid UUID"
47 raise serializers.ValidationError(error_msg) from None
48 try:
49 exchange_account = ExchangeAccount.objects.get(uuid=validated_data["exchange_account"]["uuid"])
50 except ExchangeAccount.DoesNotExist:
51 error_msg: str = "Exchange Account does not exist"
52 raise serializers.ValidationError(error_msg) from None
54 return NapseSpace.objects.create(
55 name=validated_data["name"],
56 description=validated_data["description"],
57 exchange_account=exchange_account,
58 )
61class SpaceDetailSerializer(serializers.ModelSerializer):
62 fleets = FleetSerializer(many=True, read_only=True)
63 exchange_account = serializers.CharField(source="exchange_account.uuid", read_only=True)
64 statistics = serializers.SerializerMethodField(read_only=True)
65 wallet = WalletSerializer(read_only=True)
66 history = serializers.SerializerMethodField(read_only=True)
68 class Meta:
69 model = NapseSpace
70 fields = [
71 "name",
72 "description",
73 # read-only
74 "uuid",
75 "testing",
76 "exchange_account",
77 "created_at",
78 "statistics",
79 "wallet",
80 "history",
81 "fleets",
82 ]
83 read_only_fields = [
84 "uuid",
85 "testing",
86 "exchange_account",
87 "created_at",
88 "statistics",
89 "wallet",
90 "history",
91 "fleet",
92 ]
94 def get_statistics(self, instance) -> dict:
95 return instance.get_stats()
97 def get_history(self, instance) -> list:
98 try:
99 history = SpaceHistory.objects.get(owner=instance)
100 except SpaceHistory.DoesNotExist:
101 return []
103 return loads(history.to_dataframe().to_json(orient="records"))
106class SpaceMoneyFlowSerializer(serializers.Serializer):
107 amount = serializers.FloatField(write_only=True, required=True)
108 ticker = serializers.CharField(write_only=True, required=True)
110 def __init__(self, side, instance=None, data=serializers.empty, **kwargs):
111 self.side = side
112 super().__init__(instance=instance, data=data, **kwargs)
114 def _invest_validate(self, attrs):
115 if not self.instance.testing:
116 error_msg: str = "Not implemented yet."
117 raise NotImplementedError(error_msg)
119 # Test invest
120 return attrs
122 def _withdraw_validate(self, attrs):
123 if self.instance.testing:
124 error_msg: str = "Not implemented yet."
125 raise NotImplementedError(error_msg)
127 # Test withdraw
128 return attrs
130 def validate(self, attrs):
131 if attrs.get("amount") <= 0:
132 error_msg: str = "Invalid amount."
133 raise serializers.ValidationError(error_msg)
135 if attrs.get("ticker") not in self.instance.exchange_account.get_tickers():
136 error_msg: str = f"{attrs['ticker']} is not available on {self.instance.exchange_account.exchange.name} exchange."
137 raise serializers.ValidationError(error_msg)
139 match self.side.upper():
140 case "INVEST":
141 return self._invest_validate(attrs)
142 case "WITHDRAW":
143 return self._withdraw_validate(attrs)
144 case _:
145 error_msg: str = "Invalid side."
146 raise ValueError(error_msg)
148 def save(self, **kwargs):
149 if self.side.upper() == "INVEST":
150 self.instance.invest(
151 self.validated_data.get("amount"),
152 self.validated_data.get("ticker"),
153 )
154 else:
155 self.instance.withdraw(self.amount, self.ticker)