wbportfolio 1.52.0__py2.py3-none-any.whl → 1.59.4__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.
- wbportfolio/admin/__init__.py +3 -1
- wbportfolio/admin/indexes.py +1 -1
- wbportfolio/admin/orders/__init__.py +2 -0
- wbportfolio/admin/orders/order_proposals.py +16 -0
- wbportfolio/admin/orders/orders.py +32 -0
- wbportfolio/admin/portfolio.py +11 -5
- wbportfolio/admin/product_groups.py +1 -1
- wbportfolio/admin/products.py +2 -1
- wbportfolio/admin/{transactions/rebalancing.py → rebalancing.py} +1 -1
- wbportfolio/admin/transactions/__init__.py +0 -2
- wbportfolio/admin/transactions/dividends.py +40 -4
- wbportfolio/admin/transactions/fees.py +24 -14
- wbportfolio/admin/transactions/trades.py +34 -27
- wbportfolio/analysis/claims.py +5 -6
- wbportfolio/api_clients/ubs.py +162 -0
- wbportfolio/constants.py +1 -0
- wbportfolio/contrib/company_portfolio/configs/display.py +22 -10
- wbportfolio/contrib/company_portfolio/configs/previews.py +3 -3
- wbportfolio/contrib/company_portfolio/filters.py +10 -10
- wbportfolio/contrib/company_portfolio/models.py +69 -39
- wbportfolio/contrib/company_portfolio/scripts.py +7 -2
- wbportfolio/contrib/company_portfolio/serializers.py +32 -22
- wbportfolio/contrib/company_portfolio/tasks.py +12 -1
- wbportfolio/contrib/company_portfolio/tests/conftest.py +2 -2
- wbportfolio/defaults/fees/default.py +7 -15
- wbportfolio/factories/__init__.py +2 -2
- wbportfolio/factories/assets.py +1 -1
- wbportfolio/factories/dividends.py +8 -3
- wbportfolio/factories/fees.py +8 -4
- wbportfolio/factories/orders/__init__.py +2 -0
- wbportfolio/factories/orders/order_proposals.py +21 -0
- wbportfolio/factories/orders/orders.py +34 -0
- wbportfolio/factories/portfolios.py +2 -1
- wbportfolio/factories/product_groups.py +3 -3
- wbportfolio/factories/products.py +3 -3
- wbportfolio/factories/rebalancing.py +1 -1
- wbportfolio/factories/trades.py +12 -16
- wbportfolio/filters/assets.py +18 -4
- wbportfolio/filters/orders/__init__.py +2 -0
- wbportfolio/filters/orders/order_proposals.py +55 -0
- wbportfolio/filters/orders/orders.py +11 -0
- wbportfolio/filters/portfolios.py +38 -1
- wbportfolio/filters/positions.py +0 -1
- wbportfolio/filters/transactions/__init__.py +1 -2
- wbportfolio/filters/transactions/fees.py +5 -12
- wbportfolio/filters/transactions/trades.py +16 -8
- wbportfolio/filters/transactions/utils.py +42 -0
- wbportfolio/import_export/backends/ubs/__init__.py +1 -0
- wbportfolio/import_export/backends/ubs/asset_position.py +6 -7
- wbportfolio/import_export/backends/ubs/fees.py +10 -20
- wbportfolio/import_export/backends/ubs/instrument_price.py +6 -6
- wbportfolio/import_export/backends/ubs/trade.py +48 -0
- wbportfolio/import_export/backends/utils.py +0 -17
- wbportfolio/import_export/handlers/asset_position.py +22 -10
- wbportfolio/import_export/handlers/dividend.py +8 -8
- wbportfolio/import_export/handlers/fees.py +13 -23
- wbportfolio/import_export/handlers/orders.py +71 -0
- wbportfolio/import_export/handlers/trade.py +53 -77
- wbportfolio/import_export/parsers/default_mapping.py +1 -1
- wbportfolio/import_export/parsers/jpmorgan/customer_trade.py +2 -2
- wbportfolio/import_export/parsers/jpmorgan/fees.py +4 -4
- wbportfolio/import_export/parsers/jpmorgan/strategy.py +59 -85
- wbportfolio/import_export/parsers/jpmorgan/valuation.py +2 -2
- wbportfolio/import_export/parsers/leonteq/customer_trade.py +5 -5
- wbportfolio/import_export/parsers/leonteq/fees.py +11 -7
- wbportfolio/import_export/parsers/leonteq/trade.py +2 -6
- wbportfolio/import_export/parsers/natixis/d1_fees.py +2 -2
- wbportfolio/import_export/parsers/natixis/dividend.py +4 -9
- wbportfolio/import_export/parsers/natixis/equity.py +22 -4
- wbportfolio/import_export/parsers/natixis/fees.py +7 -9
- wbportfolio/import_export/parsers/natixis/utils.py +13 -19
- wbportfolio/import_export/parsers/sg_lux/customer_trade_pending_slk.py +1 -1
- wbportfolio/import_export/parsers/sg_lux/equity.py +10 -10
- wbportfolio/import_export/parsers/sg_lux/fees.py +2 -2
- wbportfolio/import_export/parsers/sg_lux/perf_fees.py +2 -2
- wbportfolio/import_export/parsers/sg_lux/sylk.py +12 -11
- wbportfolio/import_export/parsers/sg_lux/utils.py +2 -2
- wbportfolio/import_export/parsers/sg_lux/valuation.py +4 -2
- wbportfolio/import_export/parsers/societe_generale/strategy.py +5 -5
- wbportfolio/import_export/parsers/tellco/customer_trade.py +2 -1
- wbportfolio/import_export/parsers/tellco/valuation.py +4 -3
- wbportfolio/import_export/parsers/ubs/api/fees.py +2 -2
- wbportfolio/import_export/parsers/ubs/api/trade.py +39 -0
- wbportfolio/import_export/parsers/ubs/customer_trade.py +7 -5
- wbportfolio/import_export/parsers/ubs/equity.py +3 -2
- wbportfolio/import_export/parsers/ubs/valuation.py +2 -1
- wbportfolio/import_export/parsers/vontobel/customer_trade.py +2 -3
- wbportfolio/import_export/parsers/vontobel/historical_customer_trade.py +0 -1
- wbportfolio/import_export/parsers/vontobel/management_fees.py +12 -20
- wbportfolio/import_export/parsers/vontobel/performance_fees.py +5 -8
- wbportfolio/import_export/parsers/vontobel/valuation_api.py +4 -1
- wbportfolio/import_export/resources/trades.py +3 -3
- wbportfolio/import_export/utils.py +3 -1
- wbportfolio/jinja2/wbportfolio/sql/aum_nnm.sql +2 -2
- wbportfolio/metric/backends/base.py +2 -2
- wbportfolio/migrations/0059_fees_unique_fees.py +1 -1
- wbportfolio/migrations/0077_remove_transaction_currency_and_more.py +622 -0
- wbportfolio/migrations/0078_trade_drift_factor.py +26 -0
- wbportfolio/migrations/0079_alter_trade_drift_factor.py +19 -0
- wbportfolio/migrations/0080_alter_trade_drift_factor_alter_trade_weighting.py +19 -0
- wbportfolio/migrations/0081_alter_trade_drift_factor.py +19 -0
- wbportfolio/migrations/0082_remove_tradeproposal_creator_and_more.py +93 -0
- wbportfolio/migrations/0083_order_alter_trade_options_and_more.py +181 -0
- wbportfolio/migrations/0084_orderproposal_min_order_value.py +25 -0
- wbportfolio/migrations/0085_order_desired_target_weight.py +26 -0
- wbportfolio/migrations/0086_orderproposal_total_cash_weight.py +19 -0
- wbportfolio/migrations/0087_product_order_routing_custodian_adapter.py +94 -0
- wbportfolio/migrations/0088_orderproposal_total_effective_portfolio_contribution.py +19 -0
- wbportfolio/migrations/0089_orderproposal_min_weighting.py +71 -0
- wbportfolio/migrations/0090_dividendtransaction_price_fx_portfolio_and_more.py +44 -0
- wbportfolio/migrations/0091_remove_order_execution_confirmed_and_more.py +32 -0
- wbportfolio/migrations/0092_order_quantization_error_alter_orderproposal_status.py +49 -0
- wbportfolio/migrations/0093_remove_portfolioportfoliothroughmodel_unique_primary_and_more.py +35 -0
- wbportfolio/models/__init__.py +2 -0
- wbportfolio/models/adjustments.py +1 -1
- wbportfolio/models/asset.py +28 -170
- wbportfolio/models/builder.py +323 -0
- wbportfolio/models/custodians.py +3 -3
- wbportfolio/models/exceptions.py +1 -1
- wbportfolio/models/graphs/portfolio.py +1 -1
- wbportfolio/models/graphs/utils.py +11 -11
- wbportfolio/models/mixins/instruments.py +7 -0
- wbportfolio/models/mixins/liquidity_stress_test.py +4 -4
- wbportfolio/models/orders/__init__.py +2 -0
- wbportfolio/models/orders/order_proposals.py +1414 -0
- wbportfolio/models/orders/orders.py +410 -0
- wbportfolio/models/portfolio.py +311 -289
- wbportfolio/models/portfolio_relationship.py +6 -0
- wbportfolio/models/products.py +12 -0
- wbportfolio/models/{transactions/rebalancing.py → rebalancing.py} +40 -27
- wbportfolio/models/roles.py +4 -10
- wbportfolio/models/transactions/__init__.py +0 -4
- wbportfolio/models/transactions/claim.py +7 -6
- wbportfolio/models/transactions/dividends.py +42 -5
- wbportfolio/models/transactions/fees.py +55 -22
- wbportfolio/models/transactions/trades.py +121 -442
- wbportfolio/models/transactions/transactions.py +78 -158
- wbportfolio/models/utils.py +100 -1
- wbportfolio/order_routing/__init__.py +35 -0
- wbportfolio/order_routing/adapters/__init__.py +65 -0
- wbportfolio/order_routing/adapters/ubs.py +195 -0
- wbportfolio/order_routing/router.py +33 -0
- wbportfolio/order_routing/tests/__init__.py +0 -0
- wbportfolio/order_routing/tests/test_router.py +110 -0
- wbportfolio/permissions.py +7 -0
- wbportfolio/pms/analytics/portfolio.py +17 -9
- wbportfolio/pms/analytics/utils.py +9 -0
- wbportfolio/pms/trading/__init__.py +0 -1
- wbportfolio/pms/trading/optimizer.py +61 -0
- wbportfolio/pms/typing.py +198 -63
- wbportfolio/rebalancing/base.py +12 -1
- wbportfolio/rebalancing/decorators.py +1 -1
- wbportfolio/rebalancing/models/composite.py +4 -8
- wbportfolio/rebalancing/models/equally_weighted.py +13 -11
- wbportfolio/rebalancing/models/market_capitalization_weighted.py +21 -14
- wbportfolio/rebalancing/models/model_portfolio.py +14 -18
- wbportfolio/risk_management/backends/__init__.py +1 -0
- wbportfolio/risk_management/backends/controversy_portfolio.py +2 -2
- wbportfolio/risk_management/backends/esg_aggregation_portfolio.py +64 -0
- wbportfolio/risk_management/backends/exposure_portfolio.py +4 -4
- wbportfolio/risk_management/backends/instrument_list_portfolio.py +3 -3
- wbportfolio/risk_management/tests/test_esg_aggregation_portfolio.py +49 -0
- wbportfolio/risk_management/tests/test_exposure_portfolio.py +1 -1
- wbportfolio/risk_management/tests/test_stop_loss_instrument.py +2 -2
- wbportfolio/risk_management/tests/test_stop_loss_portfolio.py +1 -1
- wbportfolio/serializers/__init__.py +1 -0
- wbportfolio/serializers/orders/__init__.py +2 -0
- wbportfolio/serializers/orders/order_proposals.py +115 -0
- wbportfolio/serializers/orders/orders.py +283 -0
- wbportfolio/serializers/portfolios.py +7 -7
- wbportfolio/serializers/positions.py +2 -2
- wbportfolio/serializers/rebalancing.py +1 -1
- wbportfolio/serializers/signals.py +9 -12
- wbportfolio/serializers/transactions/__init__.py +1 -10
- wbportfolio/serializers/transactions/claim.py +2 -2
- wbportfolio/serializers/transactions/dividends.py +37 -9
- wbportfolio/serializers/transactions/fees.py +39 -10
- wbportfolio/serializers/transactions/trades.py +55 -157
- wbportfolio/tasks.py +43 -5
- wbportfolio/tests/analysis/__init__.py +0 -0
- wbportfolio/tests/analysis/test_claims.py +85 -0
- wbportfolio/tests/conftest.py +12 -12
- wbportfolio/tests/models/orders/__init__.py +0 -0
- wbportfolio/tests/models/orders/test_order_proposals.py +1046 -0
- wbportfolio/tests/models/test_assets.py +7 -3
- wbportfolio/tests/models/test_imports.py +9 -13
- wbportfolio/tests/models/test_portfolios.py +102 -95
- wbportfolio/tests/models/test_products.py +11 -0
- wbportfolio/tests/models/test_splits.py +1 -6
- wbportfolio/tests/models/test_utils.py +140 -0
- wbportfolio/tests/models/transactions/test_fees.py +7 -13
- wbportfolio/tests/models/transactions/test_rebalancing.py +5 -5
- wbportfolio/tests/models/transactions/test_trades.py +0 -20
- wbportfolio/tests/pms/test_analytics.py +22 -3
- wbportfolio/tests/rebalancing/test_models.py +51 -57
- wbportfolio/tests/signals.py +10 -20
- wbportfolio/tests/tests.py +3 -1
- wbportfolio/tests/viewsets/test_products.py +1 -0
- wbportfolio/urls.py +10 -13
- wbportfolio/viewsets/__init__.py +9 -4
- wbportfolio/viewsets/assets.py +3 -204
- wbportfolio/viewsets/charts/__init__.py +6 -1
- wbportfolio/viewsets/charts/assets.py +344 -154
- wbportfolio/viewsets/configs/buttons/__init__.py +2 -2
- wbportfolio/viewsets/configs/buttons/assets.py +1 -1
- wbportfolio/viewsets/configs/buttons/mixins.py +4 -4
- wbportfolio/viewsets/configs/buttons/portfolios.py +45 -1
- wbportfolio/viewsets/configs/buttons/products.py +32 -2
- wbportfolio/viewsets/configs/display/__init__.py +2 -5
- wbportfolio/viewsets/configs/display/assets.py +6 -19
- wbportfolio/viewsets/configs/display/fees.py +3 -3
- wbportfolio/viewsets/configs/display/portfolios.py +5 -5
- wbportfolio/viewsets/configs/display/products.py +1 -1
- wbportfolio/viewsets/configs/display/rebalancing.py +2 -2
- wbportfolio/viewsets/configs/display/reconciliations.py +4 -4
- wbportfolio/viewsets/configs/display/trades.py +1 -189
- wbportfolio/viewsets/configs/endpoints/__init__.py +3 -7
- wbportfolio/viewsets/configs/endpoints/fees.py +2 -2
- wbportfolio/viewsets/configs/endpoints/trades.py +0 -41
- wbportfolio/viewsets/configs/menu/__init__.py +1 -1
- wbportfolio/viewsets/configs/menu/orders.py +11 -0
- wbportfolio/viewsets/configs/titles/__init__.py +2 -3
- wbportfolio/viewsets/configs/titles/fees.py +4 -8
- wbportfolio/viewsets/esg.py +3 -5
- wbportfolio/viewsets/mixins.py +5 -1
- wbportfolio/viewsets/orders/__init__.py +6 -0
- wbportfolio/viewsets/orders/configs/__init__.py +4 -0
- wbportfolio/viewsets/orders/configs/buttons/__init__.py +2 -0
- wbportfolio/viewsets/orders/configs/buttons/order_proposals.py +188 -0
- wbportfolio/viewsets/orders/configs/buttons/orders.py +113 -0
- wbportfolio/viewsets/orders/configs/displays/__init__.py +2 -0
- wbportfolio/viewsets/orders/configs/displays/order_proposals.py +157 -0
- wbportfolio/viewsets/orders/configs/displays/orders.py +232 -0
- wbportfolio/viewsets/orders/configs/endpoints/__init__.py +2 -0
- wbportfolio/viewsets/orders/configs/endpoints/order_proposals.py +21 -0
- wbportfolio/viewsets/orders/configs/endpoints/orders.py +28 -0
- wbportfolio/viewsets/orders/configs/titles/__init__.py +0 -0
- wbportfolio/viewsets/orders/configs/titles/orders.py +0 -0
- wbportfolio/viewsets/orders/order_proposals.py +252 -0
- wbportfolio/viewsets/orders/orders.py +277 -0
- wbportfolio/viewsets/portfolios.py +36 -12
- wbportfolio/viewsets/positions.py +3 -2
- wbportfolio/viewsets/products.py +6 -6
- wbportfolio/viewsets/{transactions/rebalancing.py → rebalancing.py} +2 -2
- wbportfolio/viewsets/transactions/__init__.py +3 -14
- wbportfolio/viewsets/transactions/fees.py +22 -22
- wbportfolio/viewsets/transactions/trades.py +1 -180
- {wbportfolio-1.52.0.dist-info → wbportfolio-1.59.4.dist-info}/METADATA +3 -1
- {wbportfolio-1.52.0.dist-info → wbportfolio-1.59.4.dist-info}/RECORD +252 -203
- {wbportfolio-1.52.0.dist-info → wbportfolio-1.59.4.dist-info}/WHEEL +1 -1
- wbportfolio/admin/transactions/transactions.py +0 -38
- wbportfolio/factories/transactions.py +0 -22
- wbportfolio/fdm/tasks.py +0 -13
- wbportfolio/filters/transactions/transactions.py +0 -99
- wbportfolio/models/transactions/expiry.py +0 -7
- wbportfolio/models/transactions/trade_proposals.py +0 -704
- wbportfolio/pms/trading/handler.py +0 -161
- wbportfolio/serializers/transactions/expiry.py +0 -18
- wbportfolio/serializers/transactions/trade_proposals.py +0 -76
- wbportfolio/serializers/transactions/transactions.py +0 -85
- wbportfolio/tests/models/transactions/test_trade_proposals.py +0 -410
- wbportfolio/viewsets/configs/buttons/trade_proposals.py +0 -66
- wbportfolio/viewsets/configs/display/trade_proposals.py +0 -100
- wbportfolio/viewsets/configs/display/transactions.py +0 -55
- wbportfolio/viewsets/configs/endpoints/trade_proposals.py +0 -18
- wbportfolio/viewsets/configs/endpoints/transactions.py +0 -14
- wbportfolio/viewsets/configs/menu/transactions.py +0 -9
- wbportfolio/viewsets/configs/titles/transactions.py +0 -9
- wbportfolio/viewsets/signals.py +0 -43
- wbportfolio/viewsets/transactions/trade_proposals.py +0 -139
- wbportfolio/viewsets/transactions/transactions.py +0 -122
- /wbportfolio/{fdm → api_clients}/__init__.py +0 -0
- {wbportfolio-1.52.0.dist-info → wbportfolio-1.59.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,6 +2,7 @@ from contextlib import suppress
|
|
|
2
2
|
from datetime import date
|
|
3
3
|
|
|
4
4
|
from pandas._libs.tslibs.offsets import BDay
|
|
5
|
+
from rest_framework.reverse import reverse
|
|
5
6
|
from wbcore import serializers as wb_serializers
|
|
6
7
|
from wbcore.contrib.currency.serializers import CurrencyRepresentationSerializer
|
|
7
8
|
from wbcore.contrib.icons import WBIcon
|
|
@@ -11,9 +12,11 @@ from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
|
11
12
|
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
12
13
|
create_simple_display,
|
|
13
14
|
)
|
|
15
|
+
from wbfdm.models import Instrument
|
|
16
|
+
from wbfdm.serializers import InvestableUniverseRepresentationSerializer
|
|
14
17
|
|
|
15
18
|
from wbportfolio.models import AssetPosition, Portfolio
|
|
16
|
-
from wbportfolio.serializers import RebalancerModelSerializer
|
|
19
|
+
from wbportfolio.serializers import PortfolioRepresentationSerializer, RebalancerModelSerializer
|
|
17
20
|
from wbportfolio.viewsets.configs.display.rebalancing import RebalancerDisplayConfig
|
|
18
21
|
|
|
19
22
|
|
|
@@ -32,6 +35,28 @@ class CreateModelPortfolioSerializer(wb_serializers.ModelSerializer):
|
|
|
32
35
|
)
|
|
33
36
|
|
|
34
37
|
|
|
38
|
+
class AdjustQuoteSerializer(wb_serializers.Serializer):
|
|
39
|
+
old_quote = wb_serializers.PrimaryKeyRelatedField(queryset=Instrument.objects.all())
|
|
40
|
+
_old_quote = InvestableUniverseRepresentationSerializer(source="old_quote")
|
|
41
|
+
|
|
42
|
+
new_quote = wb_serializers.PrimaryKeyRelatedField(queryset=Instrument.objects.all())
|
|
43
|
+
_new_quote = InvestableUniverseRepresentationSerializer(
|
|
44
|
+
source="new_quote",
|
|
45
|
+
optional_get_parameters={"old_quote": "sibling_of"},
|
|
46
|
+
depends_on=[{"field": "old_quote", "options": {}}],
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
only_portfolios = wb_serializers.PrimaryKeyRelatedField(queryset=Portfolio.objects.all(), required=False)
|
|
50
|
+
_only_portfolios = PortfolioRepresentationSerializer(
|
|
51
|
+
source="only_portfolios",
|
|
52
|
+
optional_get_parameters={"old_quote": "invests_in"},
|
|
53
|
+
depends_on=[{"field": "new_quote", "options": {}}],
|
|
54
|
+
many=True,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
adjust_after = wb_serializers.DateField(required=False)
|
|
58
|
+
|
|
59
|
+
|
|
35
60
|
def _get_portfolio_start_end_serializer_class(portfolio):
|
|
36
61
|
today = date.today()
|
|
37
62
|
|
|
@@ -60,6 +85,25 @@ def _get_rebalance_serializer_class(portfolio):
|
|
|
60
85
|
|
|
61
86
|
|
|
62
87
|
class PortfolioButtonConfig(ButtonViewConfig):
|
|
88
|
+
def get_custom_buttons(self) -> set:
|
|
89
|
+
return {
|
|
90
|
+
bt.ActionButton(
|
|
91
|
+
method=RequestType.POST,
|
|
92
|
+
identifiers=("wbportfolio:portfolio",),
|
|
93
|
+
endpoint=reverse("wbportfolio:portfolio-adjustquote", args=[], request=self.request),
|
|
94
|
+
label="Adjust quote",
|
|
95
|
+
serializer=AdjustQuoteSerializer,
|
|
96
|
+
action_label="Action triggered",
|
|
97
|
+
title="Adjust Quote",
|
|
98
|
+
instance_display=create_simple_display(
|
|
99
|
+
[
|
|
100
|
+
["old_quote", "new_quote", "adjust_after"],
|
|
101
|
+
["only_portfolios", "only_portfolios", "only_portfolios"],
|
|
102
|
+
]
|
|
103
|
+
),
|
|
104
|
+
),
|
|
105
|
+
}
|
|
106
|
+
|
|
63
107
|
def get_custom_instance_buttons(self):
|
|
64
108
|
admin_buttons = [
|
|
65
109
|
bt.ActionButton(
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
+
from rest_framework.reverse import reverse
|
|
1
2
|
from wbcore.contrib.icons import WBIcon
|
|
2
3
|
from wbcore.metadata.configs import buttons as bt
|
|
3
4
|
from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
|
|
4
5
|
from wbfdm.viewsets.configs.buttons.instruments import InstrumentButtonViewConfig
|
|
5
6
|
|
|
7
|
+
from wbportfolio.models import Product
|
|
8
|
+
|
|
6
9
|
|
|
7
10
|
class ProductButtonConfig(ButtonViewConfig):
|
|
8
11
|
def get_custom_list_instance_buttons(self):
|
|
9
12
|
return self.get_custom_instance_buttons()
|
|
10
13
|
|
|
11
14
|
def get_custom_instance_buttons(self):
|
|
12
|
-
|
|
15
|
+
buttons = [
|
|
13
16
|
bt.DropDownButton(
|
|
14
17
|
label="Commission",
|
|
15
18
|
icon=WBIcon.UNFOLD.icon,
|
|
@@ -35,7 +38,34 @@ class ProductButtonConfig(ButtonViewConfig):
|
|
|
35
38
|
),
|
|
36
39
|
],
|
|
37
40
|
),
|
|
38
|
-
|
|
41
|
+
]
|
|
42
|
+
if product_id := self.view.kwargs.get("pk", None):
|
|
43
|
+
product = Product.objects.get(id=product_id)
|
|
44
|
+
report_buttons = []
|
|
45
|
+
for report in product.reports.filter(is_active=True):
|
|
46
|
+
tmp_buttons = []
|
|
47
|
+
if primary_version := report.primary_version:
|
|
48
|
+
tmp_buttons.append(
|
|
49
|
+
bt.HyperlinkButton(
|
|
50
|
+
label="Public Report",
|
|
51
|
+
endpoint=reverse(
|
|
52
|
+
"public_report:report_version", args=[primary_version.lookup], request=self.request
|
|
53
|
+
),
|
|
54
|
+
),
|
|
55
|
+
)
|
|
56
|
+
if self.request.user.profile.is_internal or self.request.user.is_superuser:
|
|
57
|
+
tmp_buttons.append(
|
|
58
|
+
bt.WidgetButton(
|
|
59
|
+
label="Widget",
|
|
60
|
+
endpoint=reverse("wbreport:report-detail", args=[report.id], request=self.request),
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
if tmp_buttons:
|
|
64
|
+
report_buttons.append(bt.DropDownButton(label=str(report), buttons=tmp_buttons))
|
|
65
|
+
if report_buttons:
|
|
66
|
+
buttons.append(bt.DropDownButton(label="Reports", buttons=report_buttons))
|
|
67
|
+
|
|
68
|
+
return set(buttons)
|
|
39
69
|
|
|
40
70
|
|
|
41
71
|
class ProductCustomerButtonConfig(ButtonViewConfig):
|
|
@@ -19,9 +19,9 @@ from .claim import (
|
|
|
19
19
|
from .custodians import CustodianDisplayConfig
|
|
20
20
|
|
|
21
21
|
from .fees import (
|
|
22
|
-
|
|
22
|
+
FeesAggregatedProductPandasDisplayConfig,
|
|
23
23
|
FeesDisplayConfig,
|
|
24
|
-
|
|
24
|
+
FeesProductDisplayConfig,
|
|
25
25
|
)
|
|
26
26
|
from .portfolios import (
|
|
27
27
|
PortfolioDisplayConfig,
|
|
@@ -49,10 +49,7 @@ from .trades import (
|
|
|
49
49
|
SubscriptionRedemptionDisplayConfig,
|
|
50
50
|
TradeDisplayConfig,
|
|
51
51
|
TradePortfolioDisplayConfig,
|
|
52
|
-
TradeTradeProposalDisplayConfig,
|
|
53
52
|
)
|
|
54
|
-
from .trade_proposals import TradeProposalDisplayConfig
|
|
55
|
-
from .transactions import TransactionDisplayConfig, TransactionPortfolioDisplayConfig
|
|
56
53
|
from .portfolio_relationship import (
|
|
57
54
|
PortfolioInstrumentPreferredClassificationThroughDisplayConfig,
|
|
58
55
|
InstrumentPortfolioThroughPortfolioModelDisplayConfig,
|
|
@@ -234,22 +234,9 @@ class CompositionModelPortfolioPandasDisplayConfig(DisplayViewConfig):
|
|
|
234
234
|
|
|
235
235
|
class DistributionTableDisplayConfig(DisplayViewConfig):
|
|
236
236
|
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
fields =
|
|
242
|
-
|
|
243
|
-
dp.Field(key="weighting", label="Weight"),
|
|
244
|
-
]
|
|
245
|
-
else:
|
|
246
|
-
fields = []
|
|
247
|
-
for level_rep in self.view.classification_levels_representation:
|
|
248
|
-
fields.append(dp.Field(key=level_rep, label=level_rep))
|
|
249
|
-
fields.extend(
|
|
250
|
-
[
|
|
251
|
-
dp.Field(key="equity", label="Equity"),
|
|
252
|
-
dp.Field(key="weighting", label="Weight"),
|
|
253
|
-
]
|
|
254
|
-
)
|
|
255
|
-
return dp.ListDisplay(fields=tuple(fields))
|
|
237
|
+
fields = [
|
|
238
|
+
dp.Field(key="weighting", label="Weighting"),
|
|
239
|
+
]
|
|
240
|
+
for k, v in reversed(self.view.columns_map.items()):
|
|
241
|
+
fields.append(dp.Field(key=k, label=v))
|
|
242
|
+
return dp.ListDisplay(fields=fields)
|
|
@@ -55,7 +55,7 @@ class FeesDisplayConfig(DisplayViewConfig):
|
|
|
55
55
|
)
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
class
|
|
58
|
+
class FeesProductDisplayConfig(DisplayViewConfig):
|
|
59
59
|
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
60
60
|
return dp.ListDisplay(
|
|
61
61
|
fields=[
|
|
@@ -98,7 +98,7 @@ class FeesPortfolioDisplayConfig(DisplayViewConfig):
|
|
|
98
98
|
dp.Field(key="calculated", label="Calculated"),
|
|
99
99
|
dp.Field(key="currency_fx_rate", label="FX rate", show="open"),
|
|
100
100
|
dp.Field(key="currency", label="Currency", show="open"),
|
|
101
|
-
dp.Field(key="
|
|
101
|
+
dp.Field(key="product", label="Product", show="open"),
|
|
102
102
|
],
|
|
103
103
|
),
|
|
104
104
|
]
|
|
@@ -117,7 +117,7 @@ class FeesPortfolioDisplayConfig(DisplayViewConfig):
|
|
|
117
117
|
)
|
|
118
118
|
|
|
119
119
|
|
|
120
|
-
class
|
|
120
|
+
class FeesAggregatedProductPandasDisplayConfig(DisplayViewConfig):
|
|
121
121
|
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
122
122
|
return dp.ListDisplay(
|
|
123
123
|
fields=[
|
|
@@ -51,9 +51,9 @@ class PortfolioDisplayConfig(DisplayViewConfig):
|
|
|
51
51
|
key=None,
|
|
52
52
|
children=[
|
|
53
53
|
dp.Field(key="automatic_rebalancer", label="Automatic Rebalancer"),
|
|
54
|
-
dp.Field(key="
|
|
54
|
+
dp.Field(key="last_order_proposal_date", label="Last Rebalance", width=Unit.PIXEL(250)),
|
|
55
55
|
dp.Field(
|
|
56
|
-
key="
|
|
56
|
+
key="next_expected_order_proposal_date",
|
|
57
57
|
label="Next Rebalancing",
|
|
58
58
|
width=Unit.PIXEL(250),
|
|
59
59
|
show="open",
|
|
@@ -126,15 +126,15 @@ class PortfolioDisplayConfig(DisplayViewConfig):
|
|
|
126
126
|
},
|
|
127
127
|
),
|
|
128
128
|
Page(
|
|
129
|
-
title="
|
|
129
|
+
title="Order",
|
|
130
130
|
layouts={
|
|
131
131
|
default(): dp.Layout(
|
|
132
132
|
grid_template_areas=[
|
|
133
|
-
["
|
|
133
|
+
["order_proposals"],
|
|
134
134
|
],
|
|
135
135
|
grid_template_rows=["auto"],
|
|
136
136
|
inlines=[
|
|
137
|
-
dp.Inline(key="
|
|
137
|
+
dp.Inline(key="order_proposals", endpoint="order_proposals"),
|
|
138
138
|
],
|
|
139
139
|
)
|
|
140
140
|
},
|
|
@@ -124,7 +124,7 @@ class ProductDisplayConfig(DisplayViewConfig):
|
|
|
124
124
|
return create_simple_display(
|
|
125
125
|
[
|
|
126
126
|
[repeat_field(2, "name"), repeat_field(2, "name_repr")],
|
|
127
|
-
["inception_date", "
|
|
127
|
+
["inception_date", "delisted_date", "isin", "id_repr"],
|
|
128
128
|
["share_price", "issue_price", "initial_high_water_mark", "currency"],
|
|
129
129
|
[repeat_field(2, "bank"), repeat_field(2, "parent")],
|
|
130
130
|
[repeat_field(4, "tags")],
|
|
@@ -11,7 +11,7 @@ class RebalancerDisplayConfig(DisplayViewConfig):
|
|
|
11
11
|
fields=[
|
|
12
12
|
dp.Field(key="portfolio", label="Portfolio"),
|
|
13
13
|
dp.Field(key="rebalancing_model", label="Rebalancing Model"),
|
|
14
|
-
dp.Field(key="
|
|
14
|
+
dp.Field(key="apply_order_proposal_automatically", label="Approve automatically"),
|
|
15
15
|
dp.Field(key="frequency_repr", label="Frequency"),
|
|
16
16
|
dp.Field(key="activation_date", label="Activation Date"),
|
|
17
17
|
],
|
|
@@ -20,7 +20,7 @@ class RebalancerDisplayConfig(DisplayViewConfig):
|
|
|
20
20
|
def get_instance_display(self) -> Display:
|
|
21
21
|
return create_simple_display(
|
|
22
22
|
[
|
|
23
|
-
["rebalancing_model", "
|
|
23
|
+
["rebalancing_model", "apply_order_proposal_automatically"],
|
|
24
24
|
["frequency", "activation_date"],
|
|
25
25
|
["rebalancing_dates", "rebalancing_dates"],
|
|
26
26
|
]
|
|
@@ -49,14 +49,14 @@ class AccountReconciliationLineDisplayViewConfig(DisplayViewConfig):
|
|
|
49
49
|
]
|
|
50
50
|
editable = [dp.FormattingRule(style={"fontWeight": "bold"})]
|
|
51
51
|
equal = [dp.FormattingRule(condition=("==", False, "is_equal"), style={"backgroundColor": "orange"})]
|
|
52
|
-
|
|
52
|
+
border_left = [
|
|
53
53
|
dp.FormattingRule(
|
|
54
54
|
style={
|
|
55
55
|
"borderLeft": "1px solid #bdc3c7",
|
|
56
56
|
}
|
|
57
57
|
)
|
|
58
58
|
]
|
|
59
|
-
|
|
59
|
+
border_right = [
|
|
60
60
|
dp.FormattingRule(
|
|
61
61
|
style={
|
|
62
62
|
"borderRight": "1px solid #bdc3c7",
|
|
@@ -111,7 +111,7 @@ class AccountReconciliationLineDisplayViewConfig(DisplayViewConfig):
|
|
|
111
111
|
key="shares_external",
|
|
112
112
|
label="Shares",
|
|
113
113
|
width=90,
|
|
114
|
-
formatting_rules=[*equal, *editable, *
|
|
114
|
+
formatting_rules=[*equal, *editable, *border_left],
|
|
115
115
|
),
|
|
116
116
|
dp.Field(
|
|
117
117
|
key="nominal_value_external",
|
|
@@ -128,7 +128,7 @@ class AccountReconciliationLineDisplayViewConfig(DisplayViewConfig):
|
|
|
128
128
|
key="assets_under_management_external",
|
|
129
129
|
label="AuM",
|
|
130
130
|
width=120,
|
|
131
|
-
formatting_rules=[*equal, *
|
|
131
|
+
formatting_rules=[*equal, *border_right],
|
|
132
132
|
),
|
|
133
133
|
],
|
|
134
134
|
),
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
|
-
from django.shortcuts import get_object_or_404
|
|
4
3
|
from wbcore.contrib.color.enums import WBColor
|
|
5
4
|
from wbcore.contrib.icons import WBIcon
|
|
6
5
|
from wbcore.enums import Unit
|
|
@@ -12,8 +11,6 @@ from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
|
12
11
|
from wbcore.metadata.configs.display.instance_display.utils import repeat_field
|
|
13
12
|
from wbcore.metadata.configs.display.view_config import DisplayViewConfig
|
|
14
13
|
|
|
15
|
-
from wbportfolio.models import Trade, TradeProposal
|
|
16
|
-
|
|
17
14
|
NEGATIVE_RED_FORMATTING = [
|
|
18
15
|
dp.FormattingRule(
|
|
19
16
|
style={
|
|
@@ -37,63 +34,6 @@ SHARE_FORMATTING = dp.Formatting(
|
|
|
37
34
|
],
|
|
38
35
|
)
|
|
39
36
|
|
|
40
|
-
TRADE_STATUS_LEGENDS = dp.Legend(
|
|
41
|
-
key="status",
|
|
42
|
-
items=[
|
|
43
|
-
dp.LegendItem(
|
|
44
|
-
icon=WBColor.RED_LIGHT.value,
|
|
45
|
-
label=Trade.Status.FAILED.label,
|
|
46
|
-
value=Trade.Status.FAILED.value,
|
|
47
|
-
),
|
|
48
|
-
dp.LegendItem(
|
|
49
|
-
icon=WBColor.BLUE_LIGHT.value,
|
|
50
|
-
label=Trade.Status.DRAFT.label,
|
|
51
|
-
value=Trade.Status.DRAFT.value,
|
|
52
|
-
),
|
|
53
|
-
dp.LegendItem(
|
|
54
|
-
icon=WBColor.YELLOW_LIGHT.value,
|
|
55
|
-
label=Trade.Status.SUBMIT.label,
|
|
56
|
-
value=Trade.Status.SUBMIT.value,
|
|
57
|
-
),
|
|
58
|
-
dp.LegendItem(
|
|
59
|
-
icon=WBColor.GREEN_LIGHT.value,
|
|
60
|
-
label=Trade.Status.EXECUTED.label,
|
|
61
|
-
value=Trade.Status.EXECUTED.value,
|
|
62
|
-
),
|
|
63
|
-
dp.LegendItem(
|
|
64
|
-
icon=WBColor.GREEN.value,
|
|
65
|
-
label=Trade.Status.CONFIRMED.label,
|
|
66
|
-
value=Trade.Status.CONFIRMED.value,
|
|
67
|
-
),
|
|
68
|
-
],
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
TRADE_STATUS_FORMATTING = dp.Formatting(
|
|
72
|
-
column="status",
|
|
73
|
-
formatting_rules=[
|
|
74
|
-
dp.FormattingRule(
|
|
75
|
-
style={"backgroundColor": WBColor.RED_LIGHT.value},
|
|
76
|
-
condition=("==", Trade.Status.FAILED.value),
|
|
77
|
-
),
|
|
78
|
-
dp.FormattingRule(
|
|
79
|
-
style={"backgroundColor": WBColor.BLUE_LIGHT.value},
|
|
80
|
-
condition=("==", Trade.Status.DRAFT.value),
|
|
81
|
-
),
|
|
82
|
-
dp.FormattingRule(
|
|
83
|
-
style={"backgroundColor": WBColor.YELLOW_LIGHT.value},
|
|
84
|
-
condition=("==", Trade.Status.SUBMIT.value),
|
|
85
|
-
),
|
|
86
|
-
dp.FormattingRule(
|
|
87
|
-
style={"backgroundColor": WBColor.GREEN_LIGHT.value},
|
|
88
|
-
condition=("==", Trade.Status.EXECUTED.value),
|
|
89
|
-
),
|
|
90
|
-
dp.FormattingRule(
|
|
91
|
-
style={"backgroundColor": WBColor.GREEN.value},
|
|
92
|
-
condition=("==", Trade.Status.CONFIRMED.value),
|
|
93
|
-
),
|
|
94
|
-
],
|
|
95
|
-
)
|
|
96
|
-
|
|
97
37
|
|
|
98
38
|
class TradeDisplayConfig(DisplayViewConfig):
|
|
99
39
|
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
@@ -145,8 +85,7 @@ class TradeDisplayConfig(DisplayViewConfig):
|
|
|
145
85
|
),
|
|
146
86
|
),
|
|
147
87
|
],
|
|
148
|
-
|
|
149
|
-
formatting=[SHARE_FORMATTING, TRADE_STATUS_FORMATTING],
|
|
88
|
+
formatting=[SHARE_FORMATTING],
|
|
150
89
|
)
|
|
151
90
|
|
|
152
91
|
def get_instance_display(self) -> Display:
|
|
@@ -285,130 +224,3 @@ class SubscriptionRedemptionDisplayConfig(TradeDisplayConfig):
|
|
|
285
224
|
|
|
286
225
|
class TradePortfolioDisplayConfig(TradeDisplayConfig):
|
|
287
226
|
pass
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
class TradeTradeProposalDisplayConfig(DisplayViewConfig):
|
|
291
|
-
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
292
|
-
trade_proposal = get_object_or_404(TradeProposal, pk=self.view.kwargs.get("trade_proposal_id", None))
|
|
293
|
-
fields = [
|
|
294
|
-
dp.Field(
|
|
295
|
-
label="Instrument",
|
|
296
|
-
open_by_default=True,
|
|
297
|
-
key=None,
|
|
298
|
-
children=[
|
|
299
|
-
dp.Field(key="underlying_instrument", label="Name", width=Unit.PIXEL(250)),
|
|
300
|
-
dp.Field(key="underlying_instrument_isin", label="ISIN", width=Unit.PIXEL(125)),
|
|
301
|
-
dp.Field(key="underlying_instrument_ticker", label="Ticker", width=Unit.PIXEL(100)),
|
|
302
|
-
dp.Field(
|
|
303
|
-
key="underlying_instrument_refinitiv_identifier_code", label="RIC", width=Unit.PIXEL(100)
|
|
304
|
-
),
|
|
305
|
-
dp.Field(key="underlying_instrument_instrument_type", label="Asset Class", width=Unit.PIXEL(125)),
|
|
306
|
-
],
|
|
307
|
-
),
|
|
308
|
-
dp.Field(
|
|
309
|
-
label="Weight",
|
|
310
|
-
open_by_default=False,
|
|
311
|
-
key=None,
|
|
312
|
-
children=[
|
|
313
|
-
dp.Field(key="effective_weight", label="Effective Weight", show="open", width=Unit.PIXEL(150)),
|
|
314
|
-
dp.Field(key="target_weight", label="Target Weight", show="open", width=Unit.PIXEL(150)),
|
|
315
|
-
dp.Field(
|
|
316
|
-
key="weighting",
|
|
317
|
-
label="Delta Weight",
|
|
318
|
-
formatting_rules=[
|
|
319
|
-
dp.FormattingRule(
|
|
320
|
-
style={"color": WBColor.RED_DARK.value, "fontWeight": "bold"},
|
|
321
|
-
condition=("<", 0),
|
|
322
|
-
),
|
|
323
|
-
dp.FormattingRule(
|
|
324
|
-
style={"color": WBColor.GREEN_DARK.value, "fontWeight": "bold"},
|
|
325
|
-
condition=(">", 0),
|
|
326
|
-
),
|
|
327
|
-
],
|
|
328
|
-
width=Unit.PIXEL(150),
|
|
329
|
-
),
|
|
330
|
-
],
|
|
331
|
-
),
|
|
332
|
-
]
|
|
333
|
-
if not trade_proposal.portfolio.only_weighting:
|
|
334
|
-
fields.append(
|
|
335
|
-
dp.Field(
|
|
336
|
-
label="Shares",
|
|
337
|
-
open_by_default=False,
|
|
338
|
-
key=None,
|
|
339
|
-
children=[
|
|
340
|
-
dp.Field(key="effective_shares", label="Effective Shares", show="open", width=Unit.PIXEL(150)),
|
|
341
|
-
dp.Field(key="target_shares", label="Target Shares", show="open", width=Unit.PIXEL(150)),
|
|
342
|
-
dp.Field(
|
|
343
|
-
key="shares",
|
|
344
|
-
label="Shares",
|
|
345
|
-
formatting_rules=[
|
|
346
|
-
dp.FormattingRule(
|
|
347
|
-
style={"color": WBColor.RED_DARK.value, "fontWeight": "bold"},
|
|
348
|
-
condition=("<", 0),
|
|
349
|
-
),
|
|
350
|
-
dp.FormattingRule(
|
|
351
|
-
style={"color": WBColor.GREEN_DARK.value, "fontWeight": "bold"},
|
|
352
|
-
condition=(">", 0),
|
|
353
|
-
),
|
|
354
|
-
],
|
|
355
|
-
width=Unit.PIXEL(150),
|
|
356
|
-
),
|
|
357
|
-
],
|
|
358
|
-
)
|
|
359
|
-
)
|
|
360
|
-
fields.append(
|
|
361
|
-
dp.Field(
|
|
362
|
-
label="Information",
|
|
363
|
-
open_by_default=False,
|
|
364
|
-
key=None,
|
|
365
|
-
children=[
|
|
366
|
-
dp.Field(
|
|
367
|
-
key="transaction_subtype",
|
|
368
|
-
label="Direction",
|
|
369
|
-
formatting_rules=[
|
|
370
|
-
dp.FormattingRule(
|
|
371
|
-
style={"color": WBColor.RED_DARK.value, "fontWeight": "bold"},
|
|
372
|
-
condition=("==", Trade.Type.SELL.name),
|
|
373
|
-
),
|
|
374
|
-
dp.FormattingRule(
|
|
375
|
-
style={"color": WBColor.RED_DARK.value, "fontWeight": "bold"},
|
|
376
|
-
condition=("==", Trade.Type.DECREASE.name),
|
|
377
|
-
),
|
|
378
|
-
dp.FormattingRule(
|
|
379
|
-
style={"color": WBColor.GREEN_DARK.value, "fontWeight": "bold"},
|
|
380
|
-
condition=("==", Trade.Type.INCREASE.name),
|
|
381
|
-
),
|
|
382
|
-
dp.FormattingRule(
|
|
383
|
-
style={"color": WBColor.GREEN_DARK.value, "fontWeight": "bold"},
|
|
384
|
-
condition=("==", Trade.Type.BUY.name),
|
|
385
|
-
),
|
|
386
|
-
dp.FormattingRule(
|
|
387
|
-
style={"color": WBColor.GREY.value, "fontWeight": "bold"},
|
|
388
|
-
condition=("==", Trade.Type.NO_CHANGE.name),
|
|
389
|
-
),
|
|
390
|
-
],
|
|
391
|
-
width=Unit.PIXEL(125),
|
|
392
|
-
),
|
|
393
|
-
dp.Field(key="comment", label="Comment", width=Unit.PIXEL(250)),
|
|
394
|
-
dp.Field(key="order", label="Order", show="open", width=Unit.PIXEL(100)),
|
|
395
|
-
],
|
|
396
|
-
)
|
|
397
|
-
)
|
|
398
|
-
return dp.ListDisplay(
|
|
399
|
-
fields=fields,
|
|
400
|
-
legends=[TRADE_STATUS_LEGENDS],
|
|
401
|
-
formatting=[TRADE_STATUS_FORMATTING],
|
|
402
|
-
)
|
|
403
|
-
|
|
404
|
-
def get_instance_display(self) -> Display:
|
|
405
|
-
trade_proposal = get_object_or_404(TradeProposal, pk=self.view.kwargs.get("trade_proposal_id", None))
|
|
406
|
-
|
|
407
|
-
fields = [
|
|
408
|
-
["company", "security", "underlying_instrument"],
|
|
409
|
-
["effective_weight", "target_weight", "weighting"],
|
|
410
|
-
]
|
|
411
|
-
if not trade_proposal.portfolio.only_weighting:
|
|
412
|
-
fields.append(["effective_shares", "target_shares", "shares"])
|
|
413
|
-
fields.append([repeat_field(3, "comment")])
|
|
414
|
-
return create_simple_display(fields)
|
|
@@ -28,10 +28,10 @@ from .claim import (
|
|
|
28
28
|
|
|
29
29
|
from .custodians import CustodianEndpointConfig
|
|
30
30
|
from .fees import (
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
FeesAggregatedProductPandasEndpointConfig,
|
|
32
|
+
FeesProductEndpointConfig,
|
|
33
33
|
)
|
|
34
|
-
from .fees import
|
|
34
|
+
from .fees import FeesAggregatedProductPandasEndpointConfig, FeesProductEndpointConfig, FeeEndpointConfig
|
|
35
35
|
|
|
36
36
|
from .portfolios import (
|
|
37
37
|
PortfolioEndpointConfig,
|
|
@@ -62,12 +62,8 @@ from .trades import (
|
|
|
62
62
|
TradeEndpointConfig,
|
|
63
63
|
TradeInstrumentEndpointConfig,
|
|
64
64
|
TradePortfolioEndpointConfig,
|
|
65
|
-
TradeProposalEndpointConfig,
|
|
66
|
-
TradeProposalPortfolioEndpointConfig,
|
|
67
|
-
TradeTradeProposalEndpointConfig,
|
|
68
65
|
SubscriptionRedemptionEndpointConfig,
|
|
69
66
|
)
|
|
70
|
-
from .transactions import TransactionEndpointConfig, TransactionPortfolioEndpointConfig
|
|
71
67
|
from .portfolio_relationship import (
|
|
72
68
|
PortfolioInstrumentPreferredClassificationThroughEndpointConfig,
|
|
73
69
|
InstrumentPortfolioThroughPortfolioModelEndpointConfig,
|
|
@@ -6,9 +6,9 @@ class FeeEndpointConfig(EndpointViewConfig):
|
|
|
6
6
|
return None
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class
|
|
9
|
+
class FeesProductEndpointConfig(FeeEndpointConfig):
|
|
10
10
|
pass
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class FeesAggregatedProductPandasEndpointConfig(EndpointViewConfig):
|
|
14
14
|
pass
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
from contextlib import suppress
|
|
2
|
-
|
|
3
|
-
from django.shortcuts import get_object_or_404
|
|
4
1
|
from rest_framework.reverse import reverse
|
|
5
2
|
from wbcore.metadata.configs.endpoints import EndpointViewConfig
|
|
6
3
|
|
|
7
|
-
from wbportfolio.models import TradeProposal
|
|
8
|
-
|
|
9
4
|
|
|
10
5
|
class TradeEndpointConfig(EndpointViewConfig):
|
|
11
6
|
def get_endpoint(self, **kwargs):
|
|
@@ -50,42 +45,6 @@ class CustodianDistributionInstrumentEndpointConfig(EndpointViewConfig):
|
|
|
50
45
|
)
|
|
51
46
|
|
|
52
47
|
|
|
53
|
-
class TradeProposalEndpointConfig(EndpointViewConfig):
|
|
54
|
-
def get_delete_endpoint(self, **kwargs):
|
|
55
|
-
if pk := self.view.kwargs.get("pk", None):
|
|
56
|
-
trade_proposal = get_object_or_404(TradeProposal, pk=pk)
|
|
57
|
-
if trade_proposal.status == TradeProposal.Status.DRAFT:
|
|
58
|
-
return super().get_endpoint()
|
|
59
|
-
return None
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class TradeProposalPortfolioEndpointConfig(TradeProposalEndpointConfig):
|
|
63
|
-
def get_endpoint(self, **kwargs):
|
|
64
|
-
return reverse(
|
|
65
|
-
"wbportfolio:portfolio-tradeproposal-list", args=[self.view.kwargs["portfolio_id"]], request=self.request
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class TradeTradeProposalEndpointConfig(EndpointViewConfig):
|
|
70
|
-
def get_endpoint(self, **kwargs):
|
|
71
|
-
if trade_proposal_id := self.view.kwargs.get("trade_proposal_id", None):
|
|
72
|
-
trade_proposal = TradeProposal.objects.get(id=trade_proposal_id)
|
|
73
|
-
if trade_proposal.status == TradeProposal.Status.DRAFT:
|
|
74
|
-
return reverse(
|
|
75
|
-
"wbportfolio:tradeproposal-trade-list",
|
|
76
|
-
args=[self.view.kwargs["trade_proposal_id"]],
|
|
77
|
-
request=self.request,
|
|
78
|
-
)
|
|
79
|
-
return None
|
|
80
|
-
|
|
81
|
-
def get_delete_endpoint(self, **kwargs):
|
|
82
|
-
with suppress(AttributeError, AssertionError):
|
|
83
|
-
trade = self.view.get_object()
|
|
84
|
-
if trade._effective_weight: # we make sure trade with a valid effective position cannot be deleted
|
|
85
|
-
return None
|
|
86
|
-
return super().get_delete_endpoint(**kwargs)
|
|
87
|
-
|
|
88
|
-
|
|
89
48
|
class SubscriptionRedemptionEndpointConfig(TradeEndpointConfig):
|
|
90
49
|
def get_endpoint(self, **kwargs):
|
|
91
50
|
return reverse("wbportfolio:subscriptionredemption-list", args=[], request=self.request)
|
|
@@ -25,6 +25,6 @@ from .products import PRODUCT_MENUITEM, PRODUCTCUSTOMER_MENUITEM
|
|
|
25
25
|
from .registers import REGISTER_MENUITEM
|
|
26
26
|
from .roles import PORTFOLIOROLE_MENUITEM
|
|
27
27
|
from .trades import SUBSCRIPTION_REDEMPTION_MENUITEM, TRADE_MENUITEM
|
|
28
|
-
from .transactions import TRANSACTION_MENUITEM
|
|
29
28
|
from .portfolio_cash_flow import PORTFOLIO_DAILY_CASH_FLOW
|
|
30
29
|
from .reconciliations import ACCOUNT_RECONCILIATION_MENU_ITEM
|
|
30
|
+
from .orders import OrderProposalMenuItem
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from wbcore.menus import ItemPermission, MenuItem
|
|
2
|
+
from wbcore.permissions.shortcuts import is_internal_user
|
|
3
|
+
|
|
4
|
+
OrderProposalMenuItem = MenuItem(
|
|
5
|
+
label="Order Proposals",
|
|
6
|
+
endpoint="wbportfolio:orderproposal-list",
|
|
7
|
+
endpoint_get_parameters={"waiting_for_input": True},
|
|
8
|
+
permission=ItemPermission(
|
|
9
|
+
permissions=["wbportfolio.view_orderproposal"], method=lambda request: is_internal_user(request.user)
|
|
10
|
+
),
|
|
11
|
+
)
|
|
@@ -27,8 +27,8 @@ from .claim import (
|
|
|
27
27
|
from .custodians import CustodianTitleConfig
|
|
28
28
|
|
|
29
29
|
from .fees import (
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
FeesAggregatedProductTitleConfig,
|
|
31
|
+
FeesProductTitleConfig,
|
|
32
32
|
FeesTitleConfig,
|
|
33
33
|
)
|
|
34
34
|
|
|
@@ -60,6 +60,5 @@ from .trades import (
|
|
|
60
60
|
TradePortfolioTitleConfig,
|
|
61
61
|
TradeTitleConfig,
|
|
62
62
|
)
|
|
63
|
-
from .transactions import TransactionPortfolioTitleConfig
|
|
64
63
|
from .esg import ESGMetricAggregationPortfolioPandasTitleConfig
|
|
65
64
|
from .assets_and_net_new_money_progression import AssetAndNetNewMoneyProgressionChartTitleConfig
|