wbportfolio 1.52.0__py2.py3-none-any.whl → 1.52.2__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 (86) 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 +26 -6
  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/__init__.py +1 -0
  57. wbportfolio/viewsets/configs/buttons/mixins.py +2 -2
  58. wbportfolio/viewsets/configs/buttons/trades.py +8 -0
  59. wbportfolio/viewsets/configs/display/__init__.py +2 -3
  60. wbportfolio/viewsets/configs/display/fees.py +3 -3
  61. wbportfolio/viewsets/configs/endpoints/__init__.py +3 -4
  62. wbportfolio/viewsets/configs/endpoints/fees.py +2 -2
  63. wbportfolio/viewsets/configs/menu/__init__.py +0 -1
  64. wbportfolio/viewsets/configs/titles/__init__.py +2 -3
  65. wbportfolio/viewsets/configs/titles/fees.py +4 -8
  66. wbportfolio/viewsets/mixins.py +5 -1
  67. wbportfolio/viewsets/products.py +6 -6
  68. wbportfolio/viewsets/transactions/__init__.py +2 -7
  69. wbportfolio/viewsets/transactions/fees.py +22 -22
  70. wbportfolio/viewsets/transactions/trade_proposals.py +1 -0
  71. wbportfolio/viewsets/transactions/trades.py +2 -0
  72. {wbportfolio-1.52.0.dist-info → wbportfolio-1.52.2.dist-info}/METADATA +1 -1
  73. {wbportfolio-1.52.0.dist-info → wbportfolio-1.52.2.dist-info}/RECORD +75 -84
  74. wbportfolio/admin/transactions/transactions.py +0 -38
  75. wbportfolio/factories/transactions.py +0 -22
  76. wbportfolio/filters/transactions/transactions.py +0 -99
  77. wbportfolio/models/transactions/expiry.py +0 -7
  78. wbportfolio/serializers/transactions/expiry.py +0 -18
  79. wbportfolio/serializers/transactions/transactions.py +0 -85
  80. wbportfolio/viewsets/configs/display/transactions.py +0 -55
  81. wbportfolio/viewsets/configs/endpoints/transactions.py +0 -14
  82. wbportfolio/viewsets/configs/menu/transactions.py +0 -9
  83. wbportfolio/viewsets/configs/titles/transactions.py +0 -9
  84. wbportfolio/viewsets/transactions/transactions.py +0 -122
  85. {wbportfolio-1.52.0.dist-info → wbportfolio-1.52.2.dist-info}/WHEEL +0 -0
  86. {wbportfolio-1.52.0.dist-info → wbportfolio-1.52.2.dist-info}/licenses/LICENSE +0 -0
@@ -51,8 +51,8 @@ class TradeImportHandler(ImportExportHandler):
51
51
  data["portfolio"] = trade_proposal.portfolio
52
52
  data["status"] = "DRAFT"
53
53
  else:
54
- if external_identifier2 := data.get("external_identifier2", None):
55
- data["external_identifier2"] = str(external_identifier2)
54
+ if external_id_alternative := data.get("external_id_alternative", None):
55
+ data["external_id_alternative"] = str(external_id_alternative)
56
56
  if transaction_date_str := data.get("transaction_date", None):
57
57
  data["transaction_date"] = datetime.strptime(transaction_date_str, "%Y-%m-%d").date()
58
58
  if value_date_str := data.get("value_date", None):
@@ -92,7 +92,6 @@ class TradeImportHandler(ImportExportHandler):
92
92
  def _create_instance(self, data: Dict[str, Any], **kwargs) -> models.Model:
93
93
  if "transaction_date" not in data: # we might get only book date and not transaction date
94
94
  data["transaction_date"] = data["book_date"]
95
-
96
95
  return self.model.objects.create(**data, import_source=self.import_source)
97
96
 
98
97
  def _get_instance(self, data: Dict[str, Any], history: Optional[models.QuerySet] = None, **kwargs) -> models.Model:
@@ -115,17 +114,16 @@ class TradeImportHandler(ImportExportHandler):
115
114
  )
116
115
  if "shares" in data:
117
116
  queryset = queryset.filter(shares=data["shares"])
118
-
119
117
  if _id := data.get("id", None):
120
118
  self.import_source.log += f"ID {_id} provided -> Load CustomerTrade"
121
119
  return self.model.objects.get(id=_id)
122
120
  # We need to check for external identifiers
123
121
  if external_id := data.get("external_id"):
124
122
  self.import_source.log += f"\nExternal Identifier used: {external_id}"
125
- queryset = queryset.filter(external_id=external_id)
126
- if queryset.count() == 1:
123
+ external_id_queryset = queryset.filter(external_id=external_id)
124
+ if external_id_queryset.count() == 1:
127
125
  self.import_source.log += f"External ID {external_id} provided -> Load CustomerTrade"
128
- return queryset.first()
126
+ return external_id_queryset.first()
129
127
 
130
128
  if portfolio := data.get("portfolio", None):
131
129
  queryset = queryset.filter(portfolio=portfolio)
@@ -34,8 +34,8 @@ def parse(import_source):
34
34
  isin = fee_data["ISIN"]
35
35
  fee_date = fee_data["Date"]
36
36
  base_data = {
37
- "linked_product": {"isin": isin},
38
- "transaction_date": fee_date.strftime("%Y-%m-%d"),
37
+ "product": {"isin": isin},
38
+ "fee_date": fee_date.strftime("%Y-%m-%d"),
39
39
  "calculated": False,
40
40
  }
41
41
  data.append(
@@ -1,4 +1,5 @@
1
1
  from contextlib import suppress
2
+ from io import BytesIO
2
3
 
3
4
  import pandas as pd
4
5
 
@@ -10,7 +11,7 @@ def parse(import_source):
10
11
  df = pd.DataFrame()
11
12
  try:
12
13
  df = pd.read_excel(
13
- import_source.file.read(),
14
+ BytesIO(import_source.file.read()),
14
15
  engine="openpyxl",
15
16
  index_col=1,
16
17
  sheet_name="TRANSACTION CONSOLIDATION",
@@ -25,7 +26,8 @@ def parse(import_source):
25
26
  with suppress(Product.DoesNotExist):
26
27
  product = Product.objects.get(isin=trade["AMC ISIN"])
27
28
  shares = (-1 * trade["TOTAL QUANTITY"]) / product.share_price
28
- price = trade["GROSS PRICE"] * product.share_price
29
+ price = trade["NET PRICE"] * product.share_price
30
+ price_gross = trade["GROSS PRICE"] * product.share_price
29
31
  portfolio = product.primary_portfolio
30
32
  data.append(
31
33
  {
@@ -38,10 +40,8 @@ def parse(import_source):
38
40
  "bank": "Leonteq Cash Transfer",
39
41
  "currency__key": product.currency.key,
40
42
  "price": price,
41
- "total_value": trade["NET AMOUNT"],
42
- "total_value_gross": trade["GROSS AMOUNT"],
43
+ "price_gross": price_gross,
43
44
  "currency_fx_rate": trade["BOOKING FX"],
44
- "total_value_fx_portfolio": trade["BOOKING NET AMOUNT"],
45
45
  }
46
46
  )
47
47
 
@@ -1,3 +1,5 @@
1
+ from io import BytesIO
2
+
1
3
  import pandas as pd
2
4
 
3
5
  from wbportfolio.models import Fees
@@ -8,7 +10,11 @@ def parse(import_source):
8
10
  df = pd.DataFrame()
9
11
  try:
10
12
  df = pd.read_excel(
11
- import_source.file.read(), engine="openpyxl", sheet_name="FEE_CONSOLIDATION", header=[0, 2], skiprows=1
13
+ BytesIO(import_source.file.read()),
14
+ engine="openpyxl",
15
+ sheet_name="FEE_CONSOLIDATION",
16
+ header=[0, 2],
17
+ skiprows=1,
12
18
  ).dropna(axis=1)
13
19
  except (ValueError, IndexError):
14
20
  pass
@@ -19,15 +25,13 @@ def parse(import_source):
19
25
 
20
26
  product_fees_df = product_fees_df.rename(
21
27
  columns={
22
- "TRADE DATE": "transaction_date",
28
+ "TRADE DATE": "fee_date",
23
29
  "INDEX SPONSOR FEE": "total_value",
24
30
  "BUSINESS EVENT": "transaction_subtype",
25
31
  }
26
32
  )
27
33
 
28
- product_fees_df.loc[:, "transaction_date"] = pd.to_datetime(
29
- product_fees_df.loc[:, "transaction_date"], dayfirst=True
30
- )
34
+ product_fees_df.loc[:, "fee_date"] = pd.to_datetime(product_fees_df.loc[:, "fee_date"], dayfirst=True)
31
35
 
32
36
  management_fees_eur = product_fees_df[
33
37
  product_fees_df.loc[:, "transaction_subtype"] == "Management Fee EUR"
@@ -50,8 +54,8 @@ def parse(import_source):
50
54
  product_fees_df = product_fees_df.where(pd.notnull(product_fees_df), None)
51
55
  for fees in product_fees_df.to_dict("records"):
52
56
  base_data = {
53
- "linked_product": {"isin": isin},
54
- "transaction_date": fees["transaction_date"].strftime("%Y-%m-%d"),
57
+ "product": {"isin": isin},
58
+ "fee_date": fees["fee_date"].strftime("%Y-%m-%d"),
55
59
  "calculated": False,
56
60
  }
57
61
 
@@ -24,11 +24,8 @@ _fields_map = {
24
24
  "TOTAL QUANTITY": "shares",
25
25
  "GROSS PRICE": "price_gross",
26
26
  "NET PRICE": "price",
27
- "total_value_gross": "total_value_gross",
28
27
  "currency_fx_rate": "currency_fx_rate",
29
28
  "NET AMOUNT": "total_value",
30
- "GROSS AMOUNT": "total_value_gross_fx_portfolio",
31
- "total_value_fx_portfolio": "total_value_fx_portfolio",
32
29
  "N°": "external_id",
33
30
  }
34
31
 
@@ -78,8 +75,6 @@ def parse(import_source):
78
75
  df["exchange"] = df["IDENTIFIER"].apply(lambda x: _get_exchange(x))
79
76
  df["currency_fx_rate"] = df["BOOKING FX"] * df["BASE CCY FX"]
80
77
 
81
- df["total_value_gross"] = df["total_value_gross_fx_portfolio"] / df["BOOKING FX"]
82
- df["total_value_fx_portfolio"] = df["total_value"] * df["currency_fx_rate"]
83
78
  df = df.drop(df.columns.difference(_fields_map.values()), axis=1)
84
79
  df["portfolio"] = product.primary_portfolio.id
85
80
 
@@ -37,8 +37,8 @@ def parse(import_source):
37
37
  management_fees = row[management_fees_column].value
38
38
 
39
39
  base_data = {
40
- "linked_product": {"isin": isin},
41
- "transaction_date": valuation_date.strftime("%Y-%m-%d"),
40
+ "product": {"isin": isin},
41
+ "fee_date": valuation_date.strftime("%Y-%m-%d"),
42
42
  "calculated": False,
43
43
  }
44
44
  if management_fees != 0:
@@ -10,10 +10,9 @@ COLUMN_MAP = {
10
10
  "Div Crncy": "currency__key",
11
11
  "Quantity": "shares",
12
12
  "Fx Rate": "currency_fx_rate",
13
- "Net Amount": "total_value_fx_portfolio",
14
13
  "Retro in%": "retrocession",
15
14
  "Gross Div": "price_gross",
16
- "Ex Div Date": "transaction_date",
15
+ "Ex Div Date": "ex_date",
17
16
  "Value Date": "value_date",
18
17
  }
19
18
 
@@ -29,25 +28,21 @@ def parse(import_source):
29
28
  lambda x: _get_exchange_from_ticker(x)
30
29
  )
31
30
  df["underlying_instrument__ticker"] = df["underlying_instrument__ticker"].apply(lambda x: _get_ticker(x))
32
- df["transaction_date"] = pd.to_datetime(df["transaction_date"], dayfirst=True).dt.strftime("%Y-%m-%d")
31
+ df["ex_date"] = pd.to_datetime(df["ex_date"], dayfirst=True).dt.strftime("%Y-%m-%d")
33
32
  df["value_date"] = pd.to_datetime(df["value_date"], dayfirst=True).dt.strftime("%Y-%m-%d")
34
33
  df = df[df["underlying_instrument__isin"].str.contains("([A-Z]{2})([A-Z0-9]{9})([0-9]{1})", regex=True)]
35
- float_columns = ["shares", "total_value_fx_portfolio", "price_gross", "currency_fx_rate", "retrocession"]
34
+ float_columns = ["shares", "price_gross", "currency_fx_rate", "retrocession"]
36
35
  for float_column in float_columns:
37
36
  df[float_column] = df[float_column].str.replace(" ", "").astype("float")
38
37
  df = df.drop(columns=df.columns.difference(COLUMN_MAP.values()))
39
38
 
40
39
  df["retrocession"] = df["retrocession"] / 100.0
41
- df["total_value"] = df["total_value_fx_portfolio"] / df["currency_fx_rate"]
42
- df["price"] = df["total_value"] / df["shares"] / df["retrocession"]
43
- df["total_value_gross"] = df["price_gross"] * df["shares"] * df["retrocession"]
44
- df["total_value_gross_fx_portfolio"] = df["total_value_gross"] * df["currency_fx_rate"]
45
40
  df["portfolio"] = [{"instrument_type": "product", **product_data}] * df.shape[0]
46
41
  df = df.replace([np.inf, -np.inf, np.nan], None)
47
42
  return {
48
43
  "data": df.to_dict("records"),
49
44
  "history": {
50
- "transaction_date": parts["valuation_date"].strftime("%Y-%m-%d"),
45
+ "value_date": parts["valuation_date"].strftime("%Y-%m-%d"),
51
46
  "product": product_data,
52
47
  },
53
48
  }
@@ -4,7 +4,7 @@ from pandas.tseries.offsets import BDay
4
4
  from .utils import file_name_parse_isin
5
5
 
6
6
  FIELD_MAP = {
7
- "Date": "transaction_date",
7
+ "Date": "fee_date",
8
8
  "Manag. Fees Natixis": "ISSUER",
9
9
  "Manag. Fees Client": "MANAGEMENT",
10
10
  "Perf fees amount": "PERFORMANCE",
@@ -21,30 +21,28 @@ def parse(import_source):
21
21
  df = pd.read_csv(import_source.file, encoding="utf-8", delimiter=";")
22
22
  df = df.rename(columns=FIELD_MAP)
23
23
  df = df.drop(columns=df.columns.difference(FIELD_MAP.values()))
24
- df["transaction_date"] = pd.to_datetime(df["transaction_date"], dayfirst=True)
24
+ df["fee_date"] = pd.to_datetime(df["fee_date"], dayfirst=True)
25
25
 
26
26
  # Switch the weeekend day fees to the next monday
27
- df["transaction_date"] = df["transaction_date"].apply(lambda x: x + BDay(1) if x.weekday() in [5, 6] else x)
27
+ df["fee_date"] = df["fee_date"].apply(lambda x: x + BDay(1) if x.weekday() in [5, 6] else x)
28
28
 
29
29
  # Ensure float columns are number
30
30
  for col in ["MANAGEMENT", "ISSUER", "PERFORMANCE"]:
31
31
  df[col] = df[col].astype("str").str.replace(" ", "").astype("float")
32
32
 
33
33
  # Groupby and sum similar fees (e.g. Monday)
34
- df = df.groupby("transaction_date").sum().reset_index()
34
+ df = df.groupby("fee_date").sum().reset_index()
35
35
  df = pd.melt(
36
36
  df,
37
- id_vars=["transaction_date"],
37
+ id_vars=["fee_date"],
38
38
  value_vars=["MANAGEMENT", "ISSUER", "PERFORMANCE"],
39
39
  var_name="transaction_subtype",
40
40
  value_name="total_value",
41
41
  )
42
42
  df = df[df["total_value"] != 0]
43
43
 
44
- df["linked_product"] = [product] * df.shape[0]
45
- df["transaction_date"] = df["transaction_date"].dt.strftime("%Y-%m-%d")
44
+ df["product"] = [product] * df.shape[0]
45
+ df["fee_date"] = df["fee_date"].dt.strftime("%Y-%m-%d")
46
46
  df["calculated"] = False
47
47
  df["total_value_gross"] = df["total_value"]
48
- df["total_value_fx_portfolio"] = df["total_value"]
49
- df["total_value_gross_fx_portfolio"] = df["total_value"]
50
48
  return {"data": df.to_dict("records")}
@@ -129,7 +129,7 @@ def parse(import_source):
129
129
  )
130
130
 
131
131
  df["bank"] = df["REGISTER_DEAL_NAME"]
132
- df["external_identifier2"] = df["NORDER"]
132
+ df["external_id_alternative"] = df["NORDER"]
133
133
  df["register__register_reference"] = df["REGISTER_ID1"]
134
134
  df["external_id"] = df.apply(assemble_transaction_reference, axis=1)
135
135
 
@@ -40,12 +40,12 @@ def parse(import_source):
40
40
  date = datetime.datetime.strptime(fee_data["NAV Date"], "%Y/%m/%d")
41
41
  data.append(
42
42
  {
43
- "linked_product": {
43
+ "product": {
44
44
  "parent__identifier": fee_data["Code"],
45
45
  "currency__key": fee_data["Local ccy"],
46
46
  "identifier": share_class,
47
47
  },
48
- "transaction_date": date.strftime("%Y-%m-%d"),
48
+ "fee_date": date.strftime("%Y-%m-%d"),
49
49
  "calculated": False,
50
50
  "transaction_subtype": Fees.Type.MANAGEMENT,
51
51
  "total_value": round(convert_string_to_number(fee_data.get("Fees - Local ccy", 0)), 6),
@@ -26,7 +26,7 @@ def parse(import_source):
26
26
  date = datetime.datetime.strptime(fee_data[0], "%m/%d/%Y")
27
27
  data.append(
28
28
  {
29
- "linked_product": {"isin": isin},
29
+ "product": {"isin": isin},
30
30
  "transaction_date": date.strftime("%Y-%m-%d"),
31
31
  "calculated": False,
32
32
  "transaction_subtype": Fees.Type.PERFORMANCE,
@@ -35,7 +35,7 @@ def parse(import_source):
35
35
  )
36
36
  data.append(
37
37
  {
38
- "linked_product": {"isin": isin},
38
+ "product": {"isin": isin},
39
39
  "transaction_date": date.strftime("%Y-%m-%d"),
40
40
  "calculated": False,
41
41
  "transaction_subtype": Fees.Type.PERFORMANCE_CRYSTALIZED,
@@ -17,7 +17,7 @@ def parse_transaction_reference(trans_ref: str) -> tuple[str, str, bool]:
17
17
 
18
18
 
19
19
  def assemble_transaction_reference(data: Dict[str, Any]) -> str:
20
- transaction_ref = data["external_identifier2"]
20
+ transaction_ref = data["external_id_alternative"]
21
21
  register_reference = data["register__register_reference"]
22
22
  if data.get("TRANSFER_REGISTER", None):
23
23
  register_reference = data["TRANSFER_REGISTER"]
@@ -29,7 +29,7 @@ def assemble_transaction_reference(data: Dict[str, Any]) -> str:
29
29
 
30
30
 
31
31
  def create_transaction_reference(customer_trade: "Trade") -> str:
32
- transaction_id = customer_trade.external_identifier2
32
+ transaction_id = customer_trade.external_id_alternative
33
33
  outlet_id = customer_trade.register.clearing_reference
34
34
  credit_debit = "C" if customer_trade.initial_shares > 0 else "D"
35
35
 
@@ -4,14 +4,14 @@ import pandas as pd
4
4
 
5
5
  from wbportfolio.models import Fees
6
6
 
7
- BASE_MAPPING = {"managementFee": "total_value", "performanceFee": "total_value", "date": "transaction_date"}
7
+ BASE_MAPPING = {"managementFee": "total_value", "performanceFee": "total_value", "date": "fee_date"}
8
8
 
9
9
 
10
10
  def parse(import_source):
11
11
  def _process_df(df, product_isin):
12
12
  df = df.rename(columns=BASE_MAPPING).dropna(how="all", axis=1)
13
13
  df = df.drop(columns=df.columns.difference(BASE_MAPPING.values()))
14
- df["linked_product"] = [{"isin": product_isin}] * df.shape[0]
14
+ df["product"] = [{"isin": product_isin}] * df.shape[0]
15
15
  return df
16
16
 
17
17
  content = json.load(import_source.file)
@@ -11,10 +11,9 @@ FIELD_MAP = {
11
11
  "Trade_Date": "book_date",
12
12
  "Value_Date": "value_date",
13
13
  "Price": "price",
14
- "Quantity": "total_value",
15
14
  "Currency": "currency__key",
16
15
  "Portfolio_Identifier": "underlying_instrument__identifier",
17
- "External_Reference": "external_identifier2",
16
+ "External_Reference": "external_id_alternative",
18
17
  "Booking_Comment": "comment",
19
18
  }
20
19
 
@@ -36,8 +35,8 @@ def parse(import_source):
36
35
  data = []
37
36
  if not df.empty:
38
37
  df = df.rename(columns=FIELD_MAP)
38
+ df["shares"] = df["Quantity"] / df["price"]
39
39
  df = df.drop(columns=df.columns.difference(FIELD_MAP.values()))
40
- df["shares"] = df["total_value"] / df["price"]
41
40
  df["transaction_date"] = pd.to_datetime(df["transaction_date"], dayfirst=True).dt.strftime("%Y-%m-%d")
42
41
  df["book_date"] = pd.to_datetime(df["book_date"], dayfirst=True).dt.strftime("%Y-%m-%d")
43
42
  df["value_date"] = pd.to_datetime(df["value_date"], dayfirst=True).dt.strftime("%Y-%m-%d")
@@ -8,7 +8,6 @@ from wbportfolio.models import Trade
8
8
 
9
9
  FIELD_MAP = {
10
10
  "Trade Date": "book_date",
11
- "Volume": "total_value",
12
11
  "Price": "price",
13
12
  "Qty": "shares",
14
13
  "Custodian": "bank",
@@ -11,7 +11,7 @@ FIELD_MAP = {
11
11
  "Value_Date": "value_date",
12
12
  "Quantity": "total_value",
13
13
  "Currency": "currency__key",
14
- "Portfolio_Identifier": "linked_product",
14
+ "Portfolio_Identifier": "product",
15
15
  "Booking_Comment": "comment",
16
16
  }
17
17
 
@@ -25,20 +25,20 @@ def parse(import_source):
25
25
  data = []
26
26
  if not df.empty:
27
27
  df = df.rename(columns=FIELD_MAP)
28
- df.linked_product = df.linked_product.apply(lambda x: Product.objects.filter(identifier=x).first())
28
+ df["product"] = df["product"].apply(lambda x: Product.objects.filter(identifier=x).first())
29
29
  df["transaction_date"] = pd.to_datetime(df["transaction_date"], dayfirst=True)
30
30
  df["book_date"] = pd.to_datetime(df["book_date"], dayfirst=True).dt.strftime("%Y-%m-%d")
31
31
  df["value_date"] = pd.to_datetime(df["value_date"], dayfirst=True).dt.strftime("%Y-%m-%d")
32
- df["portfolio"] = df.linked_product.apply(lambda x: x.primary_portfolio if x else None)
32
+ df["portfolio"] = df["product"].apply(lambda x: x.primary_portfolio if x else None)
33
33
  df["base_management_fees"] = df.apply(
34
34
  lambda row: float(
35
- row["linked_product"].get_fees_percent(row["transaction_date"], FeeProductPercentage.Type.MANAGEMENT)
35
+ row["product"].get_fees_percent(row["transaction_date"], FeeProductPercentage.Type.MANAGEMENT)
36
36
  ),
37
37
  axis=1,
38
38
  )
39
39
  df["base_bank_fees"] = df.apply(
40
40
  lambda row: float(
41
- row["linked_product"].get_fees_percent(row["transaction_date"], FeeProductPercentage.Type.BANK)
41
+ row["product"].get_fees_percent(row["transaction_date"], FeeProductPercentage.Type.BANK)
42
42
  ),
43
43
  axis=1,
44
44
  )
@@ -63,8 +63,8 @@ def parse(import_source):
63
63
  df = pd.concat([df_management, df_bank], axis=0)
64
64
  df = df.drop(columns=df.columns.difference(["transaction_subtype", *FIELD_MAP.values()]))
65
65
 
66
- df["linked_product"] = df.linked_product.apply(lambda x: x.id)
67
- df = df.dropna(subset=["linked_product"])
66
+ df["product"] = df["product"].apply(lambda x: x.id)
67
+ df = df.dropna(subset=["product"])
68
68
 
69
69
  for row in df.to_dict("records"):
70
70
  # The fee are sometime aggregated. The aggregate date range information is given in the comment. We therefore try to extract it and duplicate the averaged fees
@@ -10,7 +10,7 @@ FIELD_MAP = {
10
10
  "AccrValueInstrCcy": "total_value",
11
11
  "FxRate": "currency_fx_rate",
12
12
  "TradingCurrency": "currency__key",
13
- "#ClientName": "linked_product",
13
+ "#ClientName": "product",
14
14
  "InstrumentName": "comment",
15
15
  }
16
16
 
@@ -29,7 +29,7 @@ def parse(import_source):
29
29
  df["transaction_subtype"] = Fees.Type.MANAGEMENT
30
30
  df["transaction_date"] = pd.to_datetime(df["transaction_date"], dayfirst=True).dt.strftime("%Y-%m-%d")
31
31
  df["value_date"] = pd.to_datetime(df["value_date"], dayfirst=True).dt.strftime("%Y-%m-%d")
32
- df = df.dropna(subset=["linked_product"])
33
- df.linked_product = df.linked_product.apply(lambda x: {"identifier": x})
32
+ df = df.dropna(subset=["product"])
33
+ df.product = df["product"].apply(lambda x: {"identifier": x})
34
34
  data = df.to_dict("records")
35
35
  return {"data": data}
@@ -21,7 +21,7 @@ claims AS (
21
21
  JOIN wbcrm_account AS account
22
22
  ON claim.account_id = account.id
23
23
  JOIN wbportfolio_trade AS trade
24
- ON claim.trade_id = trade.transaction_ptr_id
24
+ ON claim.trade_id = trade.id
25
25
  WHERE claim.status = 'APPROVED'
26
26
  ),
27
27
  -- CTE for claims, that fetches them with their shares and price at transaction date
@@ -35,7 +35,7 @@ claims_with_nav AS (
35
35
  trade.marked_as_internal as marked_as_internal
36
36
  FROM wbportfolio_claim AS claims
37
37
  JOIN wbportfolio_trade AS trade
38
- ON claims.trade_id = trade.transaction_ptr_id
38
+ ON claims.trade_id = trade.id
39
39
  LEFT JOIN wbcrm_account AS accounts
40
40
  ON claims.account_id = accounts.id
41
41
  LEFT JOIN LATERAL (
@@ -45,7 +45,7 @@ class Migration(migrations.Migration):
45
45
  migrations.AddConstraint(
46
46
  model_name="fees",
47
47
  constraint=models.UniqueConstraint(
48
- fields=("linked_product", "fee_date", "transaction_subtype", "calculated"), name="unique_fees"
48
+ fields=("product", "fee_date", "transaction_subtype", "calculated"), name="unique_fees"
49
49
  ),
50
50
  ),
51
51
  ]