wbcommission 2.2.1__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 wbcommission might be problematic. Click here for more details.

Files changed (76) hide show
  1. wbcommission/__init__.py +1 -0
  2. wbcommission/admin/__init__.py +4 -0
  3. wbcommission/admin/accounts.py +22 -0
  4. wbcommission/admin/commission.py +85 -0
  5. wbcommission/admin/rebate.py +7 -0
  6. wbcommission/analytics/__init__.py +0 -0
  7. wbcommission/analytics/marginality.py +181 -0
  8. wbcommission/apps.py +5 -0
  9. wbcommission/dynamic_preferences_registry.py +0 -0
  10. wbcommission/factories/__init__.py +9 -0
  11. wbcommission/factories/commission.py +100 -0
  12. wbcommission/factories/rebate.py +16 -0
  13. wbcommission/filters/__init__.py +7 -0
  14. wbcommission/filters/rebate.py +187 -0
  15. wbcommission/filters/signals.py +44 -0
  16. wbcommission/generators/__init__.py +2 -0
  17. wbcommission/generators/rebate_generator.py +93 -0
  18. wbcommission/migrations/0001_initial.py +299 -0
  19. wbcommission/migrations/0002_commissionrule_remove_accountcustomer_account_and_more.py +395 -0
  20. wbcommission/migrations/0003_alter_commission_account.py +24 -0
  21. wbcommission/migrations/0004_rebate_audit_log.py +19 -0
  22. wbcommission/migrations/0005_alter_rebate_audit_log.py +20 -0
  23. wbcommission/migrations/0006_commissionrule_consider_zero_percent_for_exclusion.py +21 -0
  24. wbcommission/migrations/0007_remove_commission_unique_crm_recipient_account_and_more.py +50 -0
  25. wbcommission/migrations/0008_alter_commission_options_alter_commission_order.py +26 -0
  26. wbcommission/migrations/__init__.py +0 -0
  27. wbcommission/models/__init__.py +9 -0
  28. wbcommission/models/account_service.py +217 -0
  29. wbcommission/models/commission.py +679 -0
  30. wbcommission/models/rebate.py +319 -0
  31. wbcommission/models/signals.py +45 -0
  32. wbcommission/permissions.py +6 -0
  33. wbcommission/reports/__init__.py +0 -0
  34. wbcommission/reports/audit_report.py +51 -0
  35. wbcommission/reports/customer_report.py +299 -0
  36. wbcommission/reports/utils.py +30 -0
  37. wbcommission/serializers/__init__.py +3 -0
  38. wbcommission/serializers/commissions.py +26 -0
  39. wbcommission/serializers/rebate.py +87 -0
  40. wbcommission/serializers/signals.py +27 -0
  41. wbcommission/tests/__init__.py +0 -0
  42. wbcommission/tests/analytics/__init__.py +0 -0
  43. wbcommission/tests/analytics/test_marginality.py +253 -0
  44. wbcommission/tests/conftest.py +89 -0
  45. wbcommission/tests/models/__init__.py +0 -0
  46. wbcommission/tests/models/mixins.py +22 -0
  47. wbcommission/tests/models/test_account_service.py +293 -0
  48. wbcommission/tests/models/test_commission.py +587 -0
  49. wbcommission/tests/models/test_rebate.py +136 -0
  50. wbcommission/tests/signals.py +0 -0
  51. wbcommission/tests/test_permissions.py +66 -0
  52. wbcommission/tests/viewsets/__init__.py +0 -0
  53. wbcommission/tests/viewsets/test_rebate.py +76 -0
  54. wbcommission/urls.py +42 -0
  55. wbcommission/viewsets/__init__.py +7 -0
  56. wbcommission/viewsets/buttons/__init__.py +2 -0
  57. wbcommission/viewsets/buttons/rebate.py +46 -0
  58. wbcommission/viewsets/buttons/signals.py +53 -0
  59. wbcommission/viewsets/commissions.py +21 -0
  60. wbcommission/viewsets/display/__init__.py +5 -0
  61. wbcommission/viewsets/display/commissions.py +21 -0
  62. wbcommission/viewsets/display/rebate.py +117 -0
  63. wbcommission/viewsets/endpoints/__init__.py +4 -0
  64. wbcommission/viewsets/endpoints/commissions.py +0 -0
  65. wbcommission/viewsets/endpoints/rebate.py +21 -0
  66. wbcommission/viewsets/menu/__init__.py +1 -0
  67. wbcommission/viewsets/menu/commissions.py +0 -0
  68. wbcommission/viewsets/menu/rebate.py +13 -0
  69. wbcommission/viewsets/mixins.py +39 -0
  70. wbcommission/viewsets/rebate.py +481 -0
  71. wbcommission/viewsets/titles/__init__.py +1 -0
  72. wbcommission/viewsets/titles/commissions.py +0 -0
  73. wbcommission/viewsets/titles/rebate.py +11 -0
  74. wbcommission-2.2.1.dist-info/METADATA +11 -0
  75. wbcommission-2.2.1.dist-info/RECORD +76 -0
  76. wbcommission-2.2.1.dist-info/WHEEL +5 -0
@@ -0,0 +1,299 @@
1
+ from datetime import date
2
+ from decimal import Decimal
3
+ from io import BytesIO
4
+
5
+ import xlsxwriter
6
+ from celery import shared_task
7
+ from django.db.models import Case, F, Sum, When
8
+ from wbcommission.models import CommissionType, Rebate
9
+ from wbcore.contrib.authentication.models import User
10
+ from wbcore.contrib.currency.models import CurrencyFXRates
11
+ from wbcore.contrib.directory.models import Entry
12
+ from wbcrm.models.accounts import (
13
+ Account,
14
+ AccountRole,
15
+ AccountRoleType,
16
+ AccountRoleValidity,
17
+ )
18
+ from wbfdm.models import InstrumentPrice
19
+ from wbportfolio.models.transactions.claim import Claim
20
+ from xlsxwriter.utility import xl_rowcol_to_cell
21
+
22
+ from .utils import create_report_and_send
23
+
24
+ AccountCustomer = None
25
+
26
+
27
+ @shared_task(queue="commission")
28
+ def create_customer_report_and_send_as_task(user_id: int, recipient_id: int, start_date: date, end_date: date):
29
+ user = User.objects.get(id=user_id)
30
+ recipient = Entry.objects.get(id=recipient_id)
31
+ create_report_and_send(user, recipient, start_date, end_date, create_report)
32
+
33
+
34
+ def create_report(user, customer, start_date, end_date):
35
+ output = BytesIO()
36
+ workbook = xlsxwriter.Workbook(output, {"in_memory": True})
37
+
38
+ base_format = workbook.add_format({"font_name": "Liberation Sans", "font_size": 10})
39
+ bold_format = workbook.add_format({"font_name": "Liberation Sans", "font_size": 10, "bold": True})
40
+ decimal_format = workbook.add_format({"font_name": "Liberation Sans", "font_size": 10, "num_format": "#,##.00"})
41
+ bold_decimal_format = workbook.add_format(
42
+ {"font_name": "Liberation Sans", "font_size": 10, "num_format": "#,##.00", "bold": True}
43
+ )
44
+ percent_format = workbook.add_format({"font_name": "Liberation Sans", "font_size": 10, "num_format": "#,##.00 %"})
45
+ bold_percent_format = workbook.add_format(
46
+ {"font_name": "Liberation Sans", "font_size": 10, "num_format": "#,##.00 %", "bold": True}
47
+ )
48
+
49
+ # HERE STARTS THE FIRST WORKSHEET
50
+ worksheet_products = workbook.add_worksheet(f"Products ({end_date:%d.%m.%Y})")
51
+
52
+ worksheet_products.write_string(0, 0, "Product", bold_format)
53
+ worksheet_products.write_string(0, 1, "Currency", bold_format)
54
+ worksheet_products.write_string(0, 2, "Price", bold_format)
55
+ worksheet_products.write_string(0, 3, "Price USD", bold_format)
56
+ worksheet_products.write_string(0, 4, "Direct Assets", bold_format)
57
+ worksheet_products.write_string(0, 5, "Direct Assets USD", bold_format)
58
+ worksheet_products.write_string(0, 6, "Indirect Assets", bold_format)
59
+ worksheet_products.write_string(0, 7, "Indirect Assets USD", bold_format)
60
+ worksheet_products.write_string(0, 8, "Total Assets USD", bold_format)
61
+
62
+ worksheet_products.write_formula(1, 5, "=SUM(F4:F99999)", bold_decimal_format)
63
+ worksheet_products.write_formula(1, 7, "=SUM(H4:H99999)", bold_decimal_format)
64
+ worksheet_products.write_formula(1, 8, "=SUM(I4:I99999)", bold_decimal_format)
65
+
66
+ fx_rates = CurrencyFXRates.get_fx_rates_subquery(end_date)
67
+ customer_accounts = Account.get_accounts_for_customer(customer)
68
+ valid_customer_roles = (
69
+ AccountRole.objects.filter(entry=customer)
70
+ .annotate(is_currently_valid=AccountRoleValidity.get_role_validity_subquery(date.today()))
71
+ .filter(is_currently_valid=True)
72
+ )
73
+ account_types = AccountRoleType.objects.filter(id__in=valid_customer_roles.values("role_type"))
74
+
75
+ user_claims = Claim.objects.filter_for_customer(customer, include_related_roles=True).filter_for_user(
76
+ user, validity_date=date.today()
77
+ )
78
+ products = (
79
+ user_claims.filter(
80
+ date__lte=end_date,
81
+ status=Claim.Status.APPROVED,
82
+ )
83
+ .annotate(
84
+ owner_asset_shares=Case(When(account__in=customer_accounts, then=F("shares")), default=Decimal(0)),
85
+ **{
86
+ f"{account_type.key}_assets_shares": Case(
87
+ When(
88
+ account__in=valid_customer_roles.filter(role_type=account_type).values("account"),
89
+ then=F("shares"),
90
+ ),
91
+ default=Decimal(0),
92
+ )
93
+ for account_type in account_types
94
+ },
95
+ )
96
+ .values("product")
97
+ .annotate(
98
+ price=InstrumentPrice.subquery_closest_value(
99
+ "net_value", val_date=end_date, instrument_pk_name="product__pk"
100
+ ),
101
+ product_id=F("product_id"),
102
+ title=F("product__name"),
103
+ currency=F("product__currency__symbol"),
104
+ sum_shares=Sum("shares"),
105
+ fx_rate=fx_rates,
106
+ sum_owner_assets_shares=Sum("owner_asset_shares"),
107
+ **{
108
+ f"sum_{account_type.key}_assets_shares": Sum(f"{account_type.key}_assets_shares")
109
+ for account_type in account_types
110
+ },
111
+ )
112
+ .order_by("title")
113
+ )
114
+ for row, product in enumerate(products, start=3):
115
+ product_cell = xl_rowcol_to_cell(row, 0)
116
+ currency_cell = xl_rowcol_to_cell(row, 1)
117
+ price_cell = xl_rowcol_to_cell(row, 2)
118
+ price_usd_cell = xl_rowcol_to_cell(row, 3)
119
+ owner_assets_cell = xl_rowcol_to_cell(row, 4)
120
+ owner_assets_usd_cell = xl_rowcol_to_cell(row, 5)
121
+ account_role_cells = dict()
122
+ account_role_cells_usd = dict()
123
+ index = 6
124
+ for account_type in account_types:
125
+ account_role_cells[account_type.key] = xl_rowcol_to_cell(row, index)
126
+ account_role_cells_usd[account_type.key] = xl_rowcol_to_cell(row, index + 1)
127
+ index += 2
128
+ total_assets_usd_cell = xl_rowcol_to_cell(row, index)
129
+
130
+ worksheet_products.write_string(product_cell, product["title"], base_format)
131
+ worksheet_products.write_string(currency_cell, product["currency"], base_format)
132
+ worksheet_products.write_number(price_cell, product["price"], decimal_format)
133
+ worksheet_products.write_formula(price_usd_cell, f"{price_cell} * {product['fx_rate']}", decimal_format)
134
+
135
+ worksheet_products.write_formula(
136
+ owner_assets_cell, f"{product['sum_owner_assets_shares']} * {price_cell}", decimal_format
137
+ )
138
+ worksheet_products.write_formula(
139
+ owner_assets_usd_cell, f"{owner_assets_cell} * {product['fx_rate']}", decimal_format
140
+ )
141
+
142
+ for account_type in account_types:
143
+ worksheet_products.write_formula(
144
+ account_role_cells[account_type.key],
145
+ f"{product[f'sum_{account_type.key}_assets_shares']} * {price_cell}",
146
+ decimal_format,
147
+ )
148
+ worksheet_products.write_formula(
149
+ account_role_cells_usd[account_type.key],
150
+ f"{account_role_cells[account_type.key]} * {product['fx_rate']}",
151
+ decimal_format,
152
+ )
153
+ worksheet_products.write_formula(
154
+ total_assets_usd_cell,
155
+ " + ".join([owner_assets_usd_cell] + list(account_role_cells_usd.values())),
156
+ decimal_format,
157
+ )
158
+
159
+ # HERE STARTS THE SECOND WORKSHEET
160
+ worksheet_trade_performance = workbook.add_worksheet(f"Trades ({end_date:%d.%m.%Y})")
161
+
162
+ worksheet_trade_performance.write_string(0, 0, "Trade Date", bold_format)
163
+ worksheet_trade_performance.write_string(0, 1, "Shares", bold_format)
164
+ worksheet_trade_performance.write_string(0, 2, "Bank", bold_format)
165
+ worksheet_trade_performance.write_string(0, 3, "Root Account", bold_format)
166
+ worksheet_trade_performance.write_string(0, 4, "Account", bold_format)
167
+ worksheet_trade_performance.write_string(0, 5, "Product", bold_format)
168
+ worksheet_trade_performance.write_string(0, 6, "Price (Trade Date)", bold_format)
169
+ worksheet_trade_performance.write_string(0, 7, "Net Value (Trade Date)", bold_format)
170
+ worksheet_trade_performance.write_string(0, 8, "Net Value (Trade Date) USD", bold_format)
171
+ worksheet_trade_performance.write_string(0, 9, f"Price ({end_date:%d.%m.%Y})", bold_format)
172
+ worksheet_trade_performance.write_string(0, 10, f"Net Value ({end_date:%d.%m.%Y})", bold_format)
173
+ worksheet_trade_performance.write_string(0, 11, f"Net Value ({end_date:%d.%m.%Y}) USD", bold_format)
174
+ worksheet_trade_performance.write_string(0, 12, "Performance", bold_format)
175
+
176
+ worksheet_trade_performance.write_formula(1, 8, "=SUM(I4:I99999)", bold_decimal_format)
177
+ worksheet_trade_performance.write_formula(1, 11, "=SUM(L4:L99999)", bold_decimal_format)
178
+ worksheet_trade_performance.write_formula(1, 12, "=(L2/I2)-1", bold_percent_format)
179
+
180
+ fx_rates_date = CurrencyFXRates.get_fx_rates_subquery("date")
181
+
182
+ fx_rates_end = CurrencyFXRates.get_fx_rates_subquery(end_date)
183
+
184
+ claims = (
185
+ user_claims.filter(
186
+ date__lte=end_date,
187
+ status=Claim.Status.APPROVED,
188
+ )
189
+ .annotate(
190
+ price_date=InstrumentPrice.subquery_closest_value("net_value", instrument_pk_name="product__pk"),
191
+ price_end=InstrumentPrice.subquery_closest_value(
192
+ "net_value", val_date=end_date, instrument_pk_name="product__pk"
193
+ ),
194
+ fx_rates_date=fx_rates_date,
195
+ fx_rates_end=fx_rates_end,
196
+ )
197
+ .order_by("date")
198
+ ).select_related("product", "account")
199
+
200
+ for row, claim in enumerate(claims, start=3):
201
+ trade_date_cell = xl_rowcol_to_cell(row, 0)
202
+ shares_cell = xl_rowcol_to_cell(row, 1)
203
+ bank_cell = xl_rowcol_to_cell(row, 2)
204
+ root_account_cell = xl_rowcol_to_cell(row, 3)
205
+ account_cell = xl_rowcol_to_cell(row, 4)
206
+ product_cell = xl_rowcol_to_cell(row, 5)
207
+ price_trade_cell = xl_rowcol_to_cell(row, 6)
208
+ net_value_trade_cell = xl_rowcol_to_cell(row, 7)
209
+ net_value_usd_trade_cell = xl_rowcol_to_cell(row, 8)
210
+ price_end_cell = xl_rowcol_to_cell(row, 9)
211
+ net_value_end_cell = xl_rowcol_to_cell(row, 10)
212
+ net_value_usd_end_cell = xl_rowcol_to_cell(row, 11)
213
+ performance_cell = xl_rowcol_to_cell(row, 12)
214
+
215
+ worksheet_trade_performance.write_string(trade_date_cell, f"{claim.date:%d.%m.%Y}", base_format)
216
+ worksheet_trade_performance.write_number(shares_cell, claim.shares, decimal_format)
217
+ worksheet_trade_performance.write_string(bank_cell, claim.bank, base_format)
218
+ worksheet_trade_performance.write_string(root_account_cell, claim.account.get_root().title, base_format)
219
+ worksheet_trade_performance.write_string(account_cell, str(claim.account), base_format)
220
+ worksheet_trade_performance.write_string(product_cell, claim.product.title, base_format)
221
+
222
+ worksheet_trade_performance.write_number(
223
+ price_trade_cell, claim.price_date or claim.product.share_price, decimal_format
224
+ )
225
+ worksheet_trade_performance.write_formula(
226
+ net_value_trade_cell, f"={shares_cell}*{price_trade_cell}", decimal_format
227
+ )
228
+ worksheet_trade_performance.write_formula(
229
+ net_value_usd_trade_cell, f"={net_value_trade_cell}*{claim.fx_rates_date}", decimal_format
230
+ )
231
+
232
+ worksheet_trade_performance.write_number(price_end_cell, claim.price_end, decimal_format)
233
+ worksheet_trade_performance.write_formula(
234
+ net_value_end_cell, f"={shares_cell}*{price_end_cell}", decimal_format
235
+ )
236
+ worksheet_trade_performance.write_formula(
237
+ net_value_usd_end_cell, f"={net_value_end_cell}*{claim.fx_rates_end}", decimal_format
238
+ )
239
+
240
+ worksheet_trade_performance.write_formula(
241
+ performance_cell, f"=({net_value_usd_end_cell}/{net_value_usd_trade_cell})-1", percent_format
242
+ )
243
+
244
+ # HERE STARTS THE THIRD WORKSHEET
245
+ worksheet_rebates = workbook.add_worksheet(f"Rebates ({start_date:%d.%m.%Y}-{end_date:%d.%m.%Y})")
246
+
247
+ worksheet_rebates.write_string(0, 0, "Date", bold_format)
248
+ worksheet_rebates.write_string(0, 1, "Product", bold_format)
249
+ worksheet_rebates.write_string(0, 2, "Account", bold_format)
250
+ for index, commission_type in enumerate(CommissionType.objects.all()):
251
+ worksheet_rebates.write_string(0, index + 3, f"{commission_type.name.title()} Fees", bold_format)
252
+ worksheet_rebates.write_formula(
253
+ 1, index + 3, f"=SUM({chr(ord('@') + (index + 3))}3]:E99999)", bold_decimal_format
254
+ )
255
+
256
+ rebates_for_user = Rebate.objects.filter_for_user(user, validity_date=date.today())
257
+ rebates = (
258
+ rebates_for_user.filter(recipient=customer, date__gte=start_date, date__lte=end_date)
259
+ .select_related("account", "product")
260
+ .annotate(
261
+ **{
262
+ f"{commission_type.key}__value": Case(
263
+ When(commission_type=commission_type, then=F("value")), default=Decimal(0)
264
+ )
265
+ for commission_type in CommissionType.objects.all()
266
+ }
267
+ )
268
+ .values("date", "account", "product")
269
+ .annotate(
270
+ product_title=F("product__name"),
271
+ account_id=F("account__id"),
272
+ account_title=F("account__computed_str"),
273
+ **{
274
+ f"sum_{commission_type.key}_value": Sum(f"{commission_type.key}__value")
275
+ for commission_type in CommissionType.objects.all()
276
+ },
277
+ )
278
+ .order_by("date", "product", "account_id")
279
+ )
280
+
281
+ for row, rebate in enumerate(rebates, start=4):
282
+ date_cell = xl_rowcol_to_cell(row, 0)
283
+ product_cell = xl_rowcol_to_cell(row, 1)
284
+ account_cell = xl_rowcol_to_cell(row, 2)
285
+
286
+ worksheet_rebates.write_string(date_cell, f"{rebate['date']:%d.%m.%Y}", base_format)
287
+ worksheet_rebates.write_string(product_cell, rebate["product_title"], base_format)
288
+ worksheet_rebates.write_string(account_cell, rebate["account_title"], base_format)
289
+ for index, commission_type in enumerate(CommissionType.objects.all()):
290
+ cell = xl_rowcol_to_cell(row, 3 + index)
291
+ worksheet_rebates.write_number(cell, rebate[f"sum_{commission_type.key}_value"], decimal_format)
292
+
293
+ workbook.close()
294
+ output.seek(0)
295
+ return (
296
+ output,
297
+ "customer_report_{}_{}_{}.xlsx".format(customer.computed_str, start_date, end_date),
298
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
299
+ )
@@ -0,0 +1,30 @@
1
+ from contextlib import suppress
2
+ from datetime import date
3
+
4
+ from django.core.mail import EmailMultiAlternatives
5
+ from django.template.loader import get_template
6
+ from wbcore.contrib.authentication.models import User
7
+ from wbcore.contrib.directory.models import Entry
8
+ from wbcore.utils.html import convert_html2text
9
+
10
+ AccountCustomer = None
11
+
12
+
13
+ def create_report_and_send(user: User, customer: Entry, start_date: date, end_date: date, report_callback):
14
+ with suppress(ValueError):
15
+ report_stream, file_name, file_extension = report_callback(user, customer, start_date, end_date)
16
+
17
+ html = get_template("portfolio/email/customer_report.html")
18
+
19
+ context = {"profile": user, "customer": customer}
20
+ html_content = html.render(context)
21
+
22
+ msg = EmailMultiAlternatives("Report", body=convert_html2text(html_content), to=[user.email])
23
+ msg.attach_alternative(html_content, "text/html")
24
+ report_stream.seek(0)
25
+ msg.attach(
26
+ file_name,
27
+ report_stream.read(),
28
+ file_extension,
29
+ )
30
+ msg.send()
@@ -0,0 +1,3 @@
1
+ from .rebate import RebateModelSerializer, RebateProductMarginalitySerializer
2
+ from .commissions import CommissionTypeRepresentationSerializer, CommissionTypeModelSerializer
3
+ from .signals import *
@@ -0,0 +1,26 @@
1
+ from wbcommission.models import CommissionType
2
+ from wbcore import serializers as wb_serializers
3
+
4
+
5
+ class CommissionTypeRepresentationSerializer(wb_serializers.RepresentationSerializer):
6
+ _detail = wb_serializers.HyperlinkField(reverse_name="wbcommission:commissiontype-detail")
7
+
8
+ class Meta:
9
+ model = CommissionType
10
+ fields = (
11
+ "id",
12
+ "name",
13
+ "key",
14
+ "_detail",
15
+ )
16
+
17
+
18
+ class CommissionTypeModelSerializer(wb_serializers.ModelSerializer):
19
+ class Meta:
20
+ model = CommissionType
21
+ read_only_fields = ("key",)
22
+ fields = (
23
+ "id",
24
+ "name",
25
+ "key",
26
+ )
@@ -0,0 +1,87 @@
1
+ from wbcommission.models import Rebate
2
+ from wbcore import serializers as wb_serializers
3
+
4
+
5
+ class RebateModelSerializer(wb_serializers.ModelSerializer):
6
+ id = wb_serializers.PrimaryKeyField()
7
+ value_usd = wb_serializers.FloatField(read_only=True)
8
+
9
+ class Meta:
10
+ model = Rebate
11
+ fields = ("id", "value_usd")
12
+
13
+
14
+ class RebateProductMarginalitySerializer(wb_serializers.Serializer):
15
+ id = wb_serializers.PrimaryKeyField()
16
+ title = wb_serializers.CharField(read_only=True)
17
+ currency_symbol = wb_serializers.CharField(read_only=True)
18
+ sum_management_fees = wb_serializers.DecimalField(max_digits=16, decimal_places=2, label="Management Fees")
19
+ sum_performance_fees = wb_serializers.DecimalField(max_digits=16, decimal_places=2, label="Management Rebates")
20
+ sum_crystalized_performance_fees = wb_serializers.DecimalField(
21
+ max_digits=16, decimal_places=2, label="Crystalized Performance Fees"
22
+ )
23
+ sum_management_rebates = wb_serializers.DecimalField(max_digits=16, decimal_places=2, label="Performance Fees")
24
+ sum_performance_rebates = wb_serializers.DecimalField(max_digits=16, decimal_places=2, label="Performance Rebates")
25
+ marginality_management = wb_serializers.DecimalField(
26
+ max_digits=16, decimal_places=2, label="Marginality Management"
27
+ )
28
+ marginality_performance = wb_serializers.DecimalField(
29
+ max_digits=16, decimal_places=2, label="Marginality Performance"
30
+ )
31
+
32
+ total_fees = wb_serializers.DecimalField(max_digits=16, decimal_places=2, label="Total Fees")
33
+ total_rebates = wb_serializers.DecimalField(max_digits=16, decimal_places=2, label="Total Rebates")
34
+ total_marginality = wb_serializers.DecimalField(max_digits=16, decimal_places=2, label="Total Marginality")
35
+
36
+ total_fees_usd = wb_serializers.DecimalField(max_digits=16, decimal_places=2, label="Total Fees (USD)")
37
+ total_rebates_usd = wb_serializers.DecimalField(max_digits=16, decimal_places=2, label="Total Rebates (USD)")
38
+ total_usd = wb_serializers.DecimalField(max_digits=16, decimal_places=2, label="Total Net (USD)")
39
+
40
+ class Meta:
41
+ percent_fields = [
42
+ "marginality_management",
43
+ "marginality_performance",
44
+ "total_marginality",
45
+ ]
46
+ decorators = {
47
+ "sum_management_fees": wb_serializers.decorator(
48
+ decorator_type="text", position="left", value="{{currency_symbol}}"
49
+ ),
50
+ "sum_performance_fees": wb_serializers.decorator(
51
+ decorator_type="text", position="left", value="{{currency_symbol}}"
52
+ ),
53
+ "sum_management_rebates": wb_serializers.decorator(
54
+ decorator_type="text", position="left", value="{{currency_symbol}}"
55
+ ),
56
+ "sum_performance_rebates": wb_serializers.decorator(
57
+ decorator_type="text", position="left", value="{{currency_symbol}}"
58
+ ),
59
+ "total_fees": wb_serializers.decorator(
60
+ decorator_type="text", position="left", value="{{currency_symbol}}"
61
+ ),
62
+ "total_rebates": wb_serializers.decorator(
63
+ decorator_type="text", position="left", value="{{currency_symbol}}"
64
+ ),
65
+ "total_fees_usd": wb_serializers.decorator(decorator_type="text", position="left", value="$"),
66
+ "total_rebates_usd": wb_serializers.decorator(decorator_type="text", position="left", value="$"),
67
+ }
68
+
69
+ fields = (
70
+ "id",
71
+ "title",
72
+ "currency_symbol",
73
+ "sum_management_fees",
74
+ "sum_performance_fees",
75
+ "sum_crystalized_performance_fees",
76
+ "sum_management_rebates",
77
+ "sum_performance_rebates",
78
+ "marginality_management",
79
+ "marginality_performance",
80
+ "total_fees",
81
+ "total_rebates",
82
+ "total_marginality",
83
+ "total_fees_usd",
84
+ "total_rebates_usd",
85
+ "total_usd",
86
+ )
87
+ read_only_fields = fields
@@ -0,0 +1,27 @@
1
+ from django.dispatch import receiver
2
+ from rest_framework.reverse import reverse
3
+ from wbcore.contrib.directory.serializers import (
4
+ CompanyModelSerializer,
5
+ EntryModelSerializer,
6
+ PersonModelSerializer,
7
+ )
8
+ from wbcore.filters.defaults import current_quarter_date_end, current_quarter_date_start
9
+ from wbcore.signals import add_instance_additional_resource
10
+
11
+
12
+ # register the rebate and generate report addition resources to the entry model serializers
13
+ @receiver(add_instance_additional_resource, sender=CompanyModelSerializer)
14
+ @receiver(add_instance_additional_resource, sender=PersonModelSerializer)
15
+ @receiver(add_instance_additional_resource, sender=EntryModelSerializer)
16
+ def commission_adding_additional_resource(sender, serializer, instance, request, user, **kwargs):
17
+ start = current_quarter_date_start()
18
+ end = current_quarter_date_end()
19
+ res = {
20
+ "rebates": f'{reverse("wbcommission:rebatetable-list", args=[], request=request)}?group_by=PRODUCT&recipient={instance.id}&date={start:%Y-%m-%d},{end:%Y-%m-%d}',
21
+ "generate_customer_commission_report": f'{reverse("wbcommission:rebate-customerreport", request=request)}?recipient_id={instance.id}',
22
+ }
23
+ if user.has_perm("wbcommission.administrate_commission"):
24
+ res[
25
+ "generate_audit_commission_report"
26
+ ] = f'{reverse("wbcommission:rebate-auditreport", request=request)}?recipient_id={instance.id}'
27
+ return res
File without changes
File without changes