Skip to content

Commit 70264c2

Browse files
authored
Merge pull request #71 from Deigue/fix-monthly-statement
Fix broken endpoint to download monthly statements
2 parents 84e140b + 9bdf512 commit 70264c2

4 files changed

Lines changed: 24 additions & 9 deletions

File tree

‎pyproject.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ Repository = "https://github.com/gboudreau/ws-api-python"
4242
[tool.hatch.build.targets.wheel]
4343
packages = ["ws_api"]
4444

45+
[tool.pytest.ini_options]
46+
addopts = "--ignore=tests/test_full_example.py"
47+
4548
[dependency-groups]
4649
dev = [
4750
"pytest",

‎tests/test_wealthsimple_api_happy.py‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,10 +425,22 @@ def test_get_corporate_action_child_activities(api):
425425
def test_get_statement_transactions(api):
426426
"""Smoke test get_statement_transactions."""
427427
fake_transactions = [{"balance": 100}]
428-
fake_statements = [{"data": {"currentTransactions": fake_transactions}}]
429-
with patch.object(api, "do_graphql_query", return_value=fake_statements):
428+
fake_statement = {"data": {"currentTransactions": fake_transactions}}
429+
with patch.object(
430+
api, "do_graphql_query", return_value=fake_statement
431+
) as mock_query:
430432
result = api.get_statement_transactions("acc_id", "2023-01-01")
431433
assert result == fake_transactions
434+
mock_query.assert_called_once_with(
435+
"FetchMonthlyStatementWithTransactions",
436+
{
437+
"accountId": "acc_id",
438+
"period": "2023-01-01",
439+
"statementType": "brokerage_monthly_statement",
440+
},
441+
"monthlyStatement",
442+
"object",
443+
)
432444

433445

434446
def test_get_identity_positions(api):

‎ws_api/graphql_queries.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"FetchAccountHistoricalFinancials": "query FetchAccountHistoricalFinancials($id: ID!, $currency: Currency!, $startDate: Date, $resolution: DateResolution!, $endDate: Date, $first: Int, $cursor: String) {\n account(id: $id) {\n id\n financials {\n historicalDaily(\n currency: $currency\n startDate: $startDate\n resolution: $resolution\n endDate: $endDate\n first: $first\n after: $cursor\n ) {\n edges {\n node {\n ...AccountHistoricalFinancials\n __typename\n }\n __typename\n }\n pageInfo {\n hasNextPage\n endCursor\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n }\n\n fragment AccountHistoricalFinancials on AccountHistoricalDailyFinancials {\n date\n netLiquidationValueV2 {\n ...Money\n __typename\n }\n netDepositsV2 {\n ...Money\n __typename\n }\n __typename\n }\n\n fragment Money on Money {\n amount\n cents\n currency\n __typename\n }",
1313
"FetchIdentityHistoricalFinancials": "query FetchIdentityHistoricalFinancials($identityId: ID!, $currency: Currency!, $startDate: Date, $endDate: Date, $first: Int, $cursor: String, $accountIds: [ID!]) {\n identity(id: $identityId) {\n id\n financials(filter: {accounts: $accountIds}) {\n historicalDaily(\n currency: $currency\n startDate: $startDate\n endDate: $endDate\n first: $first\n after: $cursor\n ) {\n edges {\n node {\n ...IdentityHistoricalFinancials\n __typename\n }\n __typename\n }\n pageInfo {\n hasNextPage\n endCursor\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n }\n\n fragment IdentityHistoricalFinancials on IdentityHistoricalDailyFinancials {\n date\n netLiquidationValueV2 {\n amount\n currency\n __typename\n }\n netDepositsV2 {\n amount\n currency\n __typename\n }\n __typename\n }",
1414
"FetchCorporateActionChildActivities": "query FetchCorporateActionChildActivities($activityCanonicalId: String!) {\n corporateActionChildActivities(\n condition: {activityCanonicalId: $activityCanonicalId}\n ) {\n nodes {\n ...CorporateActionChildActivity\n __typename\n }\n __typename\n }\n}\n\nfragment CorporateActionChildActivity on CorporateActionChildActivity {\n canonicalId\n activityCanonicalId\n assetName\n assetSymbol\n assetType\n entitlementType\n quantity\n currency\n price\n recordDate\n __typename\n}",
15-
"FetchBrokerageMonthlyStatementTransactions": "query FetchBrokerageMonthlyStatementTransactions($period: String!, $accountId: String!) {\n brokerageMonthlyStatements(period: $period, accountId: $accountId) {\n id\n statementType\n createdAt\n data {\n ... on BrokerageMonthlyStatementObject {\n ...BrokerageMonthlyStatementObject\n __typename\n }\n __typename\n }\n __typename\n }\n}\n\nfragment BrokerageMonthlyStatementObject on BrokerageMonthlyStatementObject {\n custodianAccountId\n activitiesPerCurrency {\n currency\n currentTransactions {\n ...BrokerageMonthlyStatementTransactions\n __typename\n }\n __typename\n }\n currentTransactions {\n ...BrokerageMonthlyStatementTransactions\n __typename\n }\n isMultiCurrency\n __typename\n}\n\nfragment BrokerageMonthlyStatementTransactions on BrokerageMonthlyStatementTransactions {\n balance\n cashMovement\n unit\n description\n transactionDate\n transactionType\n __typename\n}",
15+
"FetchMonthlyStatementWithTransactions": "query FetchMonthlyStatementWithTransactions($accountId: String!, $period: String!, $statementType: StatementType!) {\n monthlyStatement(\n accountId: $accountId\n period: $period\n statementType: $statementType\n ) {\n ...MonthlyStatementWithTransactions\n __typename\n }\n}\n\nfragment MonthlyStatementWithTransactions on Statement {\n id\n statementType\n data {\n __typename\n ... on CashMonthlyStatementObject {\n custodianAccountId\n currentTransactions {\n transactionDate\n transactionType\n description\n cashMovement\n balance\n __typename\n }\n __typename\n }\n ... on BrokerageMonthlyStatementObject {\n custodianAccountId\n isMultiCurrency\n currentTransactions {\n transactionDate\n transactionType\n description\n cashMovement\n balance\n unit\n __typename\n }\n activitiesPerCurrency {\n currency\n currentTransactions {\n transactionDate\n transactionType\n description\n cashMovement\n balance\n unit\n __typename\n }\n __typename\n }\n __typename\n }\n }\n __typename\n}",
1616
"FetchIdentityPositions": "query FetchIdentityPositions($identityId: ID!, $currency: Currency!, $first: Int, $cursor: String, $accountIds: [ID!], $aggregated: Boolean, $currencyOverride: CurrencyOverride, $sort: PositionSort, $sortDirection: PositionSortDirection, $filter: PositionFilter, $since: PointInTime, $includeSecurity: Boolean = false, $includeAccountData: Boolean = false, $includeOneDayReturnsBaseline: Boolean = false) {\n identity(id: $identityId) {\n id\n financials(filter: {accounts: $accountIds}) {\n current(currency: $currency) {\n id\n positions(\n first: $first\n after: $cursor\n aggregated: $aggregated\n filter: $filter\n sort: $sort\n sortDirection: $sortDirection\n ) {\n edges {\n node {\n ...PositionV2\n __typename\n }\n __typename\n }\n pageInfo {\n hasNextPage\n endCursor\n __typename\n }\n totalCount\n status\n hasOptionsPosition\n hasCryptoPositionsOnly\n securityTypes\n securityCurrencies\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n}\n\nfragment SecuritySummary on Security {\n ...SecuritySummaryDetails\n stock {\n ...StockSummary\n __typename\n }\n quoteV2(currency: null) {\n ...SecurityQuoteV2\n __typename\n }\n optionDetails {\n ...OptionSummary\n __typename\n }\n __typename\n}\n\nfragment SecuritySummaryDetails on Security {\n id\n currency\n inactiveDate\n status\n wsTradeEligible\n equityTradingSessionType\n securityType\n active\n securityGroups {\n id\n name\n __typename\n }\n features\n logoUrl\n __typename\n}\n\nfragment StockSummary on Stock {\n name\n symbol\n primaryMic\n primaryExchange\n __typename\n}\n\nfragment StreamedSecurityQuoteV2 on UnifiedQuote {\n __typename\n securityId\n ask\n bid\n currency\n price\n sessionPrice\n quotedAsOf\n ... on EquityQuote {\n marketStatus\n askSize\n bidSize\n close\n high\n last\n lastSize\n low\n open\n mid\n volume: vol\n referenceClose\n __typename\n }\n ... on OptionQuote {\n marketStatus\n askSize\n bidSize\n close\n high\n last\n lastSize\n low\n open\n mid\n volume: vol\n breakEven\n inTheMoney\n liquidityStatus\n openInterest\n underlyingSpot\n __typename\n }\n}\n\nfragment SecurityQuoteV2 on UnifiedQuote {\n ...StreamedSecurityQuoteV2\n previousBaseline\n __typename\n}\n\nfragment OptionSummary on Option {\n underlyingSecurity {\n ...UnderlyingSecuritySummary\n __typename\n }\n maturity\n osiSymbol\n expiryDate\n multiplier\n optionType\n strikePrice\n __typename\n}\n\nfragment UnderlyingSecuritySummary on Security {\n id\n stock {\n name\n primaryExchange\n primaryMic\n symbol\n __typename\n }\n __typename\n}\n\nfragment PositionLeg on PositionLeg {\n security {\n id\n ...SecuritySummary @include(if: $includeSecurity)\n __typename\n }\n quantity\n positionDirection\n bookValue {\n amount\n currency\n __typename\n }\n totalValue(currencyOverride: $currencyOverride) {\n amount\n currency\n __typename\n }\n averagePrice {\n amount\n currency\n __typename\n }\n percentageOfAccount\n unrealizedReturns(since: $since) {\n amount\n currency\n __typename\n }\n marketAveragePrice: averagePrice(currencyOverride: $currencyOverride) {\n amount\n currency\n __typename\n }\n marketBookValue: bookValue(currencyOverride: $currencyOverride) {\n amount\n currency\n __typename\n }\n marketUnrealizedReturns: unrealizedReturns(currencyOverride: $currencyOverride) {\n amount\n currency\n __typename\n }\n oneDayReturnsBaselineV2(currencyOverride: $currencyOverride) @include(if: $includeOneDayReturnsBaseline) {\n baseline {\n currency\n amount\n __typename\n }\n useDailyPriceChange\n __typename\n }\n __typename\n}\n\nfragment PositionV2 on PositionV2 {\n id\n quantity\n accounts @include(if: $includeAccountData) {\n id\n __typename\n }\n percentageOfAccount\n positionDirection\n bookValue {\n amount\n currency\n __typename\n }\n averagePrice {\n amount\n currency\n __typename\n }\n marketAveragePrice: averagePrice(currencyOverride: $currencyOverride) {\n amount\n currency\n __typename\n }\n marketBookValue: bookValue(currencyOverride: $currencyOverride) {\n amount\n currency\n __typename\n }\n totalValue(currencyOverride: $currencyOverride) {\n amount\n currency\n __typename\n }\n unrealizedReturns(since: $since) {\n amount\n currency\n __typename\n }\n marketUnrealizedReturns: unrealizedReturns(currencyOverride: $currencyOverride) {\n amount\n currency\n __typename\n }\n security {\n id\n ...SecuritySummary @include(if: $includeSecurity)\n __typename\n }\n oneDayReturnsBaselineV2(currencyOverride: $currencyOverride) @include(if: $includeOneDayReturnsBaseline) {\n baseline {\n currency\n amount\n __typename\n }\n useDailyPriceChange\n __typename\n }\n strategyType\n legs {\n ...PositionLeg\n __typename\n }\n __typename\n}",
1717
"FetchCreditCardAccount": "query FetchCreditCardAccount($id: ID!) {\n creditCardAccount(id: $id) {\n ...CreditCardAccount\n __typename\n }\n}\n\nfragment CreditCardAccount on CreditCardAccount {\n id\n creditLimit\n upgradesInProgress\n balance {\n current\n outstanding\n availableCreditLimit\n pending\n __typename\n }\n cardProductId\n statementDayOfMonth\n actions\n currentCards {\n id\n actions\n cardNumber\n cardStatus\n cardVariant\n isLocked\n isPhysicalCardActivated\n isSupplementaryCard\n nameOnCard\n __typename\n }\n cards {\n id\n cardNumber\n adminActions\n lastPinCounterResetAt\n isBlocked\n isPhysicalCardActivated\n __typename\n }\n preferences {\n cardRewardRedemptionType\n __typename\n }\n __typename\n}",
1818
"FetchIdentityCurrentFinancials": "query FetchIdentityCurrentFinancials($identityId: ID!, $currency: Currency!, $startDate: Date, $accountIds: [ID!], $accountScope: AccountScope = OWN) {\n identity(id: $identityId) {\n id\n financials(filter: {accounts: $accountIds}, accountScope: $accountScope) {\n current(currency: $currency) {\n id\n netLiquidationValueV2 {\n ...Money\n __typename\n }\n netDeposits: netDepositsV2 {\n ...Money\n __typename\n }\n simpleReturns(referenceDate: $startDate) {\n amount {\n ...Money\n __typename\n }\n asOf\n rate\n referenceDate\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n}\n\nfragment Money on Money {\n amount\n cents\n currency\n __typename\n}",

‎ws_api/wealthsimple_api.py‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -785,19 +785,19 @@ def get_statement_transactions(self, account_id: str, period: str) -> list[Any]:
785785
Raises:
786786
WSApiException: If the response format is unexpected.
787787
"""
788-
statements = self.do_graphql_query(
789-
"FetchBrokerageMonthlyStatementTransactions",
788+
statement = self.do_graphql_query(
789+
"FetchMonthlyStatementWithTransactions",
790790
{
791791
"accountId": account_id,
792792
"period": period,
793+
"statementType": "brokerage_monthly_statement",
793794
},
794-
"brokerageMonthlyStatements",
795-
"array",
795+
"monthlyStatement",
796+
"object",
796797
)
797798

798799
transactions = []
799-
if isinstance(statements, list) and len(statements) > 0:
800-
statement = statements[0]
800+
if isinstance(statement, dict):
801801
data = statement.get("data") if "data" in statement else {}
802802
transactions = (
803803
data.get("currentTransactions") if "currentTransactions" in data else []

0 commit comments

Comments
 (0)