wbportfolio 1.50.10__py2.py3-none-any.whl → 1.50.11__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.

@@ -1,5 +1,3 @@
1
- from contextlib import suppress
2
-
3
1
  from django.db import models
4
2
  from django.db.models.signals import post_save
5
3
  from django.dispatch import receiver
@@ -58,6 +56,7 @@ class AccountReconciliation(Reconciliation):
58
56
  "Account Reconciliation Events",
59
57
  "A notification that informs the user about an account reconciliation event.",
60
58
  email=True,
59
+ is_lock=True,
61
60
  ),
62
61
  ]
63
62
 
@@ -80,12 +79,13 @@ class AccountReconciliation(Reconciliation):
80
79
  def get_representation_label_key(cls):
81
80
  return "{{account}} {{reconciliation_date}}"
82
81
 
83
- def notify(self, update: bool = False):
82
+ def notify(self, update: bool = False, silent_errors: bool = True) -> None:
84
83
  registry = global_preferences_registry.manager()
85
84
  title = registry["wbportfolio__account_holding_reconciliation_notification_title"]
86
85
  body = registry[f"wbportfolio__account_holding_reconciliation_notification_body{'_update' if update else ''}"]
86
+ errors_entries = []
87
87
  for role in self.account.roles.filter(role_type__key="reconciliation-manager"):
88
- with suppress(User.DoesNotExist):
88
+ try:
89
89
  user = User.objects.get(profile_id=role.entry.id)
90
90
  send_notification(
91
91
  code="wbportfolio.account_reconciliation.notify",
@@ -95,6 +95,12 @@ class AccountReconciliation(Reconciliation):
95
95
  reverse_name="wbportfolio:accountreconciliation-detail",
96
96
  reverse_args=[self.id],
97
97
  )
98
+ except User.DoesNotExist:
99
+ errors_entries.append(role.entry)
100
+ if errors_entries and not silent_errors:
101
+ raise ValueError(
102
+ f"Because of missing valid user account, we couldn't successfully notify the account holding reconciliation to the following customers: {', '.join(errors_entries)}. Note: The other customers were successfully notified."
103
+ )
98
104
 
99
105
 
100
106
  @receiver(post_save, sender=AccountReconciliation)
@@ -356,11 +356,19 @@ class ContributorPortfolioChartView(UserPortfolioRequestPermissionMixin, viewset
356
356
  title_config_class = ContributorPortfolioChartTitleConfig
357
357
  endpoint_config_class = ContributorPortfolioChartEndpointConfig
358
358
 
359
+ ROW_HEIGHT: int = 20
360
+
361
+ @property
362
+ def min_height(self):
363
+ if hasattr(self, "nb_rows"):
364
+ return self.nb_rows * self.ROW_HEIGHT
365
+ return "300px"
366
+
359
367
  @cached_property
360
368
  def hedged_currency(self) -> Currency | None:
361
369
  if "hedged_currency" in self.request.GET:
362
370
  with suppress(Currency.DoesNotExist):
363
- return Currency.objects.get(pk=self.kwargs["hedged_currency"])
371
+ return Currency.objects.get(pk=self.request.GET["hedged_currency"])
364
372
 
365
373
  @cached_property
366
374
  def show_lookthrough(self) -> bool:
@@ -407,6 +415,7 @@ class ContributorPortfolioChartView(UserPortfolioRequestPermissionMixin, viewset
407
415
 
408
416
  text_forex = df_forex.contribution_forex.apply(lambda x: f"{x:,.2%}")
409
417
  text_equity = contribution_equity.apply(lambda x: f"{x:,.2%}")
418
+ setattr(self, "nb_rows", df.shape[0])
410
419
  fig.add_trace(
411
420
  go.Bar(
412
421
  y=df.instrument_id,
@@ -443,10 +452,16 @@ class ContributorPortfolioChartView(UserPortfolioRequestPermissionMixin, viewset
443
452
  paper_bgcolor="rgba(0,0,0,0)",
444
453
  plot_bgcolor="rgba(0,0,0,0)",
445
454
  font=dict(family="roboto", size=12, color="black"),
455
+ bargap=0.3,
446
456
  )
447
457
  # fig = get_horizontal_barplot(df, x_label="contribution_total", y_label="name")
448
458
  return fig
449
459
 
460
+ def parse_figure_dict(self, figure_dict: dict[str, any]) -> dict[str, any]:
461
+ figure_dict = super().parse_figure_dict(figure_dict)
462
+ figure_dict["style"]["minHeight"] = self.min_height
463
+ return figure_dict
464
+
450
465
  def get_queryset(self):
451
466
  if self.has_portfolio_access:
452
467
  return super().get_queryset().filter(portfolio=self.portfolio)
@@ -46,7 +46,13 @@ class AccountReconciliationModelViewSet(viewsets.ModelViewSet):
46
46
  button_config_class = AccountReconciliationButtonViewConfig
47
47
  endpoint_config_class = AccountReconciliationEndpointViewConfig
48
48
 
49
- filterset_fields = {"account": ["exact"]}
49
+ filterset_fields = {
50
+ "account": ["exact"],
51
+ "creator": ["exact"],
52
+ "approved_by": ["exact"],
53
+ "reconciliation_date": ["gte", "exact", "lte"],
54
+ "approved_dt": ["gte", "lte"],
55
+ }
50
56
  ordering = ordering_fields = ["-reconciliation_date"]
51
57
 
52
58
  def get_queryset(self):
@@ -108,8 +114,11 @@ class AccountReconciliationModelViewSet(viewsets.ModelViewSet):
108
114
 
109
115
  @action(methods=["PATCH"], detail=True)
110
116
  def notify(self, request: "Request", pk: int | None = None) -> Response:
111
- self.get_object().notify(update=True)
112
- return Response()
117
+ try:
118
+ self.get_object().notify(update=True, silent_errors=False)
119
+ return Response()
120
+ except ValueError as e:
121
+ return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
113
122
 
114
123
 
115
124
  class AccountReconciliationLineModelViewSet(viewsets.ModelViewSet):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wbportfolio
3
- Version: 1.50.10
3
+ Version: 1.50.11
4
4
  Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
5
5
  License-File: LICENSE
6
6
  Requires-Dist: cryptography==3.4.*
@@ -269,7 +269,7 @@ wbportfolio/models/mixins/instruments.py,sha256=SgBreTpa_X3uyCWo7t8B0VaTtl49IjmB
269
269
  wbportfolio/models/mixins/liquidity_stress_test.py,sha256=whkzjtbOyl_ncNyaQBORb_Z_rDgcvfdTYPgqPolu7dA,58865
270
270
  wbportfolio/models/reconciliations/__init__.py,sha256=MXH5fZIPGDRBgJkO6wVu_NLRs8fkP1im7G6d-h36lQY,127
271
271
  wbportfolio/models/reconciliations/account_reconciliation_lines.py,sha256=QP6M7hMcyFbuXBa55Y-azui6Dl_WgbzMntEqWzQkbfM,7394
272
- wbportfolio/models/reconciliations/account_reconciliations.py,sha256=_teOTNePxua9C894auy8CvdOFsmUnQiOM2_TZAHvzY4,3955
272
+ wbportfolio/models/reconciliations/account_reconciliations.py,sha256=rofSxetFfEJov6mPyoTvGxELA16HILyJZtQvm_kwYU0,4405
273
273
  wbportfolio/models/reconciliations/reconciliations.py,sha256=kF-BNhUoT4TCn1RIgPSkdEk1iX4NQeZlGGFd_ZulAZU,686
274
274
  wbportfolio/models/transactions/__init__.py,sha256=R-4fHylrUf3773kGSEt09vtYj3LUlia5yf7rxHXjvHA,295
275
275
  wbportfolio/models/transactions/claim.py,sha256=XUSephKt-VkILe2i-Sd9aoVxB-50PJANCPIDLa_dKl4,25872
@@ -401,7 +401,7 @@ wbportfolio/tests/viewsets/transactions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5J
401
401
  wbportfolio/tests/viewsets/transactions/test_claims.py,sha256=QEZfMAW07dyoZ63t2umSwGOqvaTULfYfbN_F4ZoSAcw,6368
402
402
  wbportfolio/viewsets/__init__.py,sha256=3kUaQ66ybvROwejd3bEcSt4XKzfOlPDaeoStMvlz7qY,2294
403
403
  wbportfolio/viewsets/adjustments.py,sha256=5hWCjxSgUIsrPOmJKoDYK3gywdMTI0aYDorEj1FXRVc,1429
404
- wbportfolio/viewsets/assets.py,sha256=FgJhBK13tAkrDyTiWsgnIT0Oq39mlvJTQSq1ztopQhY,24172
404
+ wbportfolio/viewsets/assets.py,sha256=Gf5QKDM7QR9MC8GJhMNzaY7NzeKV_yOQw0wktKPEc9o,24661
405
405
  wbportfolio/viewsets/assets_and_net_new_money_progression.py,sha256=Jl4vEQP4N2OFL5IGBXoKcj-0qaPviU0I8npvQLw4Io0,4464
406
406
  wbportfolio/viewsets/custodians.py,sha256=CTFqkqVP1R3AV7lhdvcdICxB5DfwDYCyikNSI5kbYEo,2322
407
407
  wbportfolio/viewsets/esg.py,sha256=27MxxdXQH3Cq_1UEYmcrF7htUOg6i81fUpbVQXAAKJI,6985
@@ -415,7 +415,7 @@ wbportfolio/viewsets/positions.py,sha256=2rzFHB_SI09rXC_EYi58G_eqvzONbk8z61JDkkj
415
415
  wbportfolio/viewsets/product_groups.py,sha256=YvmuXPPy98K1J_rz6YPsx9gNK-tCS2P-wc1uRYgfyo0,2399
416
416
  wbportfolio/viewsets/product_performance.py,sha256=dRfRgifjGS1RgZSu9uJRM0SmB7eLnNUkPuqARMO4gyo,28371
417
417
  wbportfolio/viewsets/products.py,sha256=1KXUDXdNmBFYjQcvJkwUCnjIOKZT0cAk_XTihMKRWvw,20459
418
- wbportfolio/viewsets/reconciliations.py,sha256=nRWWfrMqZAXmXB1ZG3coUHjYEiZNblobO5u3zsXWono,7037
418
+ wbportfolio/viewsets/reconciliations.py,sha256=tRS7UBDtMn-07uA9QqYvnCtp_mZGVeULF2OJMfHJPZk,7357
419
419
  wbportfolio/viewsets/registers.py,sha256=eOuEhW2McHsOapCKue7M4eazrJnVpCBVxImpFccq0z0,2401
420
420
  wbportfolio/viewsets/roles.py,sha256=vnzS1mlJMZS3GObrss6SfXOr3KRb-OHB1s4Msvtn7xQ,1556
421
421
  wbportfolio/viewsets/signals.py,sha256=URxNz-7tKNBgvaFIE3FItfao3Md0dKQN_eVFwxxiErk,2125
@@ -522,7 +522,7 @@ wbportfolio/viewsets/transactions/rebalancing.py,sha256=6rIrdK0rtKL1afJ-tYfAGdQV
522
522
  wbportfolio/viewsets/transactions/trade_proposals.py,sha256=iQpC_Thbj56SmM05vPRsF1JZguGBDaTUH3I-_iCHCV0,5958
523
523
  wbportfolio/viewsets/transactions/trades.py,sha256=-yJ4j8NJTu2VWyhCq5BXGNND_925Ietoxx9k07SLVh0,21634
524
524
  wbportfolio/viewsets/transactions/transactions.py,sha256=ixDp-nsNA8t_A06rBCT19hOMJHy0iRmdz1XKdV1OwAs,4450
525
- wbportfolio-1.50.10.dist-info/METADATA,sha256=e_s5BwIt2n97gDO321AtrrM38advbJ1Q18XHUInpP8w,703
526
- wbportfolio-1.50.10.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
527
- wbportfolio-1.50.10.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
528
- wbportfolio-1.50.10.dist-info/RECORD,,
525
+ wbportfolio-1.50.11.dist-info/METADATA,sha256=-P0DH8eaypNkb_aIxSByI1N2TdeWYx9zZZXZ5QzGl84,703
526
+ wbportfolio-1.50.11.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
527
+ wbportfolio-1.50.11.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
528
+ wbportfolio-1.50.11.dist-info/RECORD,,