@firela/api-types 0.0.0-canary.45a6cc23 → 0.0.0-canary.4e3af49c

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.
@@ -17,6 +17,8 @@ import type {
17
17
  AccountControllerCloseResponse,
18
18
  AccountControllerReopenData,
19
19
  AccountControllerReopenResponse,
20
+ AccountControllerAddOpeningBalanceData,
21
+ AccountControllerAddOpeningBalanceResponse,
20
22
  AccountStandardsControllerGetTemplatesData,
21
23
  AccountStandardsControllerGetTemplatesResponse,
22
24
  AccountStandardsControllerGetTemplateMetadataData,
@@ -97,6 +99,18 @@ import type {
97
99
  CommodityControllerGetOrCreateResponse,
98
100
  CommodityControllerBulkCreateData,
99
101
  CommodityControllerBulkCreateResponse,
102
+ PriceControllerCreateData,
103
+ PriceControllerCreateResponse,
104
+ PriceControllerFindAllData,
105
+ PriceControllerFindAllResponse,
106
+ PriceControllerFindOneData,
107
+ PriceControllerFindOneResponse,
108
+ PriceControllerUpdateData,
109
+ PriceControllerUpdateResponse,
110
+ PriceControllerDeleteData,
111
+ PriceControllerDeleteResponse,
112
+ PriceControllerBulkCreateData,
113
+ PriceControllerBulkCreateResponse,
100
114
  RecurringRuleControllerCreateData,
101
115
  RecurringRuleControllerCreateResponse,
102
116
  RecurringRuleControllerFindAllData,
@@ -129,26 +143,14 @@ import type {
129
143
  ExpectedTransactionControllerEnterNowResponse,
130
144
  ForecastControllerGetForecastData,
131
145
  ForecastControllerGetForecastResponse,
132
- TransactionRuleControllerCreateData,
133
- TransactionRuleControllerCreateResponse,
134
- TransactionRuleControllerListData,
135
- TransactionRuleControllerListResponse,
136
- TransactionRuleControllerValidateData,
137
- TransactionRuleControllerValidateResponse,
138
- TransactionRuleControllerBulkCreateData,
139
- TransactionRuleControllerBulkCreateResponse,
140
- TransactionRuleControllerExportData,
141
- TransactionRuleControllerExportResponse,
142
- TransactionRuleControllerGetStatisticsData,
143
- TransactionRuleControllerGetStatisticsResponse,
144
- TransactionRuleControllerGetDetailData,
145
- TransactionRuleControllerGetDetailResponse,
146
- TransactionRuleControllerUpdateData,
147
- TransactionRuleControllerUpdateResponse,
148
- TransactionRuleControllerDeleteData,
149
- TransactionRuleControllerDeleteResponse,
150
- TransactionRuleControllerTestData,
151
- TransactionRuleControllerTestResponse,
146
+ ReportingControllerGetPortfolioTrendsData,
147
+ ReportingControllerGetPortfolioTrendsResponse,
148
+ ReportingControllerGetCashFlowTrendsData,
149
+ ReportingControllerGetCashFlowTrendsResponse,
150
+ ReportingControllerGenerateSnapshotData,
151
+ ReportingControllerGenerateSnapshotResponse,
152
+ ReportingControllerBackfillSnapshotsData,
153
+ ReportingControllerBackfillSnapshotsResponse,
152
154
  UserControllerDeleteOwnUserData,
153
155
  UserControllerDeleteOwnUserResponse,
154
156
  UserControllerGetUserData,
@@ -171,6 +173,26 @@ import type {
171
173
  PropertyControllerUpdateResponse,
172
174
  PropertyControllerDeleteData,
173
175
  PropertyControllerDeleteResponse,
176
+ TransactionRuleControllerCreateData,
177
+ TransactionRuleControllerCreateResponse,
178
+ TransactionRuleControllerListData,
179
+ TransactionRuleControllerListResponse,
180
+ TransactionRuleControllerValidateData,
181
+ TransactionRuleControllerValidateResponse,
182
+ TransactionRuleControllerBulkCreateData,
183
+ TransactionRuleControllerBulkCreateResponse,
184
+ TransactionRuleControllerExportData,
185
+ TransactionRuleControllerExportResponse,
186
+ TransactionRuleControllerGetStatisticsData,
187
+ TransactionRuleControllerGetStatisticsResponse,
188
+ TransactionRuleControllerGetDetailData,
189
+ TransactionRuleControllerGetDetailResponse,
190
+ TransactionRuleControllerUpdateData,
191
+ TransactionRuleControllerUpdateResponse,
192
+ TransactionRuleControllerDeleteData,
193
+ TransactionRuleControllerDeleteResponse,
194
+ TransactionRuleControllerTestData,
195
+ TransactionRuleControllerTestResponse,
174
196
  EventControllerCreateData,
175
197
  EventControllerCreateResponse,
176
198
  EventControllerFindAllData,
@@ -183,6 +205,16 @@ import type {
183
205
  EventControllerDeleteResponse,
184
206
  EventControllerGetSliceData,
185
207
  EventControllerGetSliceResponse,
208
+ OnboardingControllerBootstrapData,
209
+ OnboardingControllerBootstrapResponse,
210
+ ReconciliationControllerComputeData,
211
+ ReconciliationControllerComputeResponse,
212
+ ReconciliationControllerAssertData,
213
+ ReconciliationControllerAssertResponse,
214
+ ReconciliationControllerPadData,
215
+ ReconciliationControllerPadResponse,
216
+ ReconciliationControllerHistoryData,
217
+ ReconciliationControllerHistoryResponse,
186
218
  ExportControllerExportBeancountResponse,
187
219
  FileImportControllerImportFileData,
188
220
  FileImportControllerImportFileResponse,
@@ -196,22 +228,20 @@ import type {
196
228
  ImporterConfigControllerUpdateConfigResponse,
197
229
  ImporterConfigControllerResetConfigData,
198
230
  ImporterConfigControllerResetConfigResponse,
199
- PlatformControllerFindAllResponse,
200
- PlatformControllerCreateData,
201
- PlatformControllerCreateResponse,
202
- PlatformControllerGetPlatformListResponse,
203
- PlatformControllerMatchPlatformsData,
204
- PlatformControllerMatchPlatformsResponse,
205
- PlatformControllerUpdateData,
206
- PlatformControllerUpdateResponse,
207
- PlatformControllerDeleteData,
208
- PlatformControllerDeleteResponse,
209
231
  ProviderSyncControllerSyncData,
210
232
  ProviderSyncControllerSyncResponse,
211
233
  ProviderSyncControllerGetSupportedProvidersData,
212
234
  ProviderSyncControllerGetSupportedProvidersResponse,
213
235
  ProviderSyncControllerIsProviderSupportedData,
214
236
  ProviderSyncControllerIsProviderSupportedResponse,
237
+ ExternalAccountLinkControllerCreateData,
238
+ ExternalAccountLinkControllerCreateResponse,
239
+ ExternalAccountLinkControllerFindAllData,
240
+ ExternalAccountLinkControllerFindAllResponse,
241
+ ExternalAccountLinkControllerFindOneData,
242
+ ExternalAccountLinkControllerFindOneResponse,
243
+ ExternalAccountLinkControllerRemoveData,
244
+ ExternalAccountLinkControllerRemoveResponse,
215
245
  TelemetryControllerReportTelemetryData,
216
246
  TelemetryControllerReportTelemetryResponse,
217
247
  TelemetryControllerReportCoverageMissData,
@@ -224,6 +254,16 @@ import type {
224
254
  NlpControllerClearSessionResponse,
225
255
  NlpControllerGetSessionData,
226
256
  NlpControllerGetSessionResponse,
257
+ PlatformControllerFindAllResponse,
258
+ PlatformControllerCreateData,
259
+ PlatformControllerCreateResponse,
260
+ PlatformControllerGetPlatformListResponse,
261
+ PlatformControllerMatchPlatformsData,
262
+ PlatformControllerMatchPlatformsResponse,
263
+ PlatformControllerUpdateData,
264
+ PlatformControllerUpdateResponse,
265
+ PlatformControllerDeleteData,
266
+ PlatformControllerDeleteResponse,
227
267
  DashboardControllerGetNetWorthData,
228
268
  DashboardControllerGetNetWorthResponse,
229
269
  DashboardControllerGetAccountsData,
@@ -234,26 +274,6 @@ import type {
234
274
  DashboardControllerGetExpensesResponse,
235
275
  HoldingPnlControllerGetHoldingPnlData,
236
276
  HoldingPnlControllerGetHoldingPnlResponse,
237
- PriceControllerCreateData,
238
- PriceControllerCreateResponse,
239
- PriceControllerFindAllData,
240
- PriceControllerFindAllResponse,
241
- PriceControllerFindOneData,
242
- PriceControllerFindOneResponse,
243
- PriceControllerUpdateData,
244
- PriceControllerUpdateResponse,
245
- PriceControllerDeleteData,
246
- PriceControllerDeleteResponse,
247
- PriceControllerBulkCreateData,
248
- PriceControllerBulkCreateResponse,
249
- ReportingControllerGetPortfolioTrendsData,
250
- ReportingControllerGetPortfolioTrendsResponse,
251
- ReportingControllerGetCashFlowTrendsData,
252
- ReportingControllerGetCashFlowTrendsResponse,
253
- ReportingControllerGenerateSnapshotData,
254
- ReportingControllerGenerateSnapshotResponse,
255
- ReportingControllerBackfillSnapshotsData,
256
- ReportingControllerBackfillSnapshotsResponse,
257
277
  ApiKeysControllerCreateApiKeyResponse,
258
278
  AuthControllerAccessTokenLoginData,
259
279
  AuthControllerAccessTokenLoginResponse,
@@ -306,7 +326,7 @@ export class BeanAccountsService {
306
326
  * @param data.type Filter by account type
307
327
  * @param data.status Filter by status
308
328
  * @param data.isCustom Filter by custom (user-created) accounts only
309
- * @param data.search Search term for path or i18nKey
329
+ * @param data.search Search term for account path
310
330
  * @param data.limit Maximum number of results
311
331
  * @param data.offset Number of results to skip
312
332
  * @returns AccountListResponseDto Accounts retrieved successfully
@@ -468,6 +488,35 @@ export class BeanAccountsService {
468
488
  }
469
489
  });
470
490
  }
491
+
492
+ /**
493
+ * Post an opening-balance transaction
494
+ * Posts a double-entry opening-balance transaction against Equity:Opening-Balances for an existing Assets/Liabilities account. At most one active opening balance per account.
495
+ * @param data The data for the request.
496
+ * @param data.id Account UUID
497
+ * @param data.region Region code for tenant context
498
+ * @param data.requestBody
499
+ * @returns OpeningBalanceResultDto Opening-balance transaction created
500
+ * @throws ApiError
501
+ */
502
+ public static accountControllerAddOpeningBalance(
503
+ data: AccountControllerAddOpeningBalanceData
504
+ ): CancelablePromise<AccountControllerAddOpeningBalanceResponse> {
505
+ return __request(OpenAPI, {
506
+ method: 'POST',
507
+ url: '/api/v1/{region}/bean/accounts/{id}/opening-balance',
508
+ path: {
509
+ id: data.id,
510
+ region: data.region
511
+ },
512
+ body: data.requestBody,
513
+ mediaType: 'application/json',
514
+ errors: {
515
+ 404: 'Account not found',
516
+ 409: 'An opening balance already exists for this account'
517
+ }
518
+ });
519
+ }
471
520
  }
472
521
 
473
522
  export class BeanAccountStandardsService {
@@ -499,7 +548,7 @@ export class BeanAccountStandardsService {
499
548
 
500
549
  /**
501
550
  * Get template metadata for an account path
502
- * Returns extendable status and root type for a template path.
551
+ * Returns root type for a template path.
503
552
  * @param data The data for the request.
504
553
  * @param data.region Region code for tenant context
505
554
  * @param data.path Account path to check
@@ -794,7 +843,7 @@ export class BeanBalancesService {
794
843
  * Query account balance
795
844
  * Calculate account balance at a specific date for a single currency
796
845
  * @param data The data for the request.
797
- * @param data.account Account name (e.g., "Assets:Bank:Checking")
846
+ * @param data.account Account name (e.g., "Assets:Checking")
798
847
  * @param data.region Region code for tenant context
799
848
  * @param data.date Date to calculate balance at (ISO 8601 format)
800
849
  * @param data.currency Currency to query (e.g., "USD", "CNY")
@@ -1515,153 +1564,320 @@ export class BeanCommoditiesService {
1515
1564
  }
1516
1565
  }
1517
1566
 
1518
- export class RecurringRulesService {
1567
+ export class BeanPricesService {
1519
1568
  /**
1520
- * Create a new recurring rule
1521
- * Creates a new recurring transaction rule for the authenticated user
1569
+ * Create a new price
1570
+ * Creates a new price entry for the authenticated user
1522
1571
  * @param data The data for the request.
1523
1572
  * @param data.region Region code for tenant context
1524
1573
  * @param data.requestBody
1525
- * @returns RecurringRuleResponseDto Rule created successfully
1574
+ * @returns PriceResponseDto Price created successfully
1526
1575
  * @throws ApiError
1527
1576
  */
1528
- public static recurringRuleControllerCreate(
1529
- data: RecurringRuleControllerCreateData
1530
- ): CancelablePromise<RecurringRuleControllerCreateResponse> {
1577
+ public static priceControllerCreate(
1578
+ data: PriceControllerCreateData
1579
+ ): CancelablePromise<PriceControllerCreateResponse> {
1531
1580
  return __request(OpenAPI, {
1532
1581
  method: 'POST',
1533
- url: '/api/v1/{region}/bean/recurring-rules',
1582
+ url: '/api/v1/{region}/bean/prices',
1534
1583
  path: {
1535
1584
  region: data.region
1536
1585
  },
1537
1586
  body: data.requestBody,
1538
1587
  mediaType: 'application/json',
1539
1588
  errors: {
1540
- 400: 'Invalid input data (e.g., autoCreate without accounts)',
1541
- 409: 'Rule with same name already exists'
1589
+ 404: 'Currency or quoteCurrency commodity not found',
1590
+ 409: 'Price already exists for this currency pair and date'
1542
1591
  }
1543
1592
  });
1544
1593
  }
1545
1594
 
1546
1595
  /**
1547
- * List recurring rules
1548
- * Returns all recurring rules for the authenticated user with optional filtering
1596
+ * List user prices
1597
+ * Returns all price entries for the authenticated user with optional filtering
1549
1598
  * @param data The data for the request.
1550
1599
  * @param data.region Region code for tenant context
1551
- * @param data.isActive Filter by active status
1552
- * @param data.frequency Filter by frequency (WEEKLY, MONTHLY, etc.)
1553
- * @param data.hasAutoCreate Filter by autoCreate enabled
1554
- * @returns RecurringRuleResponseDto Rules retrieved successfully
1600
+ * @param data.currency Filter by currency (e.g., BTC, AAPL, USD)
1601
+ * @param data.quoteCurrency Filter by quote currency (pricing currency, e.g., USD, CNY)
1602
+ * @param data.dateFrom Filter prices from this date (ISO 8601 format)
1603
+ * @param data.dateTo Filter prices to this date (ISO 8601 format)
1604
+ * @param data.search Search term for currency or quoteCurrency (case-insensitive partial match)
1605
+ * @param data.page Page number for pagination (default: 1)
1606
+ * @param data.limit Number of items per page (default: 20, max: 100)
1607
+ * @returns PriceListResponseDto Prices retrieved successfully
1555
1608
  * @throws ApiError
1556
1609
  */
1557
- public static recurringRuleControllerFindAll(
1558
- data: RecurringRuleControllerFindAllData
1559
- ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
1610
+ public static priceControllerFindAll(
1611
+ data: PriceControllerFindAllData
1612
+ ): CancelablePromise<PriceControllerFindAllResponse> {
1560
1613
  return __request(OpenAPI, {
1561
1614
  method: 'GET',
1562
- url: '/api/v1/{region}/bean/recurring-rules',
1615
+ url: '/api/v1/{region}/bean/prices',
1563
1616
  path: {
1564
1617
  region: data.region
1565
1618
  },
1566
1619
  query: {
1567
- isActive: data.isActive,
1568
- frequency: data.frequency,
1569
- hasAutoCreate: data.hasAutoCreate
1620
+ currency: data.currency,
1621
+ quoteCurrency: data.quoteCurrency,
1622
+ dateFrom: data.dateFrom,
1623
+ dateTo: data.dateTo,
1624
+ search: data.search,
1625
+ page: data.page,
1626
+ limit: data.limit
1570
1627
  }
1571
1628
  });
1572
1629
  }
1573
1630
 
1574
1631
  /**
1575
- * Create recurring rule from transaction
1576
- * Auto-creates a recurring rule using transaction data. User only confirms frequency.
1632
+ * Get price by ID
1633
+ * Returns a single price entry by its ID
1577
1634
  * @param data The data for the request.
1578
- * @param data.transactionId Source transaction ID
1635
+ * @param data.id Price ID
1579
1636
  * @param data.region Region code for tenant context
1580
- * @param data.requestBody
1581
- * @returns RecurringRuleResponseDto Rule created successfully
1637
+ * @returns PriceResponseDto Price retrieved successfully
1582
1638
  * @throws ApiError
1583
1639
  */
1584
- public static recurringRuleControllerCreateFromTransaction(
1585
- data: RecurringRuleControllerCreateFromTransactionData
1586
- ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
1640
+ public static priceControllerFindOne(
1641
+ data: PriceControllerFindOneData
1642
+ ): CancelablePromise<PriceControllerFindOneResponse> {
1587
1643
  return __request(OpenAPI, {
1588
- method: 'POST',
1589
- url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
1644
+ method: 'GET',
1645
+ url: '/api/v1/{region}/bean/prices/{id}',
1590
1646
  path: {
1591
- transactionId: data.transactionId,
1647
+ id: data.id,
1592
1648
  region: data.region
1593
1649
  },
1594
- body: data.requestBody,
1595
- mediaType: 'application/json',
1596
1650
  errors: {
1597
- 404: 'Transaction not found',
1598
- 409: 'Rule with same name already exists or transaction already linked'
1651
+ 404: 'Price not found'
1599
1652
  }
1600
1653
  });
1601
1654
  }
1602
1655
 
1603
1656
  /**
1604
- * Get recurring rule by ID
1605
- * Returns a specific recurring rule with its details
1657
+ * Update a price
1658
+ * Updates an existing price entry
1606
1659
  * @param data The data for the request.
1607
- * @param data.id Rule ID
1660
+ * @param data.id Price ID
1608
1661
  * @param data.region Region code for tenant context
1609
- * @returns RecurringRuleResponseDto Rule retrieved successfully
1662
+ * @param data.requestBody
1663
+ * @returns PriceResponseDto Price updated successfully
1610
1664
  * @throws ApiError
1611
1665
  */
1612
- public static recurringRuleControllerFindOne(
1613
- data: RecurringRuleControllerFindOneData
1614
- ): CancelablePromise<RecurringRuleControllerFindOneResponse> {
1666
+ public static priceControllerUpdate(
1667
+ data: PriceControllerUpdateData
1668
+ ): CancelablePromise<PriceControllerUpdateResponse> {
1615
1669
  return __request(OpenAPI, {
1616
- method: 'GET',
1617
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1670
+ method: 'PUT',
1671
+ url: '/api/v1/{region}/bean/prices/{id}',
1618
1672
  path: {
1619
1673
  id: data.id,
1620
1674
  region: data.region
1621
1675
  },
1676
+ body: data.requestBody,
1677
+ mediaType: 'application/json',
1622
1678
  errors: {
1623
- 404: 'Rule not found'
1679
+ 404: 'Price not found',
1680
+ 409: 'Updated price conflicts with existing price'
1624
1681
  }
1625
1682
  });
1626
1683
  }
1627
1684
 
1628
1685
  /**
1629
- * Update recurring rule
1630
- * Updates an existing recurring rule
1686
+ * Delete a price
1687
+ * Deletes a price entry (hard delete)
1631
1688
  * @param data The data for the request.
1632
- * @param data.id Rule ID
1689
+ * @param data.id Price ID
1633
1690
  * @param data.region Region code for tenant context
1634
- * @param data.requestBody
1635
- * @returns RecurringRuleResponseDto Rule updated successfully
1691
+ * @returns void Price deleted successfully
1636
1692
  * @throws ApiError
1637
1693
  */
1638
- public static recurringRuleControllerUpdate(
1639
- data: RecurringRuleControllerUpdateData
1640
- ): CancelablePromise<RecurringRuleControllerUpdateResponse> {
1694
+ public static priceControllerDelete(
1695
+ data: PriceControllerDeleteData
1696
+ ): CancelablePromise<PriceControllerDeleteResponse> {
1641
1697
  return __request(OpenAPI, {
1642
- method: 'PATCH',
1643
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1698
+ method: 'DELETE',
1699
+ url: '/api/v1/{region}/bean/prices/{id}',
1644
1700
  path: {
1645
1701
  id: data.id,
1646
1702
  region: data.region
1647
1703
  },
1648
- body: data.requestBody,
1649
- mediaType: 'application/json',
1650
1704
  errors: {
1651
- 400: 'Invalid input data',
1652
- 404: 'Rule not found'
1705
+ 404: 'Price not found'
1653
1706
  }
1654
1707
  });
1655
1708
  }
1656
1709
 
1657
1710
  /**
1658
- * Delete recurring rule
1659
- * Soft deletes a recurring rule (sets isActive to false)
1711
+ * Bulk create prices
1712
+ * Creates multiple price entries at once (skips duplicates)
1660
1713
  * @param data The data for the request.
1661
- * @param data.id Rule ID
1662
1714
  * @param data.region Region code for tenant context
1663
- * @returns void Rule deleted successfully
1664
- * @throws ApiError
1715
+ * @param data.requestBody
1716
+ * @returns PriceResponseDto Prices created successfully
1717
+ * @throws ApiError
1718
+ */
1719
+ public static priceControllerBulkCreate(
1720
+ data: PriceControllerBulkCreateData
1721
+ ): CancelablePromise<PriceControllerBulkCreateResponse> {
1722
+ return __request(OpenAPI, {
1723
+ method: 'POST',
1724
+ url: '/api/v1/{region}/bean/prices/bulk',
1725
+ path: {
1726
+ region: data.region
1727
+ },
1728
+ body: data.requestBody,
1729
+ mediaType: 'application/json'
1730
+ });
1731
+ }
1732
+ }
1733
+
1734
+ export class RecurringRulesService {
1735
+ /**
1736
+ * Create a new recurring rule
1737
+ * Creates a new recurring transaction rule for the authenticated user
1738
+ * @param data The data for the request.
1739
+ * @param data.region Region code for tenant context
1740
+ * @param data.requestBody
1741
+ * @returns RecurringRuleResponseDto Rule created successfully
1742
+ * @throws ApiError
1743
+ */
1744
+ public static recurringRuleControllerCreate(
1745
+ data: RecurringRuleControllerCreateData
1746
+ ): CancelablePromise<RecurringRuleControllerCreateResponse> {
1747
+ return __request(OpenAPI, {
1748
+ method: 'POST',
1749
+ url: '/api/v1/{region}/bean/recurring-rules',
1750
+ path: {
1751
+ region: data.region
1752
+ },
1753
+ body: data.requestBody,
1754
+ mediaType: 'application/json',
1755
+ errors: {
1756
+ 400: 'Invalid input data (e.g., autoCreate without accounts)',
1757
+ 409: 'Rule with same name already exists'
1758
+ }
1759
+ });
1760
+ }
1761
+
1762
+ /**
1763
+ * List recurring rules
1764
+ * Returns all recurring rules for the authenticated user with optional filtering
1765
+ * @param data The data for the request.
1766
+ * @param data.region Region code for tenant context
1767
+ * @param data.isActive Filter by active status
1768
+ * @param data.frequency Filter by frequency (WEEKLY, MONTHLY, etc.)
1769
+ * @param data.hasAutoCreate Filter by autoCreate enabled
1770
+ * @returns RecurringRuleResponseDto Rules retrieved successfully
1771
+ * @throws ApiError
1772
+ */
1773
+ public static recurringRuleControllerFindAll(
1774
+ data: RecurringRuleControllerFindAllData
1775
+ ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
1776
+ return __request(OpenAPI, {
1777
+ method: 'GET',
1778
+ url: '/api/v1/{region}/bean/recurring-rules',
1779
+ path: {
1780
+ region: data.region
1781
+ },
1782
+ query: {
1783
+ isActive: data.isActive,
1784
+ frequency: data.frequency,
1785
+ hasAutoCreate: data.hasAutoCreate
1786
+ }
1787
+ });
1788
+ }
1789
+
1790
+ /**
1791
+ * Create recurring rule from transaction
1792
+ * Auto-creates a recurring rule using transaction data. User only confirms frequency.
1793
+ * @param data The data for the request.
1794
+ * @param data.transactionId Source transaction ID
1795
+ * @param data.region Region code for tenant context
1796
+ * @param data.requestBody
1797
+ * @returns RecurringRuleResponseDto Rule created successfully
1798
+ * @throws ApiError
1799
+ */
1800
+ public static recurringRuleControllerCreateFromTransaction(
1801
+ data: RecurringRuleControllerCreateFromTransactionData
1802
+ ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
1803
+ return __request(OpenAPI, {
1804
+ method: 'POST',
1805
+ url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
1806
+ path: {
1807
+ transactionId: data.transactionId,
1808
+ region: data.region
1809
+ },
1810
+ body: data.requestBody,
1811
+ mediaType: 'application/json',
1812
+ errors: {
1813
+ 404: 'Transaction not found',
1814
+ 409: 'Rule with same name already exists or transaction already linked'
1815
+ }
1816
+ });
1817
+ }
1818
+
1819
+ /**
1820
+ * Get recurring rule by ID
1821
+ * Returns a specific recurring rule with its details
1822
+ * @param data The data for the request.
1823
+ * @param data.id Rule ID
1824
+ * @param data.region Region code for tenant context
1825
+ * @returns RecurringRuleResponseDto Rule retrieved successfully
1826
+ * @throws ApiError
1827
+ */
1828
+ public static recurringRuleControllerFindOne(
1829
+ data: RecurringRuleControllerFindOneData
1830
+ ): CancelablePromise<RecurringRuleControllerFindOneResponse> {
1831
+ return __request(OpenAPI, {
1832
+ method: 'GET',
1833
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
1834
+ path: {
1835
+ id: data.id,
1836
+ region: data.region
1837
+ },
1838
+ errors: {
1839
+ 404: 'Rule not found'
1840
+ }
1841
+ });
1842
+ }
1843
+
1844
+ /**
1845
+ * Update recurring rule
1846
+ * Updates an existing recurring rule
1847
+ * @param data The data for the request.
1848
+ * @param data.id Rule ID
1849
+ * @param data.region Region code for tenant context
1850
+ * @param data.requestBody
1851
+ * @returns RecurringRuleResponseDto Rule updated successfully
1852
+ * @throws ApiError
1853
+ */
1854
+ public static recurringRuleControllerUpdate(
1855
+ data: RecurringRuleControllerUpdateData
1856
+ ): CancelablePromise<RecurringRuleControllerUpdateResponse> {
1857
+ return __request(OpenAPI, {
1858
+ method: 'PATCH',
1859
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
1860
+ path: {
1861
+ id: data.id,
1862
+ region: data.region
1863
+ },
1864
+ body: data.requestBody,
1865
+ mediaType: 'application/json',
1866
+ errors: {
1867
+ 400: 'Invalid input data',
1868
+ 404: 'Rule not found'
1869
+ }
1870
+ });
1871
+ }
1872
+
1873
+ /**
1874
+ * Delete recurring rule
1875
+ * Soft deletes a recurring rule (sets isActive to false)
1876
+ * @param data The data for the request.
1877
+ * @param data.id Rule ID
1878
+ * @param data.region Region code for tenant context
1879
+ * @returns void Rule deleted successfully
1880
+ * @throws ApiError
1665
1881
  */
1666
1882
  public static recurringRuleControllerDelete(
1667
1883
  data: RecurringRuleControllerDeleteData
@@ -1945,279 +2161,158 @@ export class RecurringForecastService {
1945
2161
  }
1946
2162
  }
1947
2163
 
1948
- export class BeanTransactionRulesService {
2164
+ export class ReportingService {
1949
2165
  /**
1950
- * Create a new transaction rule (or upsert if upsertByPayee=true)
1951
- * Creates a new rule. If upsertByPayee=true, updates existing rule matching payeeKeywords[0] instead of creating duplicate.
2166
+ * Get portfolio value trends
2167
+ *
2168
+ * Returns time series data of portfolio net worth.
2169
+ *
2170
+ * **Multi-currency Support:**
2171
+ * - `series[].byCurrency` - Currency breakdown for each data point
2172
+ * - `byCurrency` - Separate time series grouped by currency
2173
+ * - `warnings` - Exchange rate warnings if conversion failed
2174
+ *
2175
+ * **Parameters:**
2176
+ * - `period`: Time period (1m, 3m, 6m, 1y)
2177
+ * - `granularity`: Data granularity (day, week, month)
2178
+ *
1952
2179
  * @param data The data for the request.
1953
2180
  * @param data.region Region code for tenant context
1954
- * @param data.requestBody
1955
- * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
2181
+ * @param data.period Time period
2182
+ * @param data.granularity Data granularity
2183
+ * @returns PortfolioTrendsResponseDto Trends retrieved successfully
1956
2184
  * @throws ApiError
1957
2185
  */
1958
- public static transactionRuleControllerCreate(
1959
- data: TransactionRuleControllerCreateData
1960
- ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2186
+ public static reportingControllerGetPortfolioTrends(
2187
+ data: ReportingControllerGetPortfolioTrendsData
2188
+ ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
1961
2189
  return __request(OpenAPI, {
1962
- method: 'POST',
1963
- url: '/api/v1/{region}/bean/transaction-rules',
2190
+ method: 'GET',
2191
+ url: '/api/v1/{region}/reporting/portfolio/trends',
1964
2192
  path: {
1965
2193
  region: data.region
1966
2194
  },
1967
- body: data.requestBody,
1968
- mediaType: 'application/json',
2195
+ query: {
2196
+ period: data.period,
2197
+ granularity: data.granularity
2198
+ },
1969
2199
  errors: {
1970
- 400: 'Validation failed',
1971
- 401: 'Unauthorized',
1972
- 409: 'Resource conflict - another process is updating this rule'
2200
+ 401: 'User not authenticated'
1973
2201
  }
1974
2202
  });
1975
2203
  }
1976
2204
 
1977
2205
  /**
1978
- * Get all transaction rules for user
2206
+ * Get cash-flow trends
2207
+ *
2208
+ * Monthly income / expense / netSavings over a fixed N-month window
2209
+ * (current month + N−1 prior). Missing months are zero-filled (flow metric).
2210
+ *
2211
+ * **Parameters:**
2212
+ * - `period`: 1m | 3m | 6m | 1y (default 6m)
2213
+ * - `granularity`: accepted for API symmetry; v1 returns month buckets
2214
+ *
1979
2215
  * @param data The data for the request.
1980
2216
  * @param data.region Region code for tenant context
1981
- * @param data.limit Max results per page (default: 20, max: 100)
1982
- * @param data.offset Pagination offset (default: 0)
1983
- * @param data.enabled Filter by enabled status
1984
- * @param data.learningSource Filter by learning source. Omit this parameter or pass empty string to get manually created rules (learningSource is null in database).
1985
- * @param data.autoApplyEnabled Filter by auto-apply status
1986
- * @returns TransactionRuleListResponseDto List of rules
2217
+ * @param data.period Time period
2218
+ * @param data.granularity Data granularity (accepted for API symmetry; v1 returns month buckets)
2219
+ * @returns CashFlowTrendsResponseDto Cash-flow trends retrieved successfully
1987
2220
  * @throws ApiError
1988
2221
  */
1989
- public static transactionRuleControllerList(
1990
- data: TransactionRuleControllerListData
1991
- ): CancelablePromise<TransactionRuleControllerListResponse> {
2222
+ public static reportingControllerGetCashFlowTrends(
2223
+ data: ReportingControllerGetCashFlowTrendsData
2224
+ ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
1992
2225
  return __request(OpenAPI, {
1993
2226
  method: 'GET',
1994
- url: '/api/v1/{region}/bean/transaction-rules',
2227
+ url: '/api/v1/{region}/reporting/cash-flow/trends',
1995
2228
  path: {
1996
2229
  region: data.region
1997
2230
  },
1998
2231
  query: {
1999
- limit: data.limit,
2000
- offset: data.offset,
2001
- enabled: data.enabled,
2002
- learningSource: data.learningSource,
2003
- autoApplyEnabled: data.autoApplyEnabled
2232
+ period: data.period,
2233
+ granularity: data.granularity
2004
2234
  },
2005
2235
  errors: {
2006
- 401: 'Unauthorized'
2236
+ 401: 'User not authenticated'
2007
2237
  }
2008
2238
  });
2009
2239
  }
2010
2240
 
2011
2241
  /**
2012
- * Validate transaction rule configuration
2013
- * @param data The data for the request.
2014
- * @param data.region Region code for tenant context
2015
- * @param data.requestBody
2016
- * @returns ValidateRuleResponseDto Validation result
2017
- * @throws ApiError
2018
- */
2019
- public static transactionRuleControllerValidate(
2020
- data: TransactionRuleControllerValidateData
2021
- ): CancelablePromise<TransactionRuleControllerValidateResponse> {
2022
- return __request(OpenAPI, {
2023
- method: 'POST',
2024
- url: '/api/v1/{region}/bean/transaction-rules/validate',
2025
- path: {
2026
- region: data.region
2027
- },
2028
- body: data.requestBody,
2029
- mediaType: 'application/json',
2030
- errors: {
2031
- 400: 'Validation failed',
2032
- 401: 'Unauthorized'
2033
- }
2034
- });
2035
- }
2036
-
2037
- /**
2038
- * Bulk create transaction rules
2242
+ * Generate portfolio snapshot
2243
+ *
2244
+ * Manually generate a portfolio snapshot for a specific date.
2245
+ *
2246
+ * **Multi-currency Support:**
2247
+ * - Fetches balances grouped by currency
2248
+ * - Uses user's baseCurrency setting for conversion
2249
+ * - Stores exchange rates and warnings
2250
+ *
2251
+ * **Use Cases:**
2252
+ * - Testing snapshot generation
2253
+ * - Force regeneration after data correction
2254
+ * - Initial setup for new users
2255
+ *
2039
2256
  * @param data The data for the request.
2040
2257
  * @param data.region Region code for tenant context
2041
- * @param data.requestBody
2042
- * @returns BulkCreateRulesResponseDto Bulk create completed
2258
+ * @param data.requestBody Optional date (defaults to today)
2259
+ * @returns GenerateSnapshotResponse Snapshot generated successfully
2043
2260
  * @throws ApiError
2044
2261
  */
2045
- public static transactionRuleControllerBulkCreate(
2046
- data: TransactionRuleControllerBulkCreateData
2047
- ): CancelablePromise<TransactionRuleControllerBulkCreateResponse> {
2262
+ public static reportingControllerGenerateSnapshot(
2263
+ data: ReportingControllerGenerateSnapshotData
2264
+ ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
2048
2265
  return __request(OpenAPI, {
2049
2266
  method: 'POST',
2050
- url: '/api/v1/{region}/bean/transaction-rules/bulk',
2051
- path: {
2052
- region: data.region
2053
- },
2054
- body: data.requestBody,
2055
- mediaType: 'application/json',
2056
- errors: {
2057
- 400: 'Invalid bulk create data',
2058
- 401: 'Unauthorized'
2059
- }
2060
- });
2061
- }
2062
-
2063
- /**
2064
- * Export transaction rules
2065
- * @param data The data for the request.
2066
- * @param data.format Export format (currently only JSON supported)
2067
- * @param data.region Region code for tenant context
2068
- * @returns ExportRulesResponseDto Exported rules
2069
- * @throws ApiError
2070
- */
2071
- public static transactionRuleControllerExport(
2072
- data: TransactionRuleControllerExportData
2073
- ): CancelablePromise<TransactionRuleControllerExportResponse> {
2074
- return __request(OpenAPI, {
2075
- method: 'GET',
2076
- url: '/api/v1/{region}/bean/transaction-rules/export/{format}',
2077
- path: {
2078
- format: data.format,
2079
- region: data.region
2080
- },
2081
- errors: {
2082
- 400: 'Unsupported format',
2083
- 401: 'Unauthorized'
2084
- }
2085
- });
2086
- }
2087
-
2088
- /**
2089
- * Get transaction rule statistics
2090
- * @param data The data for the request.
2091
- * @param data.period Statistics time period
2092
- * @param data.region Region code for tenant context
2093
- * @returns RuleStatisticsResponseDto Rule statistics
2094
- * @throws ApiError
2095
- */
2096
- public static transactionRuleControllerGetStatistics(
2097
- data: TransactionRuleControllerGetStatisticsData
2098
- ): CancelablePromise<TransactionRuleControllerGetStatisticsResponse> {
2099
- return __request(OpenAPI, {
2100
- method: 'GET',
2101
- url: '/api/v1/{region}/bean/transaction-rules/statistics/{period}',
2102
- path: {
2103
- period: data.period,
2104
- region: data.region
2105
- },
2106
- errors: {
2107
- 401: 'Unauthorized'
2108
- }
2109
- });
2110
- }
2111
-
2112
- /**
2113
- * Get transaction rule detail
2114
- * @param data The data for the request.
2115
- * @param data.ruleId Rule ID
2116
- * @param data.region Region code for tenant context
2117
- * @returns TransactionRuleResponseDto Rule details
2118
- * @throws ApiError
2119
- */
2120
- public static transactionRuleControllerGetDetail(
2121
- data: TransactionRuleControllerGetDetailData
2122
- ): CancelablePromise<TransactionRuleControllerGetDetailResponse> {
2123
- return __request(OpenAPI, {
2124
- method: 'GET',
2125
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2126
- path: {
2127
- ruleId: data.ruleId,
2128
- region: data.region
2129
- },
2130
- errors: {
2131
- 401: 'Unauthorized',
2132
- 403: 'Forbidden - not owner of rule',
2133
- 404: 'Rule not found'
2134
- }
2135
- });
2136
- }
2137
-
2138
- /**
2139
- * Update a transaction rule
2140
- * @param data The data for the request.
2141
- * @param data.ruleId Rule ID to update
2142
- * @param data.region Region code for tenant context
2143
- * @param data.requestBody
2144
- * @returns TransactionRuleResponseDto Rule updated successfully
2145
- * @throws ApiError
2146
- */
2147
- public static transactionRuleControllerUpdate(
2148
- data: TransactionRuleControllerUpdateData
2149
- ): CancelablePromise<TransactionRuleControllerUpdateResponse> {
2150
- return __request(OpenAPI, {
2151
- method: 'PUT',
2152
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2267
+ url: '/api/v1/{region}/reporting/snapshots/generate',
2153
2268
  path: {
2154
- ruleId: data.ruleId,
2155
2269
  region: data.region
2156
2270
  },
2157
2271
  body: data.requestBody,
2158
2272
  mediaType: 'application/json',
2159
2273
  errors: {
2160
- 400: 'Validation failed',
2161
- 401: 'Unauthorized',
2162
- 403: 'Forbidden - not owner of rule',
2163
- 404: 'Rule not found',
2164
- 409: 'Resource conflict - rule is being modified by another process'
2165
- }
2166
- });
2167
- }
2168
-
2169
- /**
2170
- * Delete a transaction rule
2171
- * @param data The data for the request.
2172
- * @param data.ruleId Rule ID to delete
2173
- * @param data.region Region code for tenant context
2174
- * @returns void Rule deleted successfully
2175
- * @throws ApiError
2176
- */
2177
- public static transactionRuleControllerDelete(
2178
- data: TransactionRuleControllerDeleteData
2179
- ): CancelablePromise<TransactionRuleControllerDeleteResponse> {
2180
- return __request(OpenAPI, {
2181
- method: 'DELETE',
2182
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2183
- path: {
2184
- ruleId: data.ruleId,
2185
- region: data.region
2186
- },
2187
- errors: {
2188
- 401: 'Unauthorized',
2189
- 403: 'Forbidden - not owner of rule',
2190
- 404: 'Rule not found',
2191
- 409: 'Resource conflict - rule is being modified by another process'
2274
+ 400: 'Invalid date format',
2275
+ 401: 'User not authenticated'
2192
2276
  }
2193
2277
  });
2194
2278
  }
2195
2279
 
2196
2280
  /**
2197
- * Test rule matching
2281
+ * Backfill portfolio snapshots
2282
+ *
2283
+ * Generate snapshots for a date range (historical data backfill).
2284
+ *
2285
+ * **Multi-currency Support:**
2286
+ * - Each snapshot includes multi-currency data
2287
+ * - Uses exchange rates available at generation time
2288
+ * - Warnings stored for missing exchange rates
2289
+ *
2290
+ * **Best Practices:**
2291
+ * - Use for initial setup after account configuration
2292
+ * - Run during low-traffic periods for large date ranges
2293
+ * - Existing snapshots are skipped (not regenerated)
2294
+ *
2198
2295
  * @param data The data for the request.
2199
- * @param data.ruleId Rule ID to test
2200
2296
  * @param data.region Region code for tenant context
2201
2297
  * @param data.requestBody
2202
- * @returns TestRuleResponseDto Test result
2298
+ * @returns BackfillSnapshotsResponse Backfill completed successfully
2203
2299
  * @throws ApiError
2204
2300
  */
2205
- public static transactionRuleControllerTest(
2206
- data: TransactionRuleControllerTestData
2207
- ): CancelablePromise<TransactionRuleControllerTestResponse> {
2301
+ public static reportingControllerBackfillSnapshots(
2302
+ data: ReportingControllerBackfillSnapshotsData
2303
+ ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
2208
2304
  return __request(OpenAPI, {
2209
2305
  method: 'POST',
2210
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}/test',
2306
+ url: '/api/v1/{region}/reporting/snapshots/backfill',
2211
2307
  path: {
2212
- ruleId: data.ruleId,
2213
2308
  region: data.region
2214
2309
  },
2215
2310
  body: data.requestBody,
2216
2311
  mediaType: 'application/json',
2217
2312
  errors: {
2218
- 401: 'Unauthorized',
2219
- 403: 'Forbidden - not owner of rule',
2220
- 404: 'Rule not found'
2313
+ 400: 'Invalid date format or range',
2314
+ 401: 'User not authenticated',
2315
+ 409: 'Backfill already in progress for this user'
2221
2316
  }
2222
2317
  });
2223
2318
  }
@@ -2269,7 +2364,7 @@ export class UsersService {
2269
2364
  * Create a new account with auto-generated access token. Protected by Cloudflare Turnstile to prevent automated signup (when enabled).
2270
2365
  * @param data The data for the request.
2271
2366
  * @param data.requestBody
2272
- * @returns unknown User created successfully
2367
+ * @returns SignupResponseDto User created successfully
2273
2368
  * @throws ApiError
2274
2369
  */
2275
2370
  public static userControllerSignupUser(
@@ -2478,1085 +2573,1259 @@ export class PropertiesService {
2478
2573
  }
2479
2574
  }
2480
2575
 
2481
- export class LifeEventsService {
2576
+ export class BeanTransactionRulesService {
2482
2577
  /**
2483
- * Create a new life event
2484
- * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2578
+ * Create a new transaction rule (or upsert if upsertByPayee=true)
2579
+ * Creates a new rule. If upsertByPayee=true, updates existing rule matching payeeKeywords[0] instead of creating duplicate.
2485
2580
  * @param data The data for the request.
2486
- * @param data.region Region code for tenant context (decorative for life events)
2581
+ * @param data.region Region code for tenant context
2487
2582
  * @param data.requestBody
2488
- * @returns EventResponseDto Life event created successfully
2583
+ * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
2489
2584
  * @throws ApiError
2490
2585
  */
2491
- public static eventControllerCreate(
2492
- data: EventControllerCreateData
2493
- ): CancelablePromise<EventControllerCreateResponse> {
2586
+ public static transactionRuleControllerCreate(
2587
+ data: TransactionRuleControllerCreateData
2588
+ ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2494
2589
  return __request(OpenAPI, {
2495
2590
  method: 'POST',
2496
- url: '/api/v1/{region}/bean/events',
2591
+ url: '/api/v1/{region}/bean/transaction-rules',
2497
2592
  path: {
2498
2593
  region: data.region
2499
2594
  },
2500
2595
  body: data.requestBody,
2501
2596
  mediaType: 'application/json',
2502
2597
  errors: {
2503
- 409: 'Life event already exists for this (userId, type, date) combination'
2598
+ 400: 'Validation failed',
2599
+ 401: 'Unauthorized',
2600
+ 409: 'Resource conflict - another process is updating this rule'
2504
2601
  }
2505
2602
  });
2506
2603
  }
2507
2604
 
2508
2605
  /**
2509
- * List user life events
2510
- * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2606
+ * Get all transaction rules for user
2511
2607
  * @param data The data for the request.
2512
- * @param data.region Region code for tenant context (decorative for life events)
2513
- * @param data.type Filter by life event type (exact match)
2514
- * @param data.q Search term for description (case-insensitive partial match)
2515
- * @param data.from Filter life events from this date (ISO 8601 format)
2516
- * @param data.to Filter life events to this date (ISO 8601 format)
2517
- * @param data.page Page number for pagination (default: 1)
2518
- * @param data.limit Number of items per page (default: 20, max: 100)
2519
- * @returns EventListResponseDto Life events retrieved successfully
2608
+ * @param data.region Region code for tenant context
2609
+ * @param data.limit Max results per page (default: 20, max: 100)
2610
+ * @param data.offset Pagination offset (default: 0)
2611
+ * @param data.enabled Filter by enabled status
2612
+ * @param data.learningSource Filter by learning source. Omit this parameter or pass empty string to get manually created rules (learningSource is null in database).
2613
+ * @param data.autoApplyEnabled Filter by auto-apply status
2614
+ * @returns TransactionRuleListResponseDto List of rules
2520
2615
  * @throws ApiError
2521
2616
  */
2522
- public static eventControllerFindAll(
2523
- data: EventControllerFindAllData
2524
- ): CancelablePromise<EventControllerFindAllResponse> {
2525
- return __request(OpenAPI, {
2526
- method: 'GET',
2527
- url: '/api/v1/{region}/bean/events',
2617
+ public static transactionRuleControllerList(
2618
+ data: TransactionRuleControllerListData
2619
+ ): CancelablePromise<TransactionRuleControllerListResponse> {
2620
+ return __request(OpenAPI, {
2621
+ method: 'GET',
2622
+ url: '/api/v1/{region}/bean/transaction-rules',
2528
2623
  path: {
2529
2624
  region: data.region
2530
2625
  },
2531
2626
  query: {
2532
- type: data.type,
2533
- q: data.q,
2534
- from: data.from,
2535
- to: data.to,
2536
- page: data.page,
2537
- limit: data.limit
2627
+ limit: data.limit,
2628
+ offset: data.offset,
2629
+ enabled: data.enabled,
2630
+ learningSource: data.learningSource,
2631
+ autoApplyEnabled: data.autoApplyEnabled
2632
+ },
2633
+ errors: {
2634
+ 401: 'Unauthorized'
2538
2635
  }
2539
2636
  });
2540
2637
  }
2541
2638
 
2542
2639
  /**
2543
- * Get life event by ID
2544
- * Returns a single life event by its ID. Returns ETag header.
2640
+ * Validate transaction rule configuration
2545
2641
  * @param data The data for the request.
2546
- * @param data.id Life event ID
2547
- * @param data.region Region code for tenant context (decorative for life events)
2548
- * @returns EventResponseDto Life event retrieved successfully
2642
+ * @param data.region Region code for tenant context
2643
+ * @param data.requestBody
2644
+ * @returns ValidateRuleResponseDto Validation result
2549
2645
  * @throws ApiError
2550
2646
  */
2551
- public static eventControllerFindOne(
2552
- data: EventControllerFindOneData
2553
- ): CancelablePromise<EventControllerFindOneResponse> {
2647
+ public static transactionRuleControllerValidate(
2648
+ data: TransactionRuleControllerValidateData
2649
+ ): CancelablePromise<TransactionRuleControllerValidateResponse> {
2554
2650
  return __request(OpenAPI, {
2555
- method: 'GET',
2556
- url: '/api/v1/{region}/bean/events/{id}',
2651
+ method: 'POST',
2652
+ url: '/api/v1/{region}/bean/transaction-rules/validate',
2557
2653
  path: {
2558
- id: data.id,
2559
2654
  region: data.region
2560
2655
  },
2656
+ body: data.requestBody,
2657
+ mediaType: 'application/json',
2561
2658
  errors: {
2562
- 404: 'Life event not found'
2659
+ 400: 'Validation failed',
2660
+ 401: 'Unauthorized'
2563
2661
  }
2564
2662
  });
2565
2663
  }
2566
2664
 
2567
2665
  /**
2568
- * Update a life event
2569
- * Updates an existing life event. If If-Match header is provided, performs optimistic concurrency check; mismatched updatedAt returns 412.
2666
+ * Bulk create transaction rules
2570
2667
  * @param data The data for the request.
2571
- * @param data.id Life event ID
2572
- * @param data.region Region code for tenant context (decorative for life events)
2668
+ * @param data.region Region code for tenant context
2573
2669
  * @param data.requestBody
2574
- * @returns EventResponseDto Life event updated successfully
2670
+ * @returns BulkCreateRulesResponseDto Bulk create completed
2575
2671
  * @throws ApiError
2576
2672
  */
2577
- public static eventControllerUpdate(
2578
- data: EventControllerUpdateData
2579
- ): CancelablePromise<EventControllerUpdateResponse> {
2673
+ public static transactionRuleControllerBulkCreate(
2674
+ data: TransactionRuleControllerBulkCreateData
2675
+ ): CancelablePromise<TransactionRuleControllerBulkCreateResponse> {
2580
2676
  return __request(OpenAPI, {
2581
- method: 'PUT',
2582
- url: '/api/v1/{region}/bean/events/{id}',
2677
+ method: 'POST',
2678
+ url: '/api/v1/{region}/bean/transaction-rules/bulk',
2583
2679
  path: {
2584
- id: data.id,
2585
2680
  region: data.region
2586
2681
  },
2587
2682
  body: data.requestBody,
2588
2683
  mediaType: 'application/json',
2589
2684
  errors: {
2590
- 400: 'If-Match header is not a valid ISO 8601 date',
2591
- 404: 'Life event not found',
2592
- 409: 'Updated event conflicts with an existing (userId, type, date) combination',
2593
- 412: 'If-Match precondition failed (updatedAt mismatch)'
2685
+ 400: 'Invalid bulk create data',
2686
+ 401: 'Unauthorized'
2594
2687
  }
2595
2688
  });
2596
2689
  }
2597
2690
 
2598
2691
  /**
2599
- * Delete a life event
2600
- * Deletes a life event entry (hard delete). Returns 204.
2692
+ * Export transaction rules
2601
2693
  * @param data The data for the request.
2602
- * @param data.id Life event ID
2603
- * @param data.region Region code for tenant context (decorative for life events)
2604
- * @returns void Life event deleted successfully
2694
+ * @param data.format Export format (currently only JSON supported)
2695
+ * @param data.region Region code for tenant context
2696
+ * @returns ExportRulesResponseDto Exported rules
2605
2697
  * @throws ApiError
2606
2698
  */
2607
- public static eventControllerDelete(
2608
- data: EventControllerDeleteData
2609
- ): CancelablePromise<EventControllerDeleteResponse> {
2699
+ public static transactionRuleControllerExport(
2700
+ data: TransactionRuleControllerExportData
2701
+ ): CancelablePromise<TransactionRuleControllerExportResponse> {
2610
2702
  return __request(OpenAPI, {
2611
- method: 'DELETE',
2612
- url: '/api/v1/{region}/bean/events/{id}',
2703
+ method: 'GET',
2704
+ url: '/api/v1/{region}/bean/transaction-rules/export/{format}',
2613
2705
  path: {
2614
- id: data.id,
2706
+ format: data.format,
2615
2707
  region: data.region
2616
2708
  },
2617
2709
  errors: {
2618
- 404: 'Life event not found'
2710
+ 400: 'Unsupported format',
2711
+ 401: 'Unauthorized'
2619
2712
  }
2620
2713
  });
2621
2714
  }
2622
2715
 
2623
2716
  /**
2624
- * Slice time-series by a life event (Phase 79)
2625
- * Returns aggregated time-series for postings matching accountPattern within the half-open date range of the given life event.
2717
+ * Get transaction rule statistics
2626
2718
  * @param data The data for the request.
2627
- * @param data.id Life event ID
2628
- * @param data.accountPattern
2629
- * @param data.granularity
2630
- * @param data.region Region code for tenant context (decorative for life events)
2631
- * @returns unknown Time-series sliced by the life event range
2719
+ * @param data.period Statistics time period
2720
+ * @param data.region Region code for tenant context
2721
+ * @returns RuleStatisticsResponseDto Rule statistics
2632
2722
  * @throws ApiError
2633
2723
  */
2634
- public static eventControllerGetSlice(
2635
- data: EventControllerGetSliceData
2636
- ): CancelablePromise<EventControllerGetSliceResponse> {
2724
+ public static transactionRuleControllerGetStatistics(
2725
+ data: TransactionRuleControllerGetStatisticsData
2726
+ ): CancelablePromise<TransactionRuleControllerGetStatisticsResponse> {
2637
2727
  return __request(OpenAPI, {
2638
2728
  method: 'GET',
2639
- url: '/api/v1/{region}/bean/events/{id}/slice',
2729
+ url: '/api/v1/{region}/bean/transaction-rules/statistics/{period}',
2640
2730
  path: {
2641
- id: data.id,
2731
+ period: data.period,
2642
2732
  region: data.region
2643
2733
  },
2644
- query: {
2645
- accountPattern: data.accountPattern,
2646
- granularity: data.granularity
2647
- },
2648
2734
  errors: {
2649
- 400: 'accountPattern query param is empty',
2650
- 404: 'Life event not found'
2735
+ 401: 'Unauthorized'
2651
2736
  }
2652
2737
  });
2653
2738
  }
2654
- }
2655
2739
 
2656
- export class BeanExportService {
2657
2740
  /**
2658
- * Export Beancount ledger as ZIP
2659
- * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
2660
- * @returns unknown
2741
+ * Get transaction rule detail
2742
+ * @param data The data for the request.
2743
+ * @param data.ruleId Rule ID
2744
+ * @param data.region Region code for tenant context
2745
+ * @returns TransactionRuleResponseDto Rule details
2661
2746
  * @throws ApiError
2662
2747
  */
2663
- public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
2748
+ public static transactionRuleControllerGetDetail(
2749
+ data: TransactionRuleControllerGetDetailData
2750
+ ): CancelablePromise<TransactionRuleControllerGetDetailResponse> {
2664
2751
  return __request(OpenAPI, {
2665
2752
  method: 'GET',
2666
- url: '/api/v1/{region}/bean/export/beancount'
2753
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2754
+ path: {
2755
+ ruleId: data.ruleId,
2756
+ region: data.region
2757
+ },
2758
+ errors: {
2759
+ 401: 'Unauthorized',
2760
+ 403: 'Forbidden - not owner of rule',
2761
+ 404: 'Rule not found'
2762
+ }
2667
2763
  });
2668
2764
  }
2669
- }
2670
2765
 
2671
- export class BeanImportService {
2672
2766
  /**
2673
- * Import a bill file
2674
- * Upload and process a bill file (CSV, PDF, OFX, etc.). The system automatically identifies the file type, extracts transactions, validates them, and stores only validated transactions to the database. Maximum file size: 50MB. Only 1 import per user at a time (concurrent imports rejected with 429).
2767
+ * Update a transaction rule
2675
2768
  * @param data The data for the request.
2769
+ * @param data.ruleId Rule ID to update
2676
2770
  * @param data.region Region code for tenant context
2677
- * @param data.formData Bill file to import
2678
- * @returns ImportResultDto File imported successfully
2771
+ * @param data.requestBody
2772
+ * @returns TransactionRuleResponseDto Rule updated successfully
2679
2773
  * @throws ApiError
2680
2774
  */
2681
- public static fileImportControllerImportFile(
2682
- data: FileImportControllerImportFileData
2683
- ): CancelablePromise<FileImportControllerImportFileResponse> {
2775
+ public static transactionRuleControllerUpdate(
2776
+ data: TransactionRuleControllerUpdateData
2777
+ ): CancelablePromise<TransactionRuleControllerUpdateResponse> {
2684
2778
  return __request(OpenAPI, {
2685
- method: 'POST',
2686
- url: '/api/v1/{region}/bean/import/file',
2779
+ method: 'PUT',
2780
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2687
2781
  path: {
2782
+ ruleId: data.ruleId,
2688
2783
  region: data.region
2689
2784
  },
2690
- formData: data.formData,
2691
- mediaType: 'multipart/form-data',
2785
+ body: data.requestBody,
2786
+ mediaType: 'application/json',
2692
2787
  errors: {
2693
- 400: 'Bad request - file-format-unsupported or file-import-failed',
2694
- 413: 'Payload too large - file exceeds 50MB limit',
2695
- 429: 'Too many requests - user already has import in progress',
2696
- 500: 'Internal server error - DATABASE_ERROR'
2788
+ 400: 'Validation failed',
2789
+ 401: 'Unauthorized',
2790
+ 403: 'Forbidden - not owner of rule',
2791
+ 404: 'Rule not found',
2792
+ 409: 'Resource conflict - rule is being modified by another process'
2697
2793
  }
2698
2794
  });
2699
2795
  }
2700
2796
 
2701
2797
  /**
2702
- * Identify file type
2703
- * Upload a file to check if it can be processed by any registered importer. Does not perform actual import - useful for pre-validation. Uses user-specific importer configuration.
2798
+ * Delete a transaction rule
2704
2799
  * @param data The data for the request.
2800
+ * @param data.ruleId Rule ID to delete
2705
2801
  * @param data.region Region code for tenant context
2706
- * @param data.formData File to identify
2707
- * @returns IdentifyResultDto File identification result
2802
+ * @returns void Rule deleted successfully
2708
2803
  * @throws ApiError
2709
2804
  */
2710
- public static fileImportControllerIdentifyFile(
2711
- data: FileImportControllerIdentifyFileData
2712
- ): CancelablePromise<FileImportControllerIdentifyFileResponse> {
2805
+ public static transactionRuleControllerDelete(
2806
+ data: TransactionRuleControllerDeleteData
2807
+ ): CancelablePromise<TransactionRuleControllerDeleteResponse> {
2713
2808
  return __request(OpenAPI, {
2714
- method: 'POST',
2715
- url: '/api/v1/{region}/bean/import/identify',
2809
+ method: 'DELETE',
2810
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2716
2811
  path: {
2812
+ ruleId: data.ruleId,
2717
2813
  region: data.region
2718
2814
  },
2719
- formData: data.formData,
2720
- mediaType: 'multipart/form-data',
2721
2815
  errors: {
2722
- 400: 'Bad request - No file uploaded'
2816
+ 401: 'Unauthorized',
2817
+ 403: 'Forbidden - not owner of rule',
2818
+ 404: 'Rule not found',
2819
+ 409: 'Resource conflict - rule is being modified by another process'
2723
2820
  }
2724
2821
  });
2725
2822
  }
2726
2823
 
2727
2824
  /**
2728
- * Import a Beancount file in community format
2729
- * Upload a .beancount file to import. The system parses community-format paths, converts to internal format using category metadata, auto-creates accounts, and imports transactions with deduplication. Maximum file size: 50MB. Only 1 import per user at a time.
2825
+ * Test rule matching
2730
2826
  * @param data The data for the request.
2827
+ * @param data.ruleId Rule ID to test
2731
2828
  * @param data.region Region code for tenant context
2732
- * @param data.formData Beancount file to import
2733
- * @returns unknown Beancount file imported successfully
2829
+ * @param data.requestBody
2830
+ * @returns TestRuleResponseDto Test result
2734
2831
  * @throws ApiError
2735
2832
  */
2736
- public static fileImportControllerImportBeancount(
2737
- data: FileImportControllerImportBeancountData
2738
- ): CancelablePromise<FileImportControllerImportBeancountResponse> {
2833
+ public static transactionRuleControllerTest(
2834
+ data: TransactionRuleControllerTestData
2835
+ ): CancelablePromise<TransactionRuleControllerTestResponse> {
2739
2836
  return __request(OpenAPI, {
2740
2837
  method: 'POST',
2741
- url: '/api/v1/{region}/bean/import/beancount',
2838
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}/test',
2742
2839
  path: {
2840
+ ruleId: data.ruleId,
2743
2841
  region: data.region
2744
2842
  },
2745
- formData: data.formData,
2746
- mediaType: 'multipart/form-data',
2843
+ body: data.requestBody,
2844
+ mediaType: 'application/json',
2747
2845
  errors: {
2748
- 400: 'Bad request - invalid file or no file uploaded'
2846
+ 401: 'Unauthorized',
2847
+ 403: 'Forbidden - not owner of rule',
2848
+ 404: 'Rule not found'
2749
2849
  }
2750
2850
  });
2751
2851
  }
2852
+ }
2752
2853
 
2854
+ export class LifeEventsService {
2753
2855
  /**
2754
- * Get importer configuration
2755
- * Returns the current configuration for the specified importer. Creates default configuration if none exists.
2856
+ * Create a new life event
2857
+ * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2756
2858
  * @param data The data for the request.
2757
- * @param data.importerId Importer identifier. Supported importers: alipay, alipay-web, wechat, boc, boc-credit, ccb, cmb, cmbc, cmbc-credit, icbc, icbc-credit, hsbc-hk-credit, hsbc-hk-debit
2758
- * @param data.region Region code for tenant context
2759
- * @returns ImporterConfigDto Configuration retrieved successfully
2859
+ * @param data.region Region code for tenant context (decorative for life events)
2860
+ * @param data.requestBody
2861
+ * @returns EventResponseDto Life event created successfully
2760
2862
  * @throws ApiError
2761
2863
  */
2762
- public static importerConfigControllerGetConfig(
2763
- data: ImporterConfigControllerGetConfigData
2764
- ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
2864
+ public static eventControllerCreate(
2865
+ data: EventControllerCreateData
2866
+ ): CancelablePromise<EventControllerCreateResponse> {
2765
2867
  return __request(OpenAPI, {
2766
- method: 'GET',
2767
- url: '/api/v1/{region}/bean/import/config/{importerId}',
2868
+ method: 'POST',
2869
+ url: '/api/v1/{region}/bean/events',
2768
2870
  path: {
2769
- importerId: data.importerId,
2770
2871
  region: data.region
2771
2872
  },
2772
- errors: {
2773
- 400: 'Invalid input - Unsupported importer',
2774
- 401: 'Unauthorized - Authentication required'
2873
+ body: data.requestBody,
2874
+ mediaType: 'application/json',
2875
+ errors: {
2876
+ 409: 'Life event already exists for this (userId, type, date) combination'
2775
2877
  }
2776
2878
  });
2777
2879
  }
2778
2880
 
2779
2881
  /**
2780
- * Update importer configuration
2781
- * Updates the configuration for the specified importer. Partial updates are supported.
2882
+ * List user life events
2883
+ * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2782
2884
  * @param data The data for the request.
2783
- * @param data.importerId Importer identifier. Supported importers: alipay, alipay-web, wechat, boc, boc-credit, ccb, cmb, cmbc, cmbc-credit, icbc, icbc-credit, hsbc-hk-credit, hsbc-hk-debit
2784
- * @param data.region Region code for tenant context
2785
- * @param data.requestBody Partial configuration update. Only provided fields will be updated.
2786
- * @returns ImporterConfigDto Configuration updated successfully
2885
+ * @param data.region Region code for tenant context (decorative for life events)
2886
+ * @param data.type Filter by life event type (exact match)
2887
+ * @param data.q Search term for description (case-insensitive partial match)
2888
+ * @param data.from Filter life events from this date (ISO 8601 format)
2889
+ * @param data.to Filter life events to this date (ISO 8601 format)
2890
+ * @param data.page Page number for pagination (default: 1)
2891
+ * @param data.limit Number of items per page (default: 20, max: 100)
2892
+ * @returns EventListResponseDto Life events retrieved successfully
2787
2893
  * @throws ApiError
2788
2894
  */
2789
- public static importerConfigControllerUpdateConfig(
2790
- data: ImporterConfigControllerUpdateConfigData
2791
- ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
2895
+ public static eventControllerFindAll(
2896
+ data: EventControllerFindAllData
2897
+ ): CancelablePromise<EventControllerFindAllResponse> {
2792
2898
  return __request(OpenAPI, {
2793
- method: 'PUT',
2794
- url: '/api/v1/{region}/bean/import/config/{importerId}',
2899
+ method: 'GET',
2900
+ url: '/api/v1/{region}/bean/events',
2795
2901
  path: {
2796
- importerId: data.importerId,
2797
2902
  region: data.region
2798
2903
  },
2799
- body: data.requestBody,
2800
- mediaType: 'application/json',
2801
- errors: {
2802
- 400: 'Invalid input - Validation failed',
2803
- 404: 'Configuration not found'
2904
+ query: {
2905
+ type: data.type,
2906
+ q: data.q,
2907
+ from: data.from,
2908
+ to: data.to,
2909
+ page: data.page,
2910
+ limit: data.limit
2804
2911
  }
2805
2912
  });
2806
2913
  }
2807
2914
 
2808
2915
  /**
2809
- * Reset configuration to default
2810
- * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
2916
+ * Get life event by ID
2917
+ * Returns a single life event by its ID. Returns ETag header.
2811
2918
  * @param data The data for the request.
2812
- * @param data.importerId Importer identifier. Supported importers: alipay, alipay-web, wechat, boc, boc-credit, ccb, cmb, cmbc, cmbc-credit, icbc, icbc-credit, hsbc-hk-credit, hsbc-hk-debit
2813
- * @param data.region Region code for tenant context
2814
- * @returns ImporterConfigDto Configuration reset successfully
2919
+ * @param data.id Life event ID
2920
+ * @param data.region Region code for tenant context (decorative for life events)
2921
+ * @returns EventResponseDto Life event retrieved successfully
2815
2922
  * @throws ApiError
2816
2923
  */
2817
- public static importerConfigControllerResetConfig(
2818
- data: ImporterConfigControllerResetConfigData
2819
- ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
2924
+ public static eventControllerFindOne(
2925
+ data: EventControllerFindOneData
2926
+ ): CancelablePromise<EventControllerFindOneResponse> {
2820
2927
  return __request(OpenAPI, {
2821
- method: 'POST',
2822
- url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
2928
+ method: 'GET',
2929
+ url: '/api/v1/{region}/bean/events/{id}',
2823
2930
  path: {
2824
- importerId: data.importerId,
2931
+ id: data.id,
2825
2932
  region: data.region
2826
2933
  },
2827
2934
  errors: {
2828
- 400: 'Invalid input - Unsupported importer'
2935
+ 404: 'Life event not found'
2829
2936
  }
2830
2937
  });
2831
2938
  }
2832
- }
2833
-
2834
- export class BeanPlatformsService {
2835
- /**
2836
- * Get all platforms with statistics
2837
- * @returns unknown List of platforms with binding and account counts
2838
- * @throws ApiError
2839
- */
2840
- public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
2841
- return __request(OpenAPI, {
2842
- method: 'GET',
2843
- url: '/api/v1/bean/platforms'
2844
- });
2845
- }
2846
2939
 
2847
2940
  /**
2848
- * Create a new platform
2941
+ * Update a life event
2942
+ * Updates an existing life event. If If-Match header is provided, performs optimistic concurrency check; mismatched updatedAt returns 412.
2849
2943
  * @param data The data for the request.
2944
+ * @param data.id Life event ID
2945
+ * @param data.region Region code for tenant context (decorative for life events)
2850
2946
  * @param data.requestBody
2851
- * @returns unknown Platform created successfully
2947
+ * @returns EventResponseDto Life event updated successfully
2852
2948
  * @throws ApiError
2853
2949
  */
2854
- public static platformControllerCreate(
2855
- data: PlatformControllerCreateData
2856
- ): CancelablePromise<PlatformControllerCreateResponse> {
2950
+ public static eventControllerUpdate(
2951
+ data: EventControllerUpdateData
2952
+ ): CancelablePromise<EventControllerUpdateResponse> {
2857
2953
  return __request(OpenAPI, {
2858
- method: 'POST',
2859
- url: '/api/v1/bean/platforms',
2954
+ method: 'PUT',
2955
+ url: '/api/v1/{region}/bean/events/{id}',
2956
+ path: {
2957
+ id: data.id,
2958
+ region: data.region
2959
+ },
2860
2960
  body: data.requestBody,
2861
2961
  mediaType: 'application/json',
2862
2962
  errors: {
2863
- 409: 'Platform already exists'
2963
+ 400: 'If-Match header is not a valid ISO 8601 date',
2964
+ 404: 'Life event not found',
2965
+ 409: 'Updated event conflicts with an existing (userId, type, date) combination',
2966
+ 412: 'If-Match precondition failed (updatedAt mismatch)'
2864
2967
  }
2865
2968
  });
2866
2969
  }
2867
2970
 
2868
2971
  /**
2869
- * Get platform list for current user
2870
- * @returns unknown List of platforms with user binding status
2972
+ * Delete a life event
2973
+ * Deletes a life event entry (hard delete). Returns 204.
2974
+ * @param data The data for the request.
2975
+ * @param data.id Life event ID
2976
+ * @param data.region Region code for tenant context (decorative for life events)
2977
+ * @returns void Life event deleted successfully
2871
2978
  * @throws ApiError
2872
2979
  */
2873
- public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
2980
+ public static eventControllerDelete(
2981
+ data: EventControllerDeleteData
2982
+ ): CancelablePromise<EventControllerDeleteResponse> {
2874
2983
  return __request(OpenAPI, {
2875
- method: 'GET',
2876
- url: '/api/v1/bean/platforms/list'
2984
+ method: 'DELETE',
2985
+ url: '/api/v1/{region}/bean/events/{id}',
2986
+ path: {
2987
+ id: data.id,
2988
+ region: data.region
2989
+ },
2990
+ errors: {
2991
+ 404: 'Life event not found'
2992
+ }
2877
2993
  });
2878
2994
  }
2879
2995
 
2880
2996
  /**
2881
- * Match platforms by name or alias
2997
+ * Slice time-series by a life event (Phase 79)
2998
+ * Returns aggregated time-series for postings matching accountPattern within the half-open date range of the given life event.
2882
2999
  * @param data The data for the request.
2883
- * @param data.q Search query — Chinese name, English name, or abbreviation
2884
- * @param data.region Region code for category override lookup
2885
- * @returns unknown List of matching platforms with suggested segment names
3000
+ * @param data.id Life event ID
3001
+ * @param data.accountPattern
3002
+ * @param data.granularity
3003
+ * @param data.region Region code for tenant context (decorative for life events)
3004
+ * @returns unknown Time-series sliced by the life event range
2886
3005
  * @throws ApiError
2887
3006
  */
2888
- public static platformControllerMatchPlatforms(
2889
- data: PlatformControllerMatchPlatformsData
2890
- ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3007
+ public static eventControllerGetSlice(
3008
+ data: EventControllerGetSliceData
3009
+ ): CancelablePromise<EventControllerGetSliceResponse> {
2891
3010
  return __request(OpenAPI, {
2892
3011
  method: 'GET',
2893
- url: '/api/v1/bean/platforms/match',
2894
- query: {
2895
- q: data.q,
3012
+ url: '/api/v1/{region}/bean/events/{id}/slice',
3013
+ path: {
3014
+ id: data.id,
2896
3015
  region: data.region
3016
+ },
3017
+ query: {
3018
+ accountPattern: data.accountPattern,
3019
+ granularity: data.granularity
3020
+ },
3021
+ errors: {
3022
+ 400: 'accountPattern query param is empty',
3023
+ 404: 'Life event not found'
2897
3024
  }
2898
3025
  });
2899
3026
  }
3027
+ }
2900
3028
 
3029
+ export class OnboardingService {
2901
3030
  /**
2902
- * Update a platform
3031
+ * Bootstrap core accounts + register asset accounts with opening balances (ADR-0113)
2903
3032
  * @param data The data for the request.
2904
- * @param data.id Platform ID
3033
+ * @param data.region Region code for tenant context
2905
3034
  * @param data.requestBody
2906
- * @returns unknown Platform updated successfully
3035
+ * @returns unknown Onboarding bootstrap result.
2907
3036
  * @throws ApiError
2908
3037
  */
2909
- public static platformControllerUpdate(
2910
- data: PlatformControllerUpdateData
2911
- ): CancelablePromise<PlatformControllerUpdateResponse> {
3038
+ public static onboardingControllerBootstrap(
3039
+ data: OnboardingControllerBootstrapData
3040
+ ): CancelablePromise<OnboardingControllerBootstrapResponse> {
2912
3041
  return __request(OpenAPI, {
2913
- method: 'PUT',
2914
- url: '/api/v1/bean/platforms/{id}',
3042
+ method: 'POST',
3043
+ url: '/api/v1/{region}/bean/onboarding',
2915
3044
  path: {
2916
- id: data.id
3045
+ region: data.region
2917
3046
  },
2918
3047
  body: data.requestBody,
2919
3048
  mediaType: 'application/json',
2920
3049
  errors: {
2921
- 404: 'Platform not found'
3050
+ 422: 'Invalid region/account path/duplicate paths.'
2922
3051
  }
2923
3052
  });
2924
3053
  }
3054
+ }
2925
3055
 
3056
+ export class BalanceReconciliationService {
2926
3057
  /**
2927
- * Delete a platform
3058
+ * Preview reconciliation (book vs actual)
3059
+ * Computes book balance, diff, Beancount-inferred tolerance, and suggested action without persisting.
2928
3060
  * @param data The data for the request.
2929
- * @param data.id Platform ID
2930
- * @returns void Platform deleted successfully
3061
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3062
+ * @param data.requestBody
3063
+ * @returns ReconciliationComputeResultDto Reconciliation preview
2931
3064
  * @throws ApiError
2932
3065
  */
2933
- public static platformControllerDelete(
2934
- data: PlatformControllerDeleteData
2935
- ): CancelablePromise<PlatformControllerDeleteResponse> {
3066
+ public static reconciliationControllerCompute(
3067
+ data: ReconciliationControllerComputeData
3068
+ ): CancelablePromise<ReconciliationControllerComputeResponse> {
2936
3069
  return __request(OpenAPI, {
2937
- method: 'DELETE',
2938
- url: '/api/v1/bean/platforms/{id}',
3070
+ method: 'POST',
3071
+ url: '/api/v1/{region}/bean/reconciliations',
2939
3072
  path: {
2940
- id: data.id
3073
+ region: data.region
2941
3074
  },
3075
+ body: data.requestBody,
3076
+ mediaType: 'application/json',
2942
3077
  errors: {
2943
- 404: 'Platform not found'
3078
+ 404: 'Account not found'
2944
3079
  }
2945
3080
  });
2946
3081
  }
2947
- }
2948
3082
 
2949
- export class ProviderSyncService {
2950
3083
  /**
2951
- * Sync transactions from financial data provider
2952
- *
2953
- * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
2954
- *
2955
- * **Supported Providers:**
2956
- * - **plaid**: Plaid API (US, Canada, Europe)
2957
- * - **teller**: Teller API (US)
2958
- * - **truelayer**: TrueLayer Open Banking (UK, Europe)
2959
- * - **gocardless**: GoCardless Bank Account Data (Europe)
2960
- * - **simplefin**: SimpleFIN (Self-hosted)
2961
- * - **yodlee**: Yodlee (Global)
2962
- * - **beancount-direct**: Beancount format transactions
2963
- * - **parsed-bill**: Client-side parsed bill transactions
2964
- *
2965
- * **Processing Flow:**
2966
- * 1. Transform raw data via provider adapter
2967
- * 2. Validate transaction format
2968
- * 3. Deduplicate using originalId
2969
- * 4. Classify using rule engine
2970
- * 5. Route low-confidence to Review Center
2971
- * 6. Persist validated transactions
2972
- *
3084
+ * Record a balance assertion
3085
+ * Persists the reconciliation as a BeanBalance assertion (amount = actual, diffAmount = book − actual). Re-reconciling the same day/currency upserts.
2973
3086
  * @param data The data for the request.
2974
- * @param data.providerName Provider name
2975
- * @param data.region Region code for tenant context
3087
+ * @param data.region Region code for tenant context (decorative for reconciliation)
2976
3088
  * @param data.requestBody
2977
- * @returns ProviderSyncResponseDto Sync completed successfully
3089
+ * @returns ReconciliationRecordDto Balance assertion recorded
2978
3090
  * @throws ApiError
2979
3091
  */
2980
- public static providerSyncControllerSync(
2981
- data: ProviderSyncControllerSyncData
2982
- ): CancelablePromise<ProviderSyncControllerSyncResponse> {
3092
+ public static reconciliationControllerAssert(
3093
+ data: ReconciliationControllerAssertData
3094
+ ): CancelablePromise<ReconciliationControllerAssertResponse> {
2983
3095
  return __request(OpenAPI, {
2984
3096
  method: 'POST',
2985
- url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3097
+ url: '/api/v1/{region}/bean/reconciliations/assert',
2986
3098
  path: {
2987
- providerName: data.providerName,
2988
3099
  region: data.region
2989
3100
  },
2990
3101
  body: data.requestBody,
2991
3102
  mediaType: 'application/json',
2992
3103
  errors: {
2993
- 400: 'Invalid request data',
2994
- 401: 'Missing or invalid authentication',
2995
- 404: 'Provider not supported'
3104
+ 404: 'Account not found'
2996
3105
  }
2997
3106
  });
2998
3107
  }
2999
3108
 
3000
3109
  /**
3001
- * Get supported providers
3002
- * Returns a list of all providers supported by the sync endpoint.
3110
+ * Generate a pad adjusting entry
3111
+ * When book is outside tolerance, synthesizes a Beancount pad transaction (flag P) booking the diff from source_account and persists it. Source defaults to Equity:Opening-Balances.
3003
3112
  * @param data The data for the request.
3004
- * @param data.region Region code for tenant context
3005
- * @returns SupportedProvidersResponseDto List of supported providers
3113
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3114
+ * @param data.requestBody
3115
+ * @returns PadResultDto Pad adjusting entry generated
3006
3116
  * @throws ApiError
3007
3117
  */
3008
- public static providerSyncControllerGetSupportedProviders(
3009
- data: ProviderSyncControllerGetSupportedProvidersData
3010
- ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
3118
+ public static reconciliationControllerPad(
3119
+ data: ReconciliationControllerPadData
3120
+ ): CancelablePromise<ReconciliationControllerPadResponse> {
3011
3121
  return __request(OpenAPI, {
3012
- method: 'GET',
3013
- url: '/api/v1/{region}/bean/import/provider/supported',
3122
+ method: 'POST',
3123
+ url: '/api/v1/{region}/bean/reconciliations/pad',
3014
3124
  path: {
3015
3125
  region: data.region
3016
3126
  },
3127
+ body: data.requestBody,
3128
+ mediaType: 'application/json',
3017
3129
  errors: {
3018
- 401: 'Missing or invalid authentication'
3130
+ 400: 'Book already within tolerance — no pad needed',
3131
+ 404: 'Account not found'
3019
3132
  }
3020
3133
  });
3021
3134
  }
3022
3135
 
3023
3136
  /**
3024
- * Check if provider is supported
3025
- * Returns whether a specific provider is supported.
3137
+ * List reconciliation history for an account
3138
+ * Returns recorded balance assertions (most recent first). The latest drives the account-detail "Last <date>" badge.
3026
3139
  * @param data The data for the request.
3027
- * @param data.providerName Provider name to check
3028
- * @param data.region Region code for tenant context
3029
- * @returns unknown Provider support status
3140
+ * @param data.accountId BeanAccount id
3141
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3142
+ * @returns ReconciliationRecordDto Reconciliation history
3030
3143
  * @throws ApiError
3031
3144
  */
3032
- public static providerSyncControllerIsProviderSupported(
3033
- data: ProviderSyncControllerIsProviderSupportedData
3034
- ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
3145
+ public static reconciliationControllerHistory(
3146
+ data: ReconciliationControllerHistoryData
3147
+ ): CancelablePromise<ReconciliationControllerHistoryResponse> {
3035
3148
  return __request(OpenAPI, {
3036
3149
  method: 'GET',
3037
- url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
3150
+ url: '/api/v1/{region}/bean/accounts/{accountId}/reconciliations',
3038
3151
  path: {
3039
- providerName: data.providerName,
3152
+ accountId: data.accountId,
3040
3153
  region: data.region
3041
3154
  },
3042
3155
  errors: {
3043
- 401: 'Missing or invalid authentication'
3156
+ 404: 'Account not found'
3044
3157
  }
3045
3158
  });
3046
3159
  }
3047
3160
  }
3048
3161
 
3049
- export class ImportTelemetryService {
3162
+ export class BeanExportService {
3050
3163
  /**
3051
- * Receive anonymous parser failure telemetry
3164
+ * Export Beancount ledger as ZIP
3165
+ * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
3166
+ * @returns unknown
3167
+ * @throws ApiError
3168
+ */
3169
+ public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
3170
+ return __request(OpenAPI, {
3171
+ method: 'GET',
3172
+ url: '/api/v1/{region}/bean/export/beancount'
3173
+ });
3174
+ }
3175
+ }
3176
+
3177
+ export class BeanImportService {
3178
+ /**
3179
+ * Import a bill file
3180
+ * Upload and process a bill file (CSV, PDF, OFX, etc.). The system automatically identifies the file type, extracts transactions, validates them, and stores only validated transactions to the database. Maximum file size: 50MB. Only 1 import per user at a time (concurrent imports rejected with 429).
3052
3181
  * @param data The data for the request.
3053
3182
  * @param data.region Region code for tenant context
3054
- * @param data.requestBody
3055
- * @returns unknown Telemetry report received
3183
+ * @param data.formData Bill file to import
3184
+ * @returns ImportResultDto File imported successfully
3056
3185
  * @throws ApiError
3057
3186
  */
3058
- public static telemetryControllerReportTelemetry(
3059
- data: TelemetryControllerReportTelemetryData
3060
- ): CancelablePromise<TelemetryControllerReportTelemetryResponse> {
3187
+ public static fileImportControllerImportFile(
3188
+ data: FileImportControllerImportFileData
3189
+ ): CancelablePromise<FileImportControllerImportFileResponse> {
3061
3190
  return __request(OpenAPI, {
3062
3191
  method: 'POST',
3063
- url: '/api/v1/{region}/bean/import/parser-telemetry',
3192
+ url: '/api/v1/{region}/bean/import/file',
3064
3193
  path: {
3065
3194
  region: data.region
3066
3195
  },
3067
- body: data.requestBody,
3068
- mediaType: 'application/json',
3196
+ formData: data.formData,
3197
+ mediaType: 'multipart/form-data',
3069
3198
  errors: {
3070
- 401: 'Unauthorized'
3199
+ 400: 'Bad request - file-format-unsupported or file-import-failed',
3200
+ 413: 'Payload too large - file exceeds 50MB limit',
3201
+ 429: 'Too many requests - user already has import in progress',
3202
+ 500: 'Internal server error - DATABASE_ERROR'
3071
3203
  }
3072
3204
  });
3073
3205
  }
3074
3206
 
3075
3207
  /**
3076
- * Receive anonymous zero-hit coverage miss report
3208
+ * Identify file type
3209
+ * Upload a file to check if it can be processed by any registered importer. Does not perform actual import - useful for pre-validation. Uses user-specific importer configuration.
3077
3210
  * @param data The data for the request.
3078
3211
  * @param data.region Region code for tenant context
3079
- * @param data.requestBody
3080
- * @returns unknown Coverage miss report received
3212
+ * @param data.formData File to identify
3213
+ * @returns IdentifyResultDto File identification result
3081
3214
  * @throws ApiError
3082
3215
  */
3083
- public static telemetryControllerReportCoverageMiss(
3084
- data: TelemetryControllerReportCoverageMissData
3085
- ): CancelablePromise<TelemetryControllerReportCoverageMissResponse> {
3216
+ public static fileImportControllerIdentifyFile(
3217
+ data: FileImportControllerIdentifyFileData
3218
+ ): CancelablePromise<FileImportControllerIdentifyFileResponse> {
3086
3219
  return __request(OpenAPI, {
3087
3220
  method: 'POST',
3088
- url: '/api/v1/{region}/bean/import/parser-coverage-miss',
3221
+ url: '/api/v1/{region}/bean/import/identify',
3089
3222
  path: {
3090
3223
  region: data.region
3091
3224
  },
3092
- body: data.requestBody,
3093
- mediaType: 'application/json',
3225
+ formData: data.formData,
3226
+ mediaType: 'multipart/form-data',
3094
3227
  errors: {
3095
- 401: 'Unauthorized'
3228
+ 400: 'Bad request - No file uploaded'
3096
3229
  }
3097
3230
  });
3098
3231
  }
3099
3232
 
3100
3233
  /**
3101
- * Coverage metrics (uncovered format aggregation)
3234
+ * Import a Beancount file in community format
3235
+ * Upload a .beancount file to import. The system parses community-format paths, converts to internal format using category metadata, auto-creates accounts, and imports transactions with deduplication. Maximum file size: 50MB. Only 1 import per user at a time.
3102
3236
  * @param data The data for the request.
3103
3237
  * @param data.region Region code for tenant context
3104
- * @param data.topN Top-N uncovered formats (default 10)
3105
- * @returns unknown Coverage metrics
3238
+ * @param data.formData Beancount file to import
3239
+ * @returns unknown Beancount file imported successfully
3106
3240
  * @throws ApiError
3107
3241
  */
3108
- public static telemetryControllerGetCoverageMetrics(
3109
- data: TelemetryControllerGetCoverageMetricsData
3110
- ): CancelablePromise<TelemetryControllerGetCoverageMetricsResponse> {
3242
+ public static fileImportControllerImportBeancount(
3243
+ data: FileImportControllerImportBeancountData
3244
+ ): CancelablePromise<FileImportControllerImportBeancountResponse> {
3111
3245
  return __request(OpenAPI, {
3112
- method: 'GET',
3113
- url: '/api/v1/{region}/bean/import/parser-coverage-metrics',
3246
+ method: 'POST',
3247
+ url: '/api/v1/{region}/bean/import/beancount',
3114
3248
  path: {
3115
3249
  region: data.region
3116
3250
  },
3117
- query: {
3118
- topN: data.topN
3251
+ formData: data.formData,
3252
+ mediaType: 'multipart/form-data',
3253
+ errors: {
3254
+ 400: 'Bad request - invalid file or no file uploaded'
3119
3255
  }
3120
3256
  });
3121
3257
  }
3122
- }
3123
3258
 
3124
- export class BeanNlpService {
3125
3259
  /**
3126
- * Process natural language input
3127
- * Parse natural language text (Chinese/English) describing a transaction. Supports multi-turn dialogue for collecting missing information. When confidence < 0.75, returns "confirm" action requiring user verification. User can reply with confirmation words (确认/yes/ok) or provide corrections. Examples: "yesterday Starbucks spent 35 yuan", "today lunch 28 yuan", "spent $50 at Walmart"
3260
+ * Get importer configuration
3261
+ * Returns the current configuration for the specified importer. Creates default configuration if none exists.
3128
3262
  * @param data The data for the request.
3263
+ * @param data.importerId Importer identifier. Supported importers: alipay, alipay-web, wechat, boc, boc-credit, ccb, cmb, cmbc, cmbc-credit, icbc, icbc-credit, hsbc-hk-credit, hsbc-hk-debit
3129
3264
  * @param data.region Region code for tenant context
3130
- * @param data.requestBody Natural language transaction input with optional session ID
3131
- * @returns NlpResponseDto NLP processing result - either created transaction or asking for more info
3265
+ * @returns ImporterConfigDto Configuration retrieved successfully
3132
3266
  * @throws ApiError
3133
3267
  */
3134
- public static nlpControllerProcessNaturalLanguage(
3135
- data: NlpControllerProcessNaturalLanguageData
3136
- ): CancelablePromise<NlpControllerProcessNaturalLanguageResponse> {
3268
+ public static importerConfigControllerGetConfig(
3269
+ data: ImporterConfigControllerGetConfigData
3270
+ ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
3137
3271
  return __request(OpenAPI, {
3138
- method: 'POST',
3139
- url: '/api/v1/{region}/bean/nlp/process',
3272
+ method: 'GET',
3273
+ url: '/api/v1/{region}/bean/import/config/{importerId}',
3140
3274
  path: {
3275
+ importerId: data.importerId,
3141
3276
  region: data.region
3142
3277
  },
3143
- body: data.requestBody,
3144
- mediaType: 'application/json',
3145
3278
  errors: {
3146
- 400: 'Invalid input',
3147
- 401: 'Unauthorized'
3279
+ 400: 'Invalid input - Unsupported importer',
3280
+ 401: 'Unauthorized - Authentication required'
3148
3281
  }
3149
3282
  });
3150
3283
  }
3151
3284
 
3152
3285
  /**
3153
- * Clear dialogue session
3154
- * Clear the current NLP dialogue session. Use this to cancel an ongoing multi-turn dialogue.
3286
+ * Update importer configuration
3287
+ * Updates the configuration for the specified importer. Partial updates are supported.
3155
3288
  * @param data The data for the request.
3289
+ * @param data.importerId Importer identifier. Supported importers: alipay, alipay-web, wechat, boc, boc-credit, ccb, cmb, cmbc, cmbc-credit, icbc, icbc-credit, hsbc-hk-credit, hsbc-hk-debit
3156
3290
  * @param data.region Region code for tenant context
3157
- * @param data.sessionId Specific session ID to clear (defaults to user session)
3158
- * @returns void Session cleared successfully
3291
+ * @param data.requestBody Partial configuration update. Only provided fields will be updated.
3292
+ * @returns ImporterConfigDto Configuration updated successfully
3159
3293
  * @throws ApiError
3160
3294
  */
3161
- public static nlpControllerClearSession(
3162
- data: NlpControllerClearSessionData
3163
- ): CancelablePromise<NlpControllerClearSessionResponse> {
3295
+ public static importerConfigControllerUpdateConfig(
3296
+ data: ImporterConfigControllerUpdateConfigData
3297
+ ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
3164
3298
  return __request(OpenAPI, {
3165
- method: 'DELETE',
3166
- url: '/api/v1/{region}/bean/nlp/session',
3299
+ method: 'PUT',
3300
+ url: '/api/v1/{region}/bean/import/config/{importerId}',
3167
3301
  path: {
3302
+ importerId: data.importerId,
3168
3303
  region: data.region
3169
3304
  },
3170
- query: {
3171
- sessionId: data.sessionId
3172
- },
3305
+ body: data.requestBody,
3306
+ mediaType: 'application/json',
3173
3307
  errors: {
3174
- 401: 'Unauthorized'
3308
+ 400: 'Invalid input - Validation failed',
3309
+ 404: 'Configuration not found'
3175
3310
  }
3176
3311
  });
3177
3312
  }
3178
3313
 
3179
3314
  /**
3180
- * Get current session state
3181
- * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
3315
+ * Reset configuration to default
3316
+ * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
3182
3317
  * @param data The data for the request.
3318
+ * @param data.importerId Importer identifier. Supported importers: alipay, alipay-web, wechat, boc, boc-credit, ccb, cmb, cmbc, cmbc-credit, icbc, icbc-credit, hsbc-hk-credit, hsbc-hk-debit
3183
3319
  * @param data.region Region code for tenant context
3184
- * @param data.sessionId Specific session ID to get (defaults to user session)
3185
- * @returns unknown Current session state (or null if no active session)
3320
+ * @returns ImporterConfigDto Configuration reset successfully
3186
3321
  * @throws ApiError
3187
3322
  */
3188
- public static nlpControllerGetSession(
3189
- data: NlpControllerGetSessionData
3190
- ): CancelablePromise<NlpControllerGetSessionResponse> {
3323
+ public static importerConfigControllerResetConfig(
3324
+ data: ImporterConfigControllerResetConfigData
3325
+ ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
3191
3326
  return __request(OpenAPI, {
3192
- method: 'GET',
3193
- url: '/api/v1/{region}/bean/nlp/session',
3327
+ method: 'POST',
3328
+ url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
3194
3329
  path: {
3330
+ importerId: data.importerId,
3195
3331
  region: data.region
3196
3332
  },
3197
- query: {
3198
- sessionId: data.sessionId
3199
- },
3200
3333
  errors: {
3201
- 401: 'Unauthorized'
3334
+ 400: 'Invalid input - Unsupported importer'
3202
3335
  }
3203
3336
  });
3204
3337
  }
3205
3338
  }
3206
3339
 
3207
- export class DashboardService {
3340
+ export class ProviderSyncService {
3208
3341
  /**
3209
- * Get net worth overview
3210
- * Returns total net worth with breakdown of assets and liabilities
3342
+ * Sync transactions from financial data provider
3343
+ *
3344
+ * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
3345
+ *
3346
+ * **Supported Providers:**
3347
+ * - **plaid**: Plaid API (US, Canada, Europe)
3348
+ * - **teller**: Teller API (US)
3349
+ * - **truelayer**: TrueLayer Open Banking (UK, Europe)
3350
+ * - **gocardless**: GoCardless Bank Account Data (Europe)
3351
+ * - **simplefin**: SimpleFIN (Self-hosted)
3352
+ * - **yodlee**: Yodlee (Global)
3353
+ * - **beancount-direct**: Beancount format transactions
3354
+ * - **parsed-bill**: Client-side parsed bill transactions
3355
+ *
3356
+ * **Processing Flow:**
3357
+ * 1. Transform raw data via provider adapter
3358
+ * 2. Validate transaction format
3359
+ * 3. Deduplicate using originalId
3360
+ * 4. Classify using rule engine
3361
+ * 5. Route low-confidence to Review Center
3362
+ * 6. Persist validated transactions
3363
+ *
3211
3364
  * @param data The data for the request.
3365
+ * @param data.providerName Provider name
3212
3366
  * @param data.region Region code for tenant context
3213
- * @param data.date Date for balance calculation (ISO 8601 format)
3214
- * @returns NetWorthResponseDto Net worth retrieved successfully
3367
+ * @param data.requestBody
3368
+ * @returns ProviderSyncResponseDto Sync completed successfully
3215
3369
  * @throws ApiError
3216
3370
  */
3217
- public static dashboardControllerGetNetWorth(
3218
- data: DashboardControllerGetNetWorthData
3219
- ): CancelablePromise<DashboardControllerGetNetWorthResponse> {
3371
+ public static providerSyncControllerSync(
3372
+ data: ProviderSyncControllerSyncData
3373
+ ): CancelablePromise<ProviderSyncControllerSyncResponse> {
3220
3374
  return __request(OpenAPI, {
3221
- method: 'GET',
3222
- url: '/api/v1/{region}/dashboard/net-worth',
3375
+ method: 'POST',
3376
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3223
3377
  path: {
3378
+ providerName: data.providerName,
3224
3379
  region: data.region
3225
3380
  },
3226
- query: {
3227
- date: data.date
3228
- },
3381
+ body: data.requestBody,
3382
+ mediaType: 'application/json',
3229
3383
  errors: {
3230
- 401: 'User not authenticated'
3384
+ 400: 'Invalid request data',
3385
+ 401: 'Missing or invalid authentication',
3386
+ 404: 'Provider not supported'
3231
3387
  }
3232
3388
  });
3233
3389
  }
3234
3390
 
3235
3391
  /**
3236
- * Get accounts grouped by platform
3237
- * Returns accounts with balances grouped by financial platform
3392
+ * Get supported providers
3393
+ * Returns a list of all providers supported by the sync endpoint.
3238
3394
  * @param data The data for the request.
3239
3395
  * @param data.region Region code for tenant context
3240
- * @param data.groupBy Grouping strategy
3241
- * @param data.date Date for balance calculation (ISO 8601 format)
3242
- * @param data.accountId Scope to a single account (only valid with groupBy=holdingAssetClass, ADR-0105 §6)
3243
- * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
3396
+ * @returns SupportedProvidersResponseDto List of supported providers
3244
3397
  * @throws ApiError
3245
3398
  */
3246
- public static dashboardControllerGetAccounts(
3247
- data: DashboardControllerGetAccountsData
3248
- ): CancelablePromise<DashboardControllerGetAccountsResponse> {
3399
+ public static providerSyncControllerGetSupportedProviders(
3400
+ data: ProviderSyncControllerGetSupportedProvidersData
3401
+ ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
3249
3402
  return __request(OpenAPI, {
3250
3403
  method: 'GET',
3251
- url: '/api/v1/{region}/dashboard/accounts',
3404
+ url: '/api/v1/{region}/bean/import/provider/supported',
3252
3405
  path: {
3253
3406
  region: data.region
3254
3407
  },
3255
- query: {
3256
- groupBy: data.groupBy,
3257
- date: data.date,
3258
- accountId: data.accountId
3259
- },
3260
3408
  errors: {
3261
- 401: 'User not authenticated'
3409
+ 401: 'Missing or invalid authentication'
3262
3410
  }
3263
3411
  });
3264
3412
  }
3265
3413
 
3266
3414
  /**
3267
- * Get cash flow summary
3268
- * Returns income, expenses, and savings for a monthly period
3415
+ * Check if provider is supported
3416
+ * Returns whether a specific provider is supported.
3269
3417
  * @param data The data for the request.
3270
- * @param data.period Period in YYYY-MM format
3418
+ * @param data.providerName Provider name to check
3271
3419
  * @param data.region Region code for tenant context
3272
- * @returns CashFlowResponseDto Cash flow retrieved successfully
3420
+ * @returns unknown Provider support status
3273
3421
  * @throws ApiError
3274
3422
  */
3275
- public static dashboardControllerGetCashFlow(
3276
- data: DashboardControllerGetCashFlowData
3277
- ): CancelablePromise<DashboardControllerGetCashFlowResponse> {
3423
+ public static providerSyncControllerIsProviderSupported(
3424
+ data: ProviderSyncControllerIsProviderSupportedData
3425
+ ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
3278
3426
  return __request(OpenAPI, {
3279
3427
  method: 'GET',
3280
- url: '/api/v1/{region}/dashboard/cash-flow',
3428
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
3281
3429
  path: {
3430
+ providerName: data.providerName,
3282
3431
  region: data.region
3283
3432
  },
3284
- query: {
3285
- period: data.period
3286
- },
3287
3433
  errors: {
3288
- 400: 'Invalid period format',
3289
- 401: 'User not authenticated'
3434
+ 401: 'Missing or invalid authentication'
3290
3435
  }
3291
3436
  });
3292
3437
  }
3438
+ }
3293
3439
 
3440
+ export class ExternalAccountLinksService {
3294
3441
  /**
3295
- * Get expenses grouped by functional category
3296
- * Returns expenses pre-aggregated by functional category (account-path Group segment) with server-side multi-currency conversion
3442
+ * Create an external account → BeanAccount mapping (ADR-0113)
3297
3443
  * @param data The data for the request.
3298
3444
  * @param data.region Region code for tenant context
3299
- * @param data.groupBy Grouping strategy
3300
- * @param data.period Time window (1m = current calendar month)
3301
- * @returns ExpensesByCategoryResponseDto Expenses retrieved successfully
3445
+ * @param data.requestBody
3446
+ * @returns ExternalAccountLinkResponseDto Link created.
3302
3447
  * @throws ApiError
3303
3448
  */
3304
- public static dashboardControllerGetExpenses(
3305
- data: DashboardControllerGetExpensesData
3306
- ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3449
+ public static externalAccountLinkControllerCreate(
3450
+ data: ExternalAccountLinkControllerCreateData
3451
+ ): CancelablePromise<ExternalAccountLinkControllerCreateResponse> {
3307
3452
  return __request(OpenAPI, {
3308
- method: 'GET',
3309
- url: '/api/v1/{region}/dashboard/expenses',
3453
+ method: 'POST',
3454
+ url: '/api/v1/{region}/bean/external-account-links',
3310
3455
  path: {
3311
3456
  region: data.region
3312
3457
  },
3313
- query: {
3314
- groupBy: data.groupBy,
3315
- period: data.period
3316
- },
3458
+ body: data.requestBody,
3459
+ mediaType: 'application/json',
3317
3460
  errors: {
3318
- 400: 'Invalid groupBy or period',
3319
- 401: 'User not authenticated'
3461
+ 422: 'beanAccountId not owned, or an active link already exists.'
3320
3462
  }
3321
3463
  });
3322
3464
  }
3323
- }
3324
3465
 
3325
- export class InvestmentService {
3326
3466
  /**
3327
- * Get per-holding unrealized + realized P&L
3328
- * Average-cost unrealized P&L per account × commodity, plus cumulative realized P&L on sold lots (method = FIFO | average, default average).
3467
+ * List the user's active external account links
3329
3468
  * @param data The data for the request.
3469
+ * @param data.provider
3330
3470
  * @param data.region Region code for tenant context
3331
- * @param data.asOf As-of date (ISO 8601), defaults to today
3332
- * @param data.accountId Scope to a single account
3333
- * @param data.method Realized-P&L lot-matching method (default average). Does not affect the average-cost unrealized basis.
3334
- * @returns HoldingPnlResponseDto Holding P&L retrieved successfully
3471
+ * @returns ExternalAccountLinkListResponseDto Links retrieved.
3335
3472
  * @throws ApiError
3336
3473
  */
3337
- public static holdingPnlControllerGetHoldingPnl(
3338
- data: HoldingPnlControllerGetHoldingPnlData
3339
- ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3474
+ public static externalAccountLinkControllerFindAll(
3475
+ data: ExternalAccountLinkControllerFindAllData
3476
+ ): CancelablePromise<ExternalAccountLinkControllerFindAllResponse> {
3340
3477
  return __request(OpenAPI, {
3341
3478
  method: 'GET',
3342
- url: '/api/v1/{region}/investment/holdings/pnl',
3479
+ url: '/api/v1/{region}/bean/external-account-links',
3343
3480
  path: {
3344
3481
  region: data.region
3345
3482
  },
3346
3483
  query: {
3347
- asOf: data.asOf,
3348
- accountId: data.accountId,
3349
- method: data.method
3484
+ provider: data.provider
3485
+ }
3486
+ });
3487
+ }
3488
+
3489
+ /**
3490
+ * Get a single external account link
3491
+ * @param data The data for the request.
3492
+ * @param data.id
3493
+ * @param data.region Region code for tenant context
3494
+ * @returns ExternalAccountLinkResponseDto Link retrieved.
3495
+ * @throws ApiError
3496
+ */
3497
+ public static externalAccountLinkControllerFindOne(
3498
+ data: ExternalAccountLinkControllerFindOneData
3499
+ ): CancelablePromise<ExternalAccountLinkControllerFindOneResponse> {
3500
+ return __request(OpenAPI, {
3501
+ method: 'GET',
3502
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3503
+ path: {
3504
+ id: data.id,
3505
+ region: data.region
3350
3506
  },
3351
3507
  errors: {
3352
- 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3353
- 401: 'User not authenticated'
3508
+ 422: 'Link not found or not owned by the user.'
3509
+ }
3510
+ });
3511
+ }
3512
+
3513
+ /**
3514
+ * Soft-delete (disconnect) an external account link
3515
+ * @param data The data for the request.
3516
+ * @param data.id
3517
+ * @param data.region Region code for tenant context
3518
+ * @returns void Link soft-deleted; historical transactions are unaffected.
3519
+ * @throws ApiError
3520
+ */
3521
+ public static externalAccountLinkControllerRemove(
3522
+ data: ExternalAccountLinkControllerRemoveData
3523
+ ): CancelablePromise<ExternalAccountLinkControllerRemoveResponse> {
3524
+ return __request(OpenAPI, {
3525
+ method: 'DELETE',
3526
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3527
+ path: {
3528
+ id: data.id,
3529
+ region: data.region
3354
3530
  }
3355
3531
  });
3356
3532
  }
3357
3533
  }
3358
3534
 
3359
- export class BeanPricesService {
3535
+ export class ImportTelemetryService {
3360
3536
  /**
3361
- * Create a new price
3362
- * Creates a new price entry for the authenticated user
3537
+ * Receive anonymous parser failure telemetry
3363
3538
  * @param data The data for the request.
3364
3539
  * @param data.region Region code for tenant context
3365
3540
  * @param data.requestBody
3366
- * @returns PriceResponseDto Price created successfully
3541
+ * @returns unknown Telemetry report received
3367
3542
  * @throws ApiError
3368
3543
  */
3369
- public static priceControllerCreate(
3370
- data: PriceControllerCreateData
3371
- ): CancelablePromise<PriceControllerCreateResponse> {
3544
+ public static telemetryControllerReportTelemetry(
3545
+ data: TelemetryControllerReportTelemetryData
3546
+ ): CancelablePromise<TelemetryControllerReportTelemetryResponse> {
3372
3547
  return __request(OpenAPI, {
3373
3548
  method: 'POST',
3374
- url: '/api/v1/{region}/bean/prices',
3549
+ url: '/api/v1/{region}/bean/import/parser-telemetry',
3375
3550
  path: {
3376
3551
  region: data.region
3377
3552
  },
3378
3553
  body: data.requestBody,
3379
3554
  mediaType: 'application/json',
3380
3555
  errors: {
3381
- 404: 'Currency or quoteCurrency commodity not found',
3382
- 409: 'Price already exists for this currency pair and date'
3556
+ 401: 'Unauthorized'
3383
3557
  }
3384
3558
  });
3385
3559
  }
3386
3560
 
3387
3561
  /**
3388
- * List user prices
3389
- * Returns all price entries for the authenticated user with optional filtering
3562
+ * Receive anonymous zero-hit coverage miss report
3390
3563
  * @param data The data for the request.
3391
3564
  * @param data.region Region code for tenant context
3392
- * @param data.currency Filter by currency (e.g., BTC, AAPL, USD)
3393
- * @param data.quoteCurrency Filter by quote currency (pricing currency, e.g., USD, CNY)
3394
- * @param data.dateFrom Filter prices from this date (ISO 8601 format)
3395
- * @param data.dateTo Filter prices to this date (ISO 8601 format)
3396
- * @param data.search Search term for currency or quoteCurrency (case-insensitive partial match)
3397
- * @param data.page Page number for pagination (default: 1)
3398
- * @param data.limit Number of items per page (default: 20, max: 100)
3399
- * @returns PriceListResponseDto Prices retrieved successfully
3565
+ * @param data.requestBody
3566
+ * @returns unknown Coverage miss report received
3400
3567
  * @throws ApiError
3401
3568
  */
3402
- public static priceControllerFindAll(
3403
- data: PriceControllerFindAllData
3404
- ): CancelablePromise<PriceControllerFindAllResponse> {
3569
+ public static telemetryControllerReportCoverageMiss(
3570
+ data: TelemetryControllerReportCoverageMissData
3571
+ ): CancelablePromise<TelemetryControllerReportCoverageMissResponse> {
3405
3572
  return __request(OpenAPI, {
3406
- method: 'GET',
3407
- url: '/api/v1/{region}/bean/prices',
3573
+ method: 'POST',
3574
+ url: '/api/v1/{region}/bean/import/parser-coverage-miss',
3408
3575
  path: {
3409
3576
  region: data.region
3410
3577
  },
3411
- query: {
3412
- currency: data.currency,
3413
- quoteCurrency: data.quoteCurrency,
3414
- dateFrom: data.dateFrom,
3415
- dateTo: data.dateTo,
3416
- search: data.search,
3417
- page: data.page,
3418
- limit: data.limit
3578
+ body: data.requestBody,
3579
+ mediaType: 'application/json',
3580
+ errors: {
3581
+ 401: 'Unauthorized'
3419
3582
  }
3420
3583
  });
3421
3584
  }
3422
3585
 
3423
3586
  /**
3424
- * Get price by ID
3425
- * Returns a single price entry by its ID
3587
+ * Coverage metrics (uncovered format aggregation)
3426
3588
  * @param data The data for the request.
3427
- * @param data.id Price ID
3428
3589
  * @param data.region Region code for tenant context
3429
- * @returns PriceResponseDto Price retrieved successfully
3590
+ * @param data.topN Top-N uncovered formats (default 10)
3591
+ * @returns unknown Coverage metrics
3430
3592
  * @throws ApiError
3431
3593
  */
3432
- public static priceControllerFindOne(
3433
- data: PriceControllerFindOneData
3434
- ): CancelablePromise<PriceControllerFindOneResponse> {
3594
+ public static telemetryControllerGetCoverageMetrics(
3595
+ data: TelemetryControllerGetCoverageMetricsData
3596
+ ): CancelablePromise<TelemetryControllerGetCoverageMetricsResponse> {
3435
3597
  return __request(OpenAPI, {
3436
3598
  method: 'GET',
3437
- url: '/api/v1/{region}/bean/prices/{id}',
3599
+ url: '/api/v1/{region}/bean/import/parser-coverage-metrics',
3438
3600
  path: {
3439
- id: data.id,
3440
3601
  region: data.region
3441
3602
  },
3442
- errors: {
3443
- 404: 'Price not found'
3603
+ query: {
3604
+ topN: data.topN
3444
3605
  }
3445
3606
  });
3446
3607
  }
3608
+ }
3447
3609
 
3610
+ export class BeanNlpService {
3448
3611
  /**
3449
- * Update a price
3450
- * Updates an existing price entry
3612
+ * Process natural language input
3613
+ * Parse natural language text (Chinese/English) describing a transaction. Supports multi-turn dialogue for collecting missing information. When confidence < 0.75, returns "confirm" action requiring user verification. User can reply with confirmation words (确认/yes/ok) or provide corrections. Examples: "yesterday Starbucks spent 35 yuan", "today lunch 28 yuan", "spent $50 at Walmart"
3451
3614
  * @param data The data for the request.
3452
- * @param data.id Price ID
3453
3615
  * @param data.region Region code for tenant context
3454
- * @param data.requestBody
3455
- * @returns PriceResponseDto Price updated successfully
3616
+ * @param data.requestBody Natural language transaction input with optional session ID
3617
+ * @returns NlpResponseDto NLP processing result - either created transaction or asking for more info
3456
3618
  * @throws ApiError
3457
3619
  */
3458
- public static priceControllerUpdate(
3459
- data: PriceControllerUpdateData
3460
- ): CancelablePromise<PriceControllerUpdateResponse> {
3620
+ public static nlpControllerProcessNaturalLanguage(
3621
+ data: NlpControllerProcessNaturalLanguageData
3622
+ ): CancelablePromise<NlpControllerProcessNaturalLanguageResponse> {
3461
3623
  return __request(OpenAPI, {
3462
- method: 'PUT',
3463
- url: '/api/v1/{region}/bean/prices/{id}',
3624
+ method: 'POST',
3625
+ url: '/api/v1/{region}/bean/nlp/process',
3464
3626
  path: {
3465
- id: data.id,
3466
3627
  region: data.region
3467
3628
  },
3468
3629
  body: data.requestBody,
3469
3630
  mediaType: 'application/json',
3470
3631
  errors: {
3471
- 404: 'Price not found',
3472
- 409: 'Updated price conflicts with existing price'
3632
+ 400: 'Invalid input',
3633
+ 401: 'Unauthorized'
3473
3634
  }
3474
3635
  });
3475
3636
  }
3476
3637
 
3477
3638
  /**
3478
- * Delete a price
3479
- * Deletes a price entry (hard delete)
3639
+ * Clear dialogue session
3640
+ * Clear the current NLP dialogue session. Use this to cancel an ongoing multi-turn dialogue.
3480
3641
  * @param data The data for the request.
3481
- * @param data.id Price ID
3482
3642
  * @param data.region Region code for tenant context
3483
- * @returns void Price deleted successfully
3643
+ * @param data.sessionId Specific session ID to clear (defaults to user session)
3644
+ * @returns void Session cleared successfully
3484
3645
  * @throws ApiError
3485
3646
  */
3486
- public static priceControllerDelete(
3487
- data: PriceControllerDeleteData
3488
- ): CancelablePromise<PriceControllerDeleteResponse> {
3647
+ public static nlpControllerClearSession(
3648
+ data: NlpControllerClearSessionData
3649
+ ): CancelablePromise<NlpControllerClearSessionResponse> {
3489
3650
  return __request(OpenAPI, {
3490
3651
  method: 'DELETE',
3491
- url: '/api/v1/{region}/bean/prices/{id}',
3652
+ url: '/api/v1/{region}/bean/nlp/session',
3492
3653
  path: {
3493
- id: data.id,
3494
3654
  region: data.region
3495
3655
  },
3656
+ query: {
3657
+ sessionId: data.sessionId
3658
+ },
3496
3659
  errors: {
3497
- 404: 'Price not found'
3660
+ 401: 'Unauthorized'
3498
3661
  }
3499
3662
  });
3500
3663
  }
3501
3664
 
3502
3665
  /**
3503
- * Bulk create prices
3504
- * Creates multiple price entries at once (skips duplicates)
3666
+ * Get current session state
3667
+ * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
3505
3668
  * @param data The data for the request.
3506
3669
  * @param data.region Region code for tenant context
3670
+ * @param data.sessionId Specific session ID to get (defaults to user session)
3671
+ * @returns unknown Current session state (or null if no active session)
3672
+ * @throws ApiError
3673
+ */
3674
+ public static nlpControllerGetSession(
3675
+ data: NlpControllerGetSessionData
3676
+ ): CancelablePromise<NlpControllerGetSessionResponse> {
3677
+ return __request(OpenAPI, {
3678
+ method: 'GET',
3679
+ url: '/api/v1/{region}/bean/nlp/session',
3680
+ path: {
3681
+ region: data.region
3682
+ },
3683
+ query: {
3684
+ sessionId: data.sessionId
3685
+ },
3686
+ errors: {
3687
+ 401: 'Unauthorized'
3688
+ }
3689
+ });
3690
+ }
3691
+ }
3692
+
3693
+ export class BeanPlatformsService {
3694
+ /**
3695
+ * Get all platforms with statistics
3696
+ * @returns unknown List of platforms with binding and account counts
3697
+ * @throws ApiError
3698
+ */
3699
+ public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
3700
+ return __request(OpenAPI, {
3701
+ method: 'GET',
3702
+ url: '/api/v1/bean/platforms'
3703
+ });
3704
+ }
3705
+
3706
+ /**
3707
+ * Create a new platform
3708
+ * @param data The data for the request.
3507
3709
  * @param data.requestBody
3508
- * @returns PriceResponseDto Prices created successfully
3710
+ * @returns unknown Platform created successfully
3509
3711
  * @throws ApiError
3510
3712
  */
3511
- public static priceControllerBulkCreate(
3512
- data: PriceControllerBulkCreateData
3513
- ): CancelablePromise<PriceControllerBulkCreateResponse> {
3713
+ public static platformControllerCreate(
3714
+ data: PlatformControllerCreateData
3715
+ ): CancelablePromise<PlatformControllerCreateResponse> {
3514
3716
  return __request(OpenAPI, {
3515
3717
  method: 'POST',
3516
- url: '/api/v1/{region}/bean/prices/bulk',
3517
- path: {
3718
+ url: '/api/v1/bean/platforms',
3719
+ body: data.requestBody,
3720
+ mediaType: 'application/json',
3721
+ errors: {
3722
+ 409: 'Platform already exists'
3723
+ }
3724
+ });
3725
+ }
3726
+
3727
+ /**
3728
+ * Get platform list for current user
3729
+ * @returns PlatformListItemDto List of platforms with user binding status
3730
+ * @throws ApiError
3731
+ */
3732
+ public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
3733
+ return __request(OpenAPI, {
3734
+ method: 'GET',
3735
+ url: '/api/v1/bean/platforms/list'
3736
+ });
3737
+ }
3738
+
3739
+ /**
3740
+ * Match platforms by name or alias
3741
+ * @param data The data for the request.
3742
+ * @param data.q Search query — Chinese name, English name, or abbreviation
3743
+ * @param data.region Region code for category override lookup
3744
+ * @returns PlatformMatchResponseDto Matching platforms with overall match type and truncation flag
3745
+ * @throws ApiError
3746
+ */
3747
+ public static platformControllerMatchPlatforms(
3748
+ data: PlatformControllerMatchPlatformsData
3749
+ ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3750
+ return __request(OpenAPI, {
3751
+ method: 'GET',
3752
+ url: '/api/v1/bean/platforms/match',
3753
+ query: {
3754
+ q: data.q,
3518
3755
  region: data.region
3756
+ }
3757
+ });
3758
+ }
3759
+
3760
+ /**
3761
+ * Update a platform
3762
+ * @param data The data for the request.
3763
+ * @param data.id Platform ID
3764
+ * @param data.requestBody
3765
+ * @returns unknown Platform updated successfully
3766
+ * @throws ApiError
3767
+ */
3768
+ public static platformControllerUpdate(
3769
+ data: PlatformControllerUpdateData
3770
+ ): CancelablePromise<PlatformControllerUpdateResponse> {
3771
+ return __request(OpenAPI, {
3772
+ method: 'PUT',
3773
+ url: '/api/v1/bean/platforms/{id}',
3774
+ path: {
3775
+ id: data.id
3519
3776
  },
3520
3777
  body: data.requestBody,
3521
- mediaType: 'application/json'
3778
+ mediaType: 'application/json',
3779
+ errors: {
3780
+ 404: 'Platform not found'
3781
+ }
3782
+ });
3783
+ }
3784
+
3785
+ /**
3786
+ * Delete a platform
3787
+ * @param data The data for the request.
3788
+ * @param data.id Platform ID
3789
+ * @returns void Platform deleted successfully
3790
+ * @throws ApiError
3791
+ */
3792
+ public static platformControllerDelete(
3793
+ data: PlatformControllerDeleteData
3794
+ ): CancelablePromise<PlatformControllerDeleteResponse> {
3795
+ return __request(OpenAPI, {
3796
+ method: 'DELETE',
3797
+ url: '/api/v1/bean/platforms/{id}',
3798
+ path: {
3799
+ id: data.id
3800
+ },
3801
+ errors: {
3802
+ 404: 'Platform not found'
3803
+ }
3522
3804
  });
3523
3805
  }
3524
3806
  }
3525
3807
 
3526
- export class ReportingService {
3808
+ export class DashboardService {
3527
3809
  /**
3528
- * Get portfolio value trends
3529
- *
3530
- * Returns time series data of portfolio net worth.
3531
- *
3532
- * **Multi-currency Support:**
3533
- * - `series[].byCurrency` - Currency breakdown for each data point
3534
- * - `byCurrency` - Separate time series grouped by currency
3535
- * - `warnings` - Exchange rate warnings if conversion failed
3536
- *
3537
- * **Parameters:**
3538
- * - `period`: Time period (1m, 3m, 6m, 1y)
3539
- * - `granularity`: Data granularity (day, week, month)
3540
- *
3810
+ * Get net worth overview
3811
+ * Returns total net worth with breakdown of assets and liabilities
3541
3812
  * @param data The data for the request.
3542
3813
  * @param data.region Region code for tenant context
3543
- * @param data.period Time period
3544
- * @param data.granularity Data granularity
3545
- * @returns PortfolioTrendsResponseDto Trends retrieved successfully
3814
+ * @param data.date Date for balance calculation (ISO 8601 format)
3815
+ * @returns NetWorthResponseDto Net worth retrieved successfully
3546
3816
  * @throws ApiError
3547
3817
  */
3548
- public static reportingControllerGetPortfolioTrends(
3549
- data: ReportingControllerGetPortfolioTrendsData
3550
- ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
3818
+ public static dashboardControllerGetNetWorth(
3819
+ data: DashboardControllerGetNetWorthData
3820
+ ): CancelablePromise<DashboardControllerGetNetWorthResponse> {
3551
3821
  return __request(OpenAPI, {
3552
3822
  method: 'GET',
3553
- url: '/api/v1/{region}/reporting/portfolio/trends',
3823
+ url: '/api/v1/{region}/dashboard/net-worth',
3554
3824
  path: {
3555
3825
  region: data.region
3556
3826
  },
3557
3827
  query: {
3558
- period: data.period,
3559
- granularity: data.granularity
3828
+ date: data.date
3560
3829
  },
3561
3830
  errors: {
3562
3831
  401: 'User not authenticated'
@@ -3565,34 +3834,29 @@ export class ReportingService {
3565
3834
  }
3566
3835
 
3567
3836
  /**
3568
- * Get cash-flow trends
3569
- *
3570
- * Monthly income / expense / netSavings over a fixed N-month window
3571
- * (current month + N−1 prior). Missing months are zero-filled (flow metric).
3572
- *
3573
- * **Parameters:**
3574
- * - `period`: 1m | 3m | 6m | 1y (default 6m)
3575
- * - `granularity`: accepted for API symmetry; v1 returns month buckets
3576
- *
3837
+ * Get accounts grouped by platform
3838
+ * Returns accounts with balances grouped by financial platform
3577
3839
  * @param data The data for the request.
3578
3840
  * @param data.region Region code for tenant context
3579
- * @param data.period Time period
3580
- * @param data.granularity Data granularity (accepted for API symmetry; v1 returns month buckets)
3581
- * @returns CashFlowTrendsResponseDto Cash-flow trends retrieved successfully
3841
+ * @param data.groupBy Grouping strategy
3842
+ * @param data.date Date for balance calculation (ISO 8601 format)
3843
+ * @param data.accountId Scope to a single account (only valid with groupBy=holdingAssetClass, ADR-0105 §6)
3844
+ * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
3582
3845
  * @throws ApiError
3583
3846
  */
3584
- public static reportingControllerGetCashFlowTrends(
3585
- data: ReportingControllerGetCashFlowTrendsData
3586
- ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
3847
+ public static dashboardControllerGetAccounts(
3848
+ data: DashboardControllerGetAccountsData
3849
+ ): CancelablePromise<DashboardControllerGetAccountsResponse> {
3587
3850
  return __request(OpenAPI, {
3588
3851
  method: 'GET',
3589
- url: '/api/v1/{region}/reporting/cash-flow/trends',
3852
+ url: '/api/v1/{region}/dashboard/accounts',
3590
3853
  path: {
3591
3854
  region: data.region
3592
3855
  },
3593
3856
  query: {
3594
- period: data.period,
3595
- granularity: data.granularity
3857
+ groupBy: data.groupBy,
3858
+ date: data.date,
3859
+ accountId: data.accountId
3596
3860
  },
3597
3861
  errors: {
3598
3862
  401: 'User not authenticated'
@@ -3601,80 +3865,95 @@ export class ReportingService {
3601
3865
  }
3602
3866
 
3603
3867
  /**
3604
- * Generate portfolio snapshot
3605
- *
3606
- * Manually generate a portfolio snapshot for a specific date.
3607
- *
3608
- * **Multi-currency Support:**
3609
- * - Fetches balances grouped by currency
3610
- * - Uses user's baseCurrency setting for conversion
3611
- * - Stores exchange rates and warnings
3612
- *
3613
- * **Use Cases:**
3614
- * - Testing snapshot generation
3615
- * - Force regeneration after data correction
3616
- * - Initial setup for new users
3617
- *
3868
+ * Get cash flow summary
3869
+ * Returns income, expenses, and savings for a monthly period
3618
3870
  * @param data The data for the request.
3871
+ * @param data.period Period in YYYY-MM format
3619
3872
  * @param data.region Region code for tenant context
3620
- * @param data.requestBody Optional date (defaults to today)
3621
- * @returns GenerateSnapshotResponse Snapshot generated successfully
3873
+ * @returns CashFlowResponseDto Cash flow retrieved successfully
3622
3874
  * @throws ApiError
3623
3875
  */
3624
- public static reportingControllerGenerateSnapshot(
3625
- data: ReportingControllerGenerateSnapshotData
3626
- ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
3876
+ public static dashboardControllerGetCashFlow(
3877
+ data: DashboardControllerGetCashFlowData
3878
+ ): CancelablePromise<DashboardControllerGetCashFlowResponse> {
3627
3879
  return __request(OpenAPI, {
3628
- method: 'POST',
3629
- url: '/api/v1/{region}/reporting/snapshots/generate',
3880
+ method: 'GET',
3881
+ url: '/api/v1/{region}/dashboard/cash-flow',
3630
3882
  path: {
3631
3883
  region: data.region
3632
3884
  },
3633
- body: data.requestBody,
3634
- mediaType: 'application/json',
3885
+ query: {
3886
+ period: data.period
3887
+ },
3635
3888
  errors: {
3636
- 400: 'Invalid date format',
3889
+ 400: 'Invalid period format',
3637
3890
  401: 'User not authenticated'
3638
3891
  }
3639
3892
  });
3640
3893
  }
3641
3894
 
3642
3895
  /**
3643
- * Backfill portfolio snapshots
3644
- *
3645
- * Generate snapshots for a date range (historical data backfill).
3646
- *
3647
- * **Multi-currency Support:**
3648
- * - Each snapshot includes multi-currency data
3649
- * - Uses exchange rates available at generation time
3650
- * - Warnings stored for missing exchange rates
3651
- *
3652
- * **Best Practices:**
3653
- * - Use for initial setup after account configuration
3654
- * - Run during low-traffic periods for large date ranges
3655
- * - Existing snapshots are skipped (not regenerated)
3656
- *
3896
+ * Get expenses/income grouped by functional category
3897
+ * Returns amounts pre-aggregated by functional category (account-path Group segment) with server-side multi-currency conversion. flow=expense (default) aggregates ^Expenses: accounts; flow=income aggregates ^Income: accounts (issue #518)
3657
3898
  * @param data The data for the request.
3658
3899
  * @param data.region Region code for tenant context
3659
- * @param data.requestBody
3660
- * @returns BackfillSnapshotsResponse Backfill completed successfully
3900
+ * @param data.groupBy Grouping strategy
3901
+ * @param data.period Time window (1m = current calendar month)
3902
+ * @param data.flow Account root to aggregate (expense → ^Expenses:, income → ^Income:)
3903
+ * @returns ExpensesByCategoryResponseDto Expenses retrieved successfully
3661
3904
  * @throws ApiError
3662
3905
  */
3663
- public static reportingControllerBackfillSnapshots(
3664
- data: ReportingControllerBackfillSnapshotsData
3665
- ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
3906
+ public static dashboardControllerGetExpenses(
3907
+ data: DashboardControllerGetExpensesData
3908
+ ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3666
3909
  return __request(OpenAPI, {
3667
- method: 'POST',
3668
- url: '/api/v1/{region}/reporting/snapshots/backfill',
3910
+ method: 'GET',
3911
+ url: '/api/v1/{region}/dashboard/expenses',
3669
3912
  path: {
3670
3913
  region: data.region
3671
3914
  },
3672
- body: data.requestBody,
3673
- mediaType: 'application/json',
3915
+ query: {
3916
+ groupBy: data.groupBy,
3917
+ period: data.period,
3918
+ flow: data.flow
3919
+ },
3674
3920
  errors: {
3675
- 400: 'Invalid date format or range',
3676
- 401: 'User not authenticated',
3677
- 409: 'Backfill already in progress for this user'
3921
+ 400: 'Invalid groupBy or period',
3922
+ 401: 'User not authenticated'
3923
+ }
3924
+ });
3925
+ }
3926
+ }
3927
+
3928
+ export class InvestmentService {
3929
+ /**
3930
+ * Get per-holding unrealized + realized P&L
3931
+ * Average-cost unrealized P&L per account × commodity, plus cumulative realized P&L on sold lots (method = FIFO | average, default average).
3932
+ * @param data The data for the request.
3933
+ * @param data.region Region code for tenant context
3934
+ * @param data.asOf As-of date (ISO 8601), defaults to today
3935
+ * @param data.accountId Scope to a single account
3936
+ * @param data.method Realized-P&L lot-matching method (default average). Does not affect the average-cost unrealized basis.
3937
+ * @returns HoldingPnlResponseDto Holding P&L retrieved successfully
3938
+ * @throws ApiError
3939
+ */
3940
+ public static holdingPnlControllerGetHoldingPnl(
3941
+ data: HoldingPnlControllerGetHoldingPnlData
3942
+ ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3943
+ return __request(OpenAPI, {
3944
+ method: 'GET',
3945
+ url: '/api/v1/{region}/investment/holdings/pnl',
3946
+ path: {
3947
+ region: data.region
3948
+ },
3949
+ query: {
3950
+ asOf: data.asOf,
3951
+ accountId: data.accountId,
3952
+ method: data.method
3953
+ },
3954
+ errors: {
3955
+ 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3956
+ 401: 'User not authenticated'
3678
3957
  }
3679
3958
  });
3680
3959
  }
@@ -3703,7 +3982,7 @@ export class AuthService {
3703
3982
  * Anonymous login with access token
3704
3983
  * @param data The data for the request.
3705
3984
  * @param data.requestBody
3706
- * @returns unknown Login successful
3985
+ * @returns AnonymousLoginResponseDto Login successful
3707
3986
  * @throws ApiError
3708
3987
  */
3709
3988
  public static authControllerAccessTokenLogin(