orionapi 2.31.0__tar.gz → 2.32.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orionapi
3
- Version: 2.31.0
3
+ Version: 2.32.0
4
4
  Summary: A python interface for the Orion Advisors platform web API
5
5
  Author: spencerogden-dsam
6
6
  Author-email: 67068943+spencerogden-dsam@users.noreply.github.com
@@ -1,4 +1,4 @@
1
- __version__ = "2.31.0"
1
+ __version__ = "2.32.0"
2
2
 
3
3
  import logging
4
4
  import re
@@ -2189,11 +2189,15 @@ class OrionAPI(BaseAPI):
2189
2189
  return res.json()
2190
2190
 
2191
2191
  def sync_cash_to_eclipse(self, account):
2192
- """Export one cash funding row to Eclipse as a cash set-aside.
2192
+ """Deprecated: export one cash funding row to Eclipse as a set-aside.
2193
2193
 
2194
- This is the API equivalent of the Cash Funding grid's export action:
2195
- Orion creates a set-aside in Eclipse for the account's balance due,
2196
- so the fee cash is reserved from trading.
2194
+ This is NOT what Orion's Cash Funding Export does. Use Eclipse
2195
+ billing_set_aside_cash() instead, which produces the same billing
2196
+ set-asides as the Orion screen (percent of value, expire on the Fee
2197
+ transaction, updated in place). Emits a ``DeprecationWarning``.
2198
+
2199
+ Orion creates a dollar set-aside in Eclipse for the ``balanceDue`` you
2200
+ send; it does not recompute the amount.
2197
2201
 
2198
2202
  Every call INSERTS a new set-aside; it never updates an existing one.
2199
2203
  Live-verified 2026-09: two calls for the same account left two active
@@ -2219,6 +2223,12 @@ class OrionAPI(BaseAPI):
2219
2223
  (EclipseCashFundingResponse) with id, accountId, cashAmount,
2220
2224
  cashAmountTypeId, description, expirationTypeId, etc.
2221
2225
  """
2226
+ warnings.warn(
2227
+ "sync_cash_to_eclipse is deprecated; use Eclipse billing_set_aside_cash(), "
2228
+ "which matches Orion's Cash Funding Export.",
2229
+ DeprecationWarning,
2230
+ stacklevel=2,
2231
+ )
2222
2232
  if not isinstance(account, dict):
2223
2233
  raise ValueError("account must be a cash funding row dict")
2224
2234
 
@@ -2953,6 +2963,30 @@ class EclipseBase(BaseAPI):
2953
2963
  )
2954
2964
  return best_acct["id"], best_acct["accountNumber"]
2955
2965
 
2966
+ def get_orion_connect_firm_id(self):
2967
+ """Get the Orion Connect firm id of the logged-in Eclipse user, cached.
2968
+
2969
+ Read from ``ocFirmId`` on ``GET /v1/admin/authorization/user``. This
2970
+ is the ``orionConnectFirmId`` that billing_set_aside_cash() needs.
2971
+
2972
+ Returns:
2973
+ int: The Orion Connect firm id
2974
+
2975
+ Raises:
2976
+ OrionAPIError: if the user has no firm id or more than one (pass
2977
+ ``orionConnectFirmId`` explicitly in that case)
2978
+ """
2979
+ if getattr(self, "_orion_connect_firm_id", None) is None:
2980
+ res = self.api_request(f"{self.base_url}/admin/authorization/user")
2981
+ firm_ids = res.json().get("ocFirmId") or []
2982
+ if len(firm_ids) != 1:
2983
+ raise OrionAPIError(
2984
+ f"Expected one Orion Connect firm id for this user, got {firm_ids!r}; "
2985
+ "pass orionConnectFirmId explicitly"
2986
+ )
2987
+ self._orion_connect_firm_id = firm_ids[0]
2988
+ return self._orion_connect_firm_id
2989
+
2956
2990
 
2957
2991
  class EclipseV1(EclipseBase):
2958
2992
  """Eclipse client targeting the v1 API surface (``/v1/...``) only.
@@ -3050,11 +3084,13 @@ class EclipseV1(EclipseBase):
3050
3084
  max_amount: Maximum cash amount (default 0.0)
3051
3085
  description: Description of the set-aside
3052
3086
  cash_type: '$' for dollar amount, '%' for percentage (default '$')
3053
- start_date: Start date for the set-aside
3087
+ start_date: Optional start date (YYYY-MM-DD)
3054
3088
  expire_type: 'None', 'Date', or 'Transaction' (default 'None')
3055
3089
  expire_date: Expiration date (if expire_type='Date')
3056
3090
  expire_trans_tol: Transaction tolerance value (default 0)
3057
- expire_trans_type: 1='Distribution / Merge Out', 3='Fee' (default 1)
3091
+ expire_trans_type: For expire_type='Transaction', the transaction
3092
+ that expires it: 1 or 'Distribution / Merge Out', 3 or 'Fee'
3093
+ (default 1). Orion's billing export uses 'Fee' with tolerance 15.
3058
3094
  deplete_over_time: Maps to the UI "Deplete Over Time" checkbox
3059
3095
  (``isDepleteOverTime``). Only meaningful when
3060
3096
  expire_type='Transaction' (default False)
@@ -3113,8 +3149,10 @@ class EclipseV1(EclipseBase):
3113
3149
  if expire_type == 1:
3114
3150
  expire_value = expire_date
3115
3151
  elif expire_type == 2:
3116
- # Transaction-based expiration uses toleranceValue, expirationValue should be 0
3117
- expire_value = 0
3152
+ # For Transaction expiration, expirationValue carries the transaction
3153
+ # type id (3 = Fee). Live-verified 2026-09: Eclipse ignores a separate
3154
+ # transactionTypeId and stores no type when expirationValue is 0.
3155
+ expire_value = expire_trans_type
3118
3156
  elif expire_type == 3:
3119
3157
  expire_value = 0
3120
3158
 
@@ -3126,22 +3164,24 @@ class EclipseV1(EclipseBase):
3126
3164
  if isinstance(percent_calc_type, str):
3127
3165
  percent_calc_type = percent_calc_type_map[percent_calc_type]
3128
3166
 
3167
+ payload = {
3168
+ "cashAmountTypeId": cash_type,
3169
+ "cashAmount": float(amount),
3170
+ "minCashAmount": float(min_amount),
3171
+ "maxCashAmount": float(max_amount),
3172
+ "expirationTypeId": expire_type,
3173
+ "expirationValue": expire_value,
3174
+ "toleranceValue": expire_trans_tol,
3175
+ "isDepleteOverTime": bool(deplete_over_time),
3176
+ "description": description,
3177
+ "percentCalculationTypeId": percent_calc_type,
3178
+ }
3179
+ if start_date is not None:
3180
+ payload["startDate"] = start_date
3129
3181
  res = self.api_request(
3130
3182
  f"{self.base_url}/account/accounts/{account_id}/asidecash",
3131
3183
  requests.post,
3132
- json={
3133
- "cashAmountTypeId": cash_type,
3134
- "cashAmount": float(amount),
3135
- "minCashAmount": float(min_amount),
3136
- "maxCashAmount": float(max_amount),
3137
- "expirationTypeId": expire_type,
3138
- "expirationValue": expire_value,
3139
- "toleranceValue": expire_trans_tol,
3140
- "transactionTypeId": expire_trans_type,
3141
- "isDepleteOverTime": bool(deplete_over_time),
3142
- "description": description,
3143
- "percentCalculationTypeId": percent_calc_type,
3144
- },
3184
+ json=payload,
3145
3185
  )
3146
3186
  result = res.json()
3147
3187
  self._maybe_wait_for_analytics(sync)
@@ -9670,18 +9710,50 @@ class EclipseV2(EclipseBase):
9670
9710
  return res.json()
9671
9711
 
9672
9712
  def billing_set_aside_cash(self, payload):
9673
- """Create billing set-aside cash (mutating).
9713
+ """Set each account's billing set-aside cash (mutating).
9714
+
9715
+ The endpoint behind Orion's Cash Funding Export. Give it dollar
9716
+ amounts; Eclipse applies its billing template. Live-verified 2026-09:
9717
+
9718
+ - The set-aside is a % of the account's total value (amount / value),
9719
+ "Use Total Value", expiring on the next Fee transaction (tolerance
9720
+ 15), start date today, description "Billing Set Aside Cash from
9721
+ Orion Connect on <date>", and ``isBilling`` true (only this
9722
+ endpoint sets it).
9723
+ - It updates the account's active billing set-aside in place rather
9724
+ than adding another.
9725
+ - An amount of 0 leaves the set-aside active at 0%; use
9726
+ expire_set_asides() to retire it.
9727
+
9728
+ Only single-account lists have been live-verified; the endpoint takes
9729
+ a list, so larger batches should work but check the results.
9674
9730
 
9675
9731
  Args:
9676
- payload: Billing set-aside DTO (request body)
9732
+ payload: List of ``{"orionConnectExternalAccountId": int,
9733
+ "amount": float}``. ``orionConnectExternalAccountId`` is the
9734
+ Orion account id (the ``id`` of a get_cash_funding() row), not
9735
+ the Eclipse id. ``orionConnectFirmId`` is filled in from
9736
+ get_orion_connect_firm_id() when an entry omits it.
9677
9737
 
9678
9738
  Returns:
9679
- dict: Result
9739
+ dict | None: Parsed response, or None on the empty body the
9740
+ endpoint normally returns
9680
9741
  """
9742
+ if not isinstance(payload, list) or not payload:
9743
+ raise ValueError("payload must be a non-empty list of account entries")
9744
+ for entry in payload:
9745
+ if not isinstance(entry, dict) or "orionConnectExternalAccountId" not in entry:
9746
+ raise ValueError("each entry needs an orionConnectExternalAccountId")
9747
+ if "amount" not in entry:
9748
+ raise ValueError("each entry needs an amount")
9749
+ if any("orionConnectFirmId" not in entry for entry in payload):
9750
+ firm_id = self.get_orion_connect_firm_id()
9751
+ payload = [{"orionConnectFirmId": firm_id, **entry} for entry in payload]
9752
+
9681
9753
  res = self.api_request(
9682
9754
  f"{self.base_url_v2}/SetAsideCash/BillingSetAsideCash", requests.post, json=payload
9683
9755
  )
9684
- return res.json()
9756
+ return _json_or_none(res)
9685
9757
 
9686
9758
  def delete_account_set_aside_cash(self, payload):
9687
9759
  """Delete account set-aside cash (mutating).
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "orionapi"
3
- version = "2.31.0"
3
+ version = "2.32.0"
4
4
  description = "A python interface for the Orion Advisors platform web API"
5
5
  authors = ["spencerogden-dsam <67068943+spencerogden-dsam@users.noreply.github.com>"]
6
6
 
File without changes