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

1import uuid 

2from json import loads 

3 

4from rest_framework import serializers 

5 

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 

9 

10 

11class SpaceSerializer(serializers.ModelSerializer): 

12 exchange_account = serializers.CharField(source="exchange_account.uuid") 

13 delta = serializers.SerializerMethodField(read_only=True) 

14 

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 ] 

33 

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() 

41 

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 

53 

54 return NapseSpace.objects.create( 

55 name=validated_data["name"], 

56 description=validated_data["description"], 

57 exchange_account=exchange_account, 

58 ) 

59 

60 

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) 

67 

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 ] 

93 

94 def get_statistics(self, instance) -> dict: 

95 return instance.get_stats() 

96 

97 def get_history(self, instance) -> list: 

98 try: 

99 history = SpaceHistory.objects.get(owner=instance) 

100 except SpaceHistory.DoesNotExist: 

101 return [] 

102 

103 return loads(history.to_dataframe().to_json(orient="records")) 

104 

105 

106class SpaceMoneyFlowSerializer(serializers.Serializer): 

107 amount = serializers.FloatField(write_only=True, required=True) 

108 ticker = serializers.CharField(write_only=True, required=True) 

109 

110 def __init__(self, side, instance=None, data=serializers.empty, **kwargs): 

111 self.side = side 

112 super().__init__(instance=instance, data=data, **kwargs) 

113 

114 def _invest_validate(self, attrs): 

115 if not self.instance.testing: 

116 error_msg: str = "Not implemented yet." 

117 raise NotImplementedError(error_msg) 

118 

119 # Test invest 

120 return attrs 

121 

122 def _withdraw_validate(self, attrs): 

123 if self.instance.testing: 

124 error_msg: str = "Not implemented yet." 

125 raise NotImplementedError(error_msg) 

126 

127 # Test withdraw 

128 return attrs 

129 

130 def validate(self, attrs): 

131 if attrs.get("amount") <= 0: 

132 error_msg: str = "Invalid amount." 

133 raise serializers.ValidationError(error_msg) 

134 

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) 

138 

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) 

147 

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)