wbportfolio 1.52.1__py2.py3-none-any.whl → 1.52.2rc0__py2.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.

Potentially problematic release.


This version of wbportfolio might be problematic. Click here for more details.

Files changed (82) hide show
  1. wbportfolio/admin/__init__.py +1 -1
  2. wbportfolio/admin/transactions/__init__.py +0 -1
  3. wbportfolio/admin/transactions/dividends.py +40 -4
  4. wbportfolio/admin/transactions/fees.py +24 -14
  5. wbportfolio/admin/transactions/trades.py +34 -12
  6. wbportfolio/defaults/fees/default.py +7 -15
  7. wbportfolio/factories/__init__.py +0 -1
  8. wbportfolio/factories/dividends.py +8 -3
  9. wbportfolio/factories/fees.py +8 -4
  10. wbportfolio/factories/trades.py +10 -3
  11. wbportfolio/filters/transactions/__init__.py +1 -2
  12. wbportfolio/filters/transactions/fees.py +5 -10
  13. wbportfolio/filters/transactions/trades.py +17 -8
  14. wbportfolio/filters/transactions/utils.py +42 -0
  15. wbportfolio/import_export/handlers/dividend.py +7 -7
  16. wbportfolio/import_export/handlers/fees.py +11 -21
  17. wbportfolio/import_export/handlers/trade.py +5 -7
  18. wbportfolio/import_export/parsers/jpmorgan/fees.py +2 -2
  19. wbportfolio/import_export/parsers/leonteq/customer_trade.py +5 -5
  20. wbportfolio/import_export/parsers/leonteq/fees.py +11 -7
  21. wbportfolio/import_export/parsers/leonteq/trade.py +0 -5
  22. wbportfolio/import_export/parsers/natixis/d1_fees.py +2 -2
  23. wbportfolio/import_export/parsers/natixis/dividend.py +4 -9
  24. wbportfolio/import_export/parsers/natixis/fees.py +7 -9
  25. wbportfolio/import_export/parsers/sg_lux/customer_trade_pending_slk.py +1 -1
  26. wbportfolio/import_export/parsers/sg_lux/fees.py +2 -2
  27. wbportfolio/import_export/parsers/sg_lux/perf_fees.py +2 -2
  28. wbportfolio/import_export/parsers/sg_lux/utils.py +2 -2
  29. wbportfolio/import_export/parsers/ubs/api/fees.py +2 -2
  30. wbportfolio/import_export/parsers/vontobel/customer_trade.py +2 -3
  31. wbportfolio/import_export/parsers/vontobel/historical_customer_trade.py +0 -1
  32. wbportfolio/import_export/parsers/vontobel/management_fees.py +7 -7
  33. wbportfolio/import_export/parsers/vontobel/performance_fees.py +3 -3
  34. wbportfolio/jinja2/wbportfolio/sql/aum_nnm.sql +2 -2
  35. wbportfolio/migrations/0059_fees_unique_fees.py +1 -1
  36. wbportfolio/migrations/0077_remove_transaction_currency_and_more.py +622 -0
  37. wbportfolio/models/mixins/liquidity_stress_test.py +3 -3
  38. wbportfolio/models/transactions/__init__.py +0 -2
  39. wbportfolio/models/transactions/claim.py +1 -1
  40. wbportfolio/models/transactions/dividends.py +41 -5
  41. wbportfolio/models/transactions/fees.py +55 -22
  42. wbportfolio/models/transactions/trade_proposals.py +25 -3
  43. wbportfolio/models/transactions/trades.py +111 -50
  44. wbportfolio/models/transactions/transactions.py +60 -156
  45. wbportfolio/serializers/signals.py +15 -10
  46. wbportfolio/serializers/transactions/__init__.py +0 -5
  47. wbportfolio/serializers/transactions/dividends.py +37 -9
  48. wbportfolio/serializers/transactions/fees.py +39 -10
  49. wbportfolio/serializers/transactions/trades.py +56 -16
  50. wbportfolio/tasks.py +2 -2
  51. wbportfolio/tests/conftest.py +2 -8
  52. wbportfolio/tests/models/test_imports.py +2 -7
  53. wbportfolio/tests/models/transactions/test_fees.py +7 -13
  54. wbportfolio/tests/models/transactions/test_trade_proposals.py +4 -2
  55. wbportfolio/urls.py +3 -6
  56. wbportfolio/viewsets/configs/buttons/mixins.py +2 -2
  57. wbportfolio/viewsets/configs/display/__init__.py +2 -3
  58. wbportfolio/viewsets/configs/display/fees.py +3 -3
  59. wbportfolio/viewsets/configs/endpoints/__init__.py +3 -4
  60. wbportfolio/viewsets/configs/endpoints/fees.py +2 -2
  61. wbportfolio/viewsets/configs/menu/__init__.py +0 -1
  62. wbportfolio/viewsets/configs/titles/__init__.py +2 -3
  63. wbportfolio/viewsets/configs/titles/fees.py +4 -8
  64. wbportfolio/viewsets/mixins.py +5 -1
  65. wbportfolio/viewsets/products.py +6 -6
  66. wbportfolio/viewsets/transactions/__init__.py +2 -7
  67. wbportfolio/viewsets/transactions/fees.py +22 -22
  68. {wbportfolio-1.52.1.dist-info → wbportfolio-1.52.2rc0.dist-info}/METADATA +1 -1
  69. {wbportfolio-1.52.1.dist-info → wbportfolio-1.52.2rc0.dist-info}/RECORD +71 -80
  70. wbportfolio/admin/transactions/transactions.py +0 -38
  71. wbportfolio/factories/transactions.py +0 -22
  72. wbportfolio/filters/transactions/transactions.py +0 -99
  73. wbportfolio/models/transactions/expiry.py +0 -7
  74. wbportfolio/serializers/transactions/expiry.py +0 -18
  75. wbportfolio/serializers/transactions/transactions.py +0 -85
  76. wbportfolio/viewsets/configs/display/transactions.py +0 -55
  77. wbportfolio/viewsets/configs/endpoints/transactions.py +0 -14
  78. wbportfolio/viewsets/configs/menu/transactions.py +0 -9
  79. wbportfolio/viewsets/configs/titles/transactions.py +0 -9
  80. wbportfolio/viewsets/transactions/transactions.py +0 -122
  81. {wbportfolio-1.52.1.dist-info → wbportfolio-1.52.2rc0.dist-info}/WHEEL +0 -0
  82. {wbportfolio-1.52.1.dist-info → wbportfolio-1.52.2rc0.dist-info}/licenses/LICENSE +0 -0
@@ -1,85 +0,0 @@
1
- from wbcore import serializers as wb_serializers
2
- from wbcore.contrib.currency.serializers import CurrencyRepresentationSerializer
3
- from wbfdm.serializers import InvestableUniverseRepresentationSerializer
4
-
5
- from wbportfolio.models import Transaction
6
- from wbportfolio.serializers.portfolios import PortfolioRepresentationSerializer
7
-
8
-
9
- class TransactionRepresentationSerializer(wb_serializers.RepresentationSerializer):
10
- _detail = wb_serializers.HyperlinkField(reverse_name="wbportfolio:transaction-detail")
11
-
12
- class Meta:
13
- model = Transaction
14
- fields = ("id", "transaction_date", "total_value", "_detail")
15
-
16
-
17
- class TransactionModelSerializer(wb_serializers.ModelSerializer):
18
- external_id = wb_serializers.CharField(required=False, read_only=True)
19
- value_date = wb_serializers.DateField(required=False, read_only=True)
20
- total_value_usd = wb_serializers.FloatField(default=0, read_only=True, label="Total Value ($)")
21
- total_value_gross_usd = wb_serializers.FloatField(default=0, read_only=True, label="Total Value Gross ($)")
22
- transaction_underlying_type = wb_serializers.CharField(read_only=True)
23
- transaction_url_type = wb_serializers.SerializerMethodField()
24
- _portfolio = PortfolioRepresentationSerializer(source="portfolio")
25
- _underlying_instrument = InvestableUniverseRepresentationSerializer(source="underlying_instrument")
26
- _currency = CurrencyRepresentationSerializer(source="currency")
27
-
28
- total_value = wb_serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
29
- total_value_fx_portfolio = wb_serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
30
- total_value_gross = wb_serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
31
- total_value_gross_fx_portfolio = wb_serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
32
-
33
- def get_transaction_url_type(self, obj):
34
- return obj.transaction_type.lower()
35
-
36
- # def get_transaction_underlying_type(self, obj):
37
- # try:
38
- # casted_transaction = obj.get_casted_transaction()
39
- # return casted_transaction.Type[casted_transaction.transaction_subtype].label
40
- # except Exception as e:
41
- # return ""
42
- class Meta:
43
- model = Transaction
44
- decorators = {
45
- "total_value": wb_serializers.decorator(
46
- decorator_type="text", position="left", value="{{_currency.symbol}}"
47
- ),
48
- "total_value_gross": wb_serializers.decorator(
49
- decorator_type="text", position="left", value="{{_currency.symbol}}"
50
- ),
51
- "total_value_usd": wb_serializers.decorator(decorator_type="text", position="left", value="{{$}}"),
52
- "total_value_gross_usd": wb_serializers.decorator(decorator_type="text", position="left", value="{{$}}"),
53
- "total_value_fx_portfolio": wb_serializers.decorator(
54
- position="left", value="{{_portfolio.currency_symbol}}"
55
- ),
56
- "total_value_gross_fx_portfolio": wb_serializers.decorator(
57
- position="left", value="{{_portfolio.currency_symbol}}"
58
- ),
59
- # "total_value_fx_portfolio": wb_serializers.decorator(decorator_type="text", position="left", value="{{_portfolio.currency_symbol}}}"),
60
- # "total_value_gross_fx_portfolio": wb_serializers.decorator(decorator_type="text", position="left", value="{{_portfolio.currency_symbol}}"),
61
- }
62
- fields = (
63
- "id",
64
- "transaction_type",
65
- "transaction_url_type",
66
- "transaction_underlying_type",
67
- "portfolio",
68
- "_portfolio",
69
- "underlying_instrument",
70
- "_underlying_instrument",
71
- "transaction_date",
72
- "book_date",
73
- "value_date",
74
- "currency",
75
- "_currency",
76
- "currency_fx_rate",
77
- "total_value",
78
- "total_value_fx_portfolio",
79
- "total_value_gross",
80
- "total_value_gross_fx_portfolio",
81
- "external_id",
82
- "comment",
83
- "total_value_usd",
84
- "total_value_gross_usd",
85
- )
@@ -1,55 +0,0 @@
1
- from typing import Optional
2
-
3
- from wbcore.metadata.configs import display as dp
4
- from wbcore.metadata.configs.display.instance_display.shortcuts import (
5
- Display,
6
- create_simple_display,
7
- )
8
- from wbcore.metadata.configs.display.instance_display.utils import repeat_field
9
- from wbcore.metadata.configs.display.view_config import DisplayViewConfig
10
-
11
-
12
- class TransactionDisplayConfig(DisplayViewConfig):
13
- def get_list_display(self) -> Optional[dp.ListDisplay]:
14
- return dp.ListDisplay(
15
- fields=[
16
- dp.Field(key="transaction_type", label="Type"),
17
- dp.Field(key="transaction_underlying_type", label="Underlying Type"),
18
- dp.Field(key="transaction_date", label="Transaction Date"),
19
- dp.Field(key="portfolio", label="Portfolio"),
20
- dp.Field(key="underlying_instrument", label="Instrument"),
21
- dp.Field(key="currency_fx_rate", label="FX Rate"),
22
- dp.Field(key="currency", label="Currency"),
23
- dp.Field(key="total_value", label="Total Value"),
24
- dp.Field(key="total_value_fx_portfolio", label="Total Value (Portfolio)"),
25
- dp.Field(key="total_value_usd", label="Total Value ($)"),
26
- ]
27
- )
28
-
29
- def get_instance_display(self) -> Display:
30
- return create_simple_display(
31
- [
32
- ["transaction_type", "underlying_instrument", "external_id"],
33
- ["transaction_date", "book_date", "value_date"],
34
- ["currency", "total_value", "total_value_fx_portfolio"],
35
- [".", "total_value_gross", "total_value_gross_fx_portfolio"],
36
- [repeat_field(3, "comment")],
37
- ]
38
- )
39
-
40
-
41
- class TransactionPortfolioDisplayConfig(TransactionDisplayConfig):
42
- def get_list_display(self) -> Optional[dp.ListDisplay]:
43
- return dp.ListDisplay(
44
- fields=[
45
- dp.Field(key="transaction_type", label="Type"),
46
- dp.Field(key="transaction_underlying_type", label="Underlying Type"),
47
- dp.Field(key="transaction_date", label="Transaction Date"),
48
- dp.Field(key="underlying_instrument", label="Instrument"),
49
- dp.Field(key="currency_fx_rate", label="FX Rate"),
50
- dp.Field(key="currency", label="Currency"),
51
- dp.Field(key="total_value", label="Total Value"),
52
- dp.Field(key="total_value_fx_portfolio", label="Total Value (Portfolio)"),
53
- dp.Field(key="total_value_usd", label="Total Value ($)"),
54
- ]
55
- )
@@ -1,14 +0,0 @@
1
- from wbcore.metadata.configs.endpoints import EndpointViewConfig
2
-
3
-
4
- class TransactionEndpointConfig(EndpointViewConfig):
5
- def get_endpoint(self, **kwargs):
6
- return None
7
-
8
- def get_instance_endpoint(self, **kwargs):
9
- model = "{{transaction_url_type}}"
10
- return f"{self.request.scheme}://{self.request.get_host()}/api/portfolio/{model}/"
11
-
12
-
13
- class TransactionPortfolioEndpointConfig(TransactionEndpointConfig):
14
- pass
@@ -1,9 +0,0 @@
1
- from wbcore.menus import ItemPermission, MenuItem
2
-
3
- from wbportfolio.permissions import is_manager
4
-
5
- TRANSACTION_MENUITEM = MenuItem(
6
- label="Transactions",
7
- endpoint="wbportfolio:transaction-list",
8
- permission=ItemPermission(method=is_manager, permissions=["wbportfolio.view_transaction"]),
9
- )
@@ -1,9 +0,0 @@
1
- from wbcore.metadata.configs.titles import TitleViewConfig
2
-
3
- from wbportfolio.models import Portfolio
4
-
5
-
6
- class TransactionPortfolioTitleConfig(TitleViewConfig):
7
- def get_list_title(self):
8
- portfolio = Portfolio.objects.get(id=self.view.kwargs["portfolio_id"])
9
- return f"Transactions for Product {str(portfolio)}"
@@ -1,122 +0,0 @@
1
- from decimal import Decimal
2
-
3
- from django.db.models import (
4
- Case,
5
- DecimalField,
6
- ExpressionWrapper,
7
- F,
8
- OuterRef,
9
- Subquery,
10
- Sum,
11
- When,
12
- )
13
- from wbcore import viewsets
14
- from wbcore.contrib.currency.models import CurrencyFXRates
15
- from wbcore.permissions.permissions import InternalUserPermissionMixin
16
- from wbcore.utils.strings import format_number
17
-
18
- from wbportfolio.filters import TransactionFilterSet, TransactionPortfolioFilterSet
19
- from wbportfolio.models import Fees, Trade, Transaction
20
- from wbportfolio.serializers import (
21
- TransactionModelSerializer,
22
- TransactionRepresentationSerializer,
23
- )
24
-
25
- from ..configs import (
26
- TransactionDisplayConfig,
27
- TransactionEndpointConfig,
28
- TransactionPortfolioDisplayConfig,
29
- TransactionPortfolioEndpointConfig,
30
- TransactionPortfolioTitleConfig,
31
- )
32
- from ..mixins import UserPortfolioRequestPermissionMixin
33
-
34
-
35
- class TransactionRepresentationViewSet(InternalUserPermissionMixin, viewsets.RepresentationViewSet):
36
- IDENTIFIER = "wbportfolio:transaction"
37
- filterset_class = TransactionFilterSet
38
- search_fields = ("portfolio__name", "underlying_instrument__name", "comment")
39
- ordering_fields = (
40
- "transaction_date",
41
- "currency__key",
42
- "underlying_instrument__name",
43
- "portfolio__name",
44
- "transaction_type",
45
- "book_date",
46
- "value_date",
47
- "currency_fx_rate",
48
- "total_value",
49
- "total_value_fx_portfolio",
50
- "total_value_gross",
51
- "total_value_gross_fx_portfolio",
52
- )
53
- ordering = ["-transaction_date"]
54
-
55
- serializer_class = TransactionRepresentationSerializer
56
- queryset = Transaction.objects.all()
57
-
58
-
59
- class TransactionModelViewSet(UserPortfolioRequestPermissionMixin, InternalUserPermissionMixin, viewsets.ModelViewSet):
60
- IDENTIFIER = "wbportfolio:transaction"
61
-
62
- serializer_class = TransactionModelSerializer
63
-
64
- filterset_class = TransactionFilterSet
65
- ordering_fields = TransactionRepresentationViewSet.ordering_fields
66
- search_fields = TransactionRepresentationViewSet.search_fields
67
- ordering = TransactionRepresentationViewSet.ordering
68
-
69
- queryset = Transaction.objects.all()
70
- display_config_class = TransactionDisplayConfig
71
- endpoint_config_class = TransactionEndpointConfig
72
-
73
- def get_queryset(self):
74
- return (
75
- super()
76
- .get_queryset()
77
- .annotate(
78
- fx_rate=CurrencyFXRates.get_fx_rates_subquery(
79
- "transaction_date", currency="currency", lookup_expr="exact"
80
- ),
81
- total_value_usd=ExpressionWrapper(F("total_value"), output_field=DecimalField()),
82
- total_value_gross_usd=ExpressionWrapper(F("total_value_gross"), output_field=DecimalField()),
83
- transaction_underlying_type_trade=Subquery(
84
- Trade.objects.filter(id=OuterRef("pk")).values("transaction_subtype")[:1]
85
- ),
86
- transaction_underlying_type_fees=Subquery(
87
- Fees.objects.filter(id=OuterRef("pk")).values("transaction_subtype")[:1]
88
- ),
89
- transaction_underlying_type=Case(
90
- When(
91
- transaction_underlying_type_trade__isnull=False,
92
- then=F("transaction_underlying_type_trade"),
93
- ),
94
- When(transaction_underlying_type_fees__isnull=False, then=F("transaction_underlying_type_fees")),
95
- ),
96
- )
97
- .select_related("underlying_instrument")
98
- .select_related("portfolio")
99
- .select_related("currency")
100
- )
101
-
102
- def get_aggregates(self, queryset, paginated_queryset):
103
- return {
104
- "total_value_usd": {
105
- "Σ": format_number(queryset.aggregate(s=Sum("total_value_usd"))["s"] or Decimal(0)),
106
- }
107
- }
108
-
109
-
110
- class TransactionPortfolioModelViewSet(TransactionModelViewSet):
111
- IDENTIFIER = "wbportfolio:transaction"
112
-
113
- filterset_class = TransactionPortfolioFilterSet
114
- display_config_class = TransactionPortfolioDisplayConfig
115
- endpoint_config_class = TransactionPortfolioEndpointConfig
116
- title_config_class = TransactionPortfolioTitleConfig
117
-
118
- def get_queryset(self):
119
- qs = super().get_queryset().filter(portfolio=self.portfolio)
120
- if self.is_portfolio_manager:
121
- return qs
122
- return qs.exclude(transaction_type=Transaction.Type.FEES)