@firela/api-types 0.0.0-canary.3ed455fd → 0.0.0-canary.45a6cc23

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.
@@ -1855,7 +1855,8 @@ export const $ResolveResultDto = {
1855
1855
  },
1856
1856
  resolutionId: {
1857
1857
  type: 'string',
1858
- description: 'Resolution ID for undo'
1858
+ description:
1859
+ 'Resolution ID for undo. Absent when the resolver rejected the decision (review stayed PENDING).'
1859
1860
  },
1860
1861
  canUndo: {
1861
1862
  type: 'boolean',
@@ -1873,7 +1874,7 @@ export const $ResolveResultDto = {
1873
1874
  example: 'rule_01HXK5V8N2M3P4Q5R6S7T8U9V0'
1874
1875
  }
1875
1876
  },
1876
- required: ['success', 'resolutionId', 'canUndo', 'undoDeadline']
1877
+ required: ['success']
1877
1878
  } as const;
1878
1879
 
1879
1880
  export const $UndoResultDto = {
@@ -4311,6 +4312,144 @@ export const $UpdatePropertyDto = {
4311
4312
  required: ['value']
4312
4313
  } as const;
4313
4314
 
4315
+ export const $CreateBeanEventDto = {
4316
+ type: 'object',
4317
+ properties: {
4318
+ date: {
4319
+ type: 'string',
4320
+ description: 'Life event date (ISO 8601)',
4321
+ example: '2024-03-15'
4322
+ },
4323
+ type: {
4324
+ type: 'string',
4325
+ description:
4326
+ 'Life event type (e.g., "employer", "location", "marital-status") — user-defined, no enum constraint at engine layer',
4327
+ example: 'employer'
4328
+ },
4329
+ description: {
4330
+ type: 'string',
4331
+ description:
4332
+ 'Life event description. Empty string is a VALID value (distinct from absence).',
4333
+ example: 'Acme Corp'
4334
+ },
4335
+ meta: {
4336
+ type: 'object',
4337
+ description:
4338
+ 'Product-side metadata (lives in BeanEvent.meta JSON, never in engine Event fields)',
4339
+ example: {
4340
+ note: 'Promotion'
4341
+ }
4342
+ }
4343
+ },
4344
+ required: ['date', 'type', 'description']
4345
+ } as const;
4346
+
4347
+ export const $EventResponseDto = {
4348
+ type: 'object',
4349
+ properties: {
4350
+ id: {
4351
+ type: 'string',
4352
+ description: 'Unique identifier',
4353
+ example: 'uuid-123-456'
4354
+ },
4355
+ userId: {
4356
+ type: 'string',
4357
+ description: 'User ID (owner of the life event)',
4358
+ example: 'user-123'
4359
+ },
4360
+ date: {
4361
+ type: 'string',
4362
+ description: 'Life event date (ISO 8601 format)',
4363
+ example: '2024-03-15',
4364
+ format: 'date'
4365
+ },
4366
+ type: {
4367
+ type: 'string',
4368
+ description:
4369
+ 'Life event type (user-defined, e.g., "employer", "location")',
4370
+ example: 'employer'
4371
+ },
4372
+ description: {
4373
+ type: 'string',
4374
+ description:
4375
+ 'Life event description. May be an empty string (a valid value distinct from absence).',
4376
+ example: 'Acme Corp'
4377
+ },
4378
+ meta: {
4379
+ type: 'object',
4380
+ description: 'Product-side metadata (free-form JSON)',
4381
+ example: {
4382
+ note: 'Promotion'
4383
+ }
4384
+ },
4385
+ createdAt: {
4386
+ format: 'date-time',
4387
+ type: 'string',
4388
+ description: 'Creation timestamp',
4389
+ example: '2024-03-15T10:00:00Z'
4390
+ },
4391
+ updatedAt: {
4392
+ format: 'date-time',
4393
+ type: 'string',
4394
+ description:
4395
+ 'Last update timestamp. Also emitted as the ETag response header for If-Match optimistic concurrency.',
4396
+ example: '2024-03-15T10:00:00Z'
4397
+ }
4398
+ },
4399
+ required: [
4400
+ 'id',
4401
+ 'userId',
4402
+ 'date',
4403
+ 'type',
4404
+ 'description',
4405
+ 'meta',
4406
+ 'createdAt',
4407
+ 'updatedAt'
4408
+ ]
4409
+ } as const;
4410
+
4411
+ export const $EventListResponseDto = {
4412
+ type: 'object',
4413
+ properties: {
4414
+ items: {
4415
+ description: 'List of life events',
4416
+ type: 'array',
4417
+ items: {
4418
+ $ref: '#/components/schemas/EventResponseDto'
4419
+ }
4420
+ },
4421
+ total: {
4422
+ type: 'number',
4423
+ description: 'Total number of life events matching the query',
4424
+ example: 42
4425
+ }
4426
+ },
4427
+ required: ['items', 'total']
4428
+ } as const;
4429
+
4430
+ export const $UpdateBeanEventDto = {
4431
+ type: 'object',
4432
+ properties: {
4433
+ date: {
4434
+ type: 'string',
4435
+ description: 'Life event date (ISO 8601)'
4436
+ },
4437
+ type: {
4438
+ type: 'string',
4439
+ description: 'Life event type (user-defined)'
4440
+ },
4441
+ description: {
4442
+ type: 'string',
4443
+ description:
4444
+ 'Life event description. Empty string is a VALID value (distinct from absence).'
4445
+ },
4446
+ meta: {
4447
+ type: 'object',
4448
+ description: 'Product-side metadata (free-form JSON)'
4449
+ }
4450
+ }
4451
+ } as const;
4452
+
4314
4453
  export const $FileImportDto = {
4315
4454
  type: 'object',
4316
4455
  properties: {
@@ -6483,6 +6622,100 @@ export const $CashFlowResponseDto = {
6483
6622
  ]
6484
6623
  } as const;
6485
6624
 
6625
+ export const $CategoryGroupDto = {
6626
+ type: 'object',
6627
+ properties: {
6628
+ category: {
6629
+ type: 'string',
6630
+ description:
6631
+ 'Functional category (account-path Group segment); regional and universal account paths merge under it',
6632
+ example: 'Food'
6633
+ },
6634
+ totalExpense: {
6635
+ type: 'string',
6636
+ description: 'Converted total expense in base currency',
6637
+ example: '1200.00'
6638
+ },
6639
+ sharePct: {
6640
+ type: 'number',
6641
+ description: 'Share of grand total (0-100); 0 when grand total is 0',
6642
+ example: 42.5
6643
+ },
6644
+ balanceByCurrency: {
6645
+ description: 'Raw (unconverted) expense per currency',
6646
+ type: 'array',
6647
+ items: {
6648
+ $ref: '#/components/schemas/BalanceByCurrencyDto'
6649
+ }
6650
+ },
6651
+ convertedBalance: {
6652
+ type: 'string',
6653
+ description:
6654
+ 'Converted total in base currency (omitted when FX missing for all currencies in this category)',
6655
+ example: '1200.00'
6656
+ }
6657
+ },
6658
+ required: ['category', 'totalExpense', 'sharePct', 'balanceByCurrency']
6659
+ } as const;
6660
+
6661
+ export const $ExpensesByCategorySummaryDto = {
6662
+ type: 'object',
6663
+ properties: {
6664
+ totalExpense: {
6665
+ type: 'string',
6666
+ description:
6667
+ 'Total expense across all categories (converted; convertible categories only)',
6668
+ example: '5000.00'
6669
+ },
6670
+ categoryCount: {
6671
+ type: 'number',
6672
+ description: 'Number of categories',
6673
+ example: 8
6674
+ }
6675
+ },
6676
+ required: ['totalExpense', 'categoryCount']
6677
+ } as const;
6678
+
6679
+ export const $ExpensesByCategoryResponseDto = {
6680
+ type: 'object',
6681
+ properties: {
6682
+ period: {
6683
+ type: 'string',
6684
+ description: 'Period requested',
6685
+ example: '1m'
6686
+ },
6687
+ baseCurrency: {
6688
+ type: 'string',
6689
+ description: 'Base currency for converted values',
6690
+ example: 'CNY'
6691
+ },
6692
+ groups: {
6693
+ description:
6694
+ 'Expense groups by functional category, sorted by converted total desc',
6695
+ type: 'array',
6696
+ items: {
6697
+ $ref: '#/components/schemas/CategoryGroupDto'
6698
+ }
6699
+ },
6700
+ summary: {
6701
+ description: 'Summary statistics',
6702
+ allOf: [
6703
+ {
6704
+ $ref: '#/components/schemas/ExpensesByCategorySummaryDto'
6705
+ }
6706
+ ]
6707
+ },
6708
+ warnings: {
6709
+ description: 'Exchange rate warnings (e.g. missing rate for a currency)',
6710
+ type: 'array',
6711
+ items: {
6712
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
6713
+ }
6714
+ }
6715
+ },
6716
+ required: ['period', 'baseCurrency', 'groups', 'summary']
6717
+ } as const;
6718
+
6486
6719
  export const $MonetaryDto = {
6487
6720
  type: 'object',
6488
6721
  properties: {
@@ -6964,6 +7197,16 @@ export const $TimeSeriesPointDto = {
6964
7197
  description: 'Change from previous point',
6965
7198
  example: '5000.00'
6966
7199
  },
7200
+ assets: {
7201
+ type: 'string',
7202
+ description: 'Total assets at this date (in base currency)',
7203
+ example: '494338.00'
7204
+ },
7205
+ liabilities: {
7206
+ type: 'string',
7207
+ description: 'Total liabilities at this date (in base currency)',
7208
+ example: '310098.00'
7209
+ },
6967
7210
  byCurrency: {
6968
7211
  description: 'Multi-currency breakdown for this point',
6969
7212
  type: 'array',
@@ -7073,6 +7316,111 @@ export const $PortfolioTrendsResponseDto = {
7073
7316
  required: ['series', 'summary', 'period', 'granularity', 'currency']
7074
7317
  } as const;
7075
7318
 
7319
+ export const $CashFlowPointDto = {
7320
+ type: 'object',
7321
+ properties: {
7322
+ month: {
7323
+ type: 'string',
7324
+ description: 'Month key (YYYY-MM)',
7325
+ example: '2024-03'
7326
+ },
7327
+ income: {
7328
+ type: 'string',
7329
+ description: 'Income in base currency (absolute, converted)',
7330
+ example: '10000.00'
7331
+ },
7332
+ expense: {
7333
+ type: 'string',
7334
+ description: 'Expense in base currency (absolute, converted)',
7335
+ example: '5000.00'
7336
+ },
7337
+ netSavings: {
7338
+ type: 'string',
7339
+ description: 'netSavings = income − expense (savings positive)',
7340
+ example: '5000.00'
7341
+ }
7342
+ },
7343
+ required: ['month', 'income', 'expense', 'netSavings']
7344
+ } as const;
7345
+
7346
+ export const $CashFlowTrendSummaryDto = {
7347
+ type: 'object',
7348
+ properties: {
7349
+ totalIncome: {
7350
+ type: 'string',
7351
+ description: 'Total income across the period',
7352
+ example: '60000.00'
7353
+ },
7354
+ totalExpense: {
7355
+ type: 'string',
7356
+ description: 'Total expense across the period',
7357
+ example: '30000.00'
7358
+ },
7359
+ totalNetSavings: {
7360
+ type: 'string',
7361
+ description: 'income − expense across the period',
7362
+ example: '30000.00'
7363
+ },
7364
+ averageMonthlyNetSavings: {
7365
+ type: 'string',
7366
+ description:
7367
+ 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
7368
+ example: '5000.00'
7369
+ }
7370
+ },
7371
+ required: [
7372
+ 'totalIncome',
7373
+ 'totalExpense',
7374
+ 'totalNetSavings',
7375
+ 'averageMonthlyNetSavings'
7376
+ ]
7377
+ } as const;
7378
+
7379
+ export const $CashFlowTrendsResponseDto = {
7380
+ type: 'object',
7381
+ properties: {
7382
+ series: {
7383
+ description:
7384
+ 'Monthly cash-flow series (fixed N-month window, zero-filled)',
7385
+ type: 'array',
7386
+ items: {
7387
+ $ref: '#/components/schemas/CashFlowPointDto'
7388
+ }
7389
+ },
7390
+ summary: {
7391
+ description: 'Period totals',
7392
+ allOf: [
7393
+ {
7394
+ $ref: '#/components/schemas/CashFlowTrendSummaryDto'
7395
+ }
7396
+ ]
7397
+ },
7398
+ period: {
7399
+ type: 'string',
7400
+ description: 'Period requested',
7401
+ example: '6m'
7402
+ },
7403
+ granularity: {
7404
+ type: 'string',
7405
+ description: 'Data granularity (v1 returns month buckets)',
7406
+ example: 'month'
7407
+ },
7408
+ currency: {
7409
+ type: 'string',
7410
+ description: 'Base currency for converted values',
7411
+ example: 'CNY'
7412
+ },
7413
+ warnings: {
7414
+ description: 'Exchange rate warnings (e.g. missing rate for a currency)',
7415
+ type: 'array',
7416
+ items: {
7417
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
7418
+ }
7419
+ }
7420
+ },
7421
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
7422
+ } as const;
7423
+
7076
7424
  export const $GenerateSnapshotBody = {
7077
7425
  type: 'object',
7078
7426
  properties: {}
@@ -171,6 +171,18 @@ import type {
171
171
  PropertyControllerUpdateResponse,
172
172
  PropertyControllerDeleteData,
173
173
  PropertyControllerDeleteResponse,
174
+ EventControllerCreateData,
175
+ EventControllerCreateResponse,
176
+ EventControllerFindAllData,
177
+ EventControllerFindAllResponse,
178
+ EventControllerFindOneData,
179
+ EventControllerFindOneResponse,
180
+ EventControllerUpdateData,
181
+ EventControllerUpdateResponse,
182
+ EventControllerDeleteData,
183
+ EventControllerDeleteResponse,
184
+ EventControllerGetSliceData,
185
+ EventControllerGetSliceResponse,
174
186
  ExportControllerExportBeancountResponse,
175
187
  FileImportControllerImportFileData,
176
188
  FileImportControllerImportFileResponse,
@@ -218,6 +230,8 @@ import type {
218
230
  DashboardControllerGetAccountsResponse,
219
231
  DashboardControllerGetCashFlowData,
220
232
  DashboardControllerGetCashFlowResponse,
233
+ DashboardControllerGetExpensesData,
234
+ DashboardControllerGetExpensesResponse,
221
235
  HoldingPnlControllerGetHoldingPnlData,
222
236
  HoldingPnlControllerGetHoldingPnlResponse,
223
237
  PriceControllerCreateData,
@@ -234,6 +248,8 @@ import type {
234
248
  PriceControllerBulkCreateResponse,
235
249
  ReportingControllerGetPortfolioTrendsData,
236
250
  ReportingControllerGetPortfolioTrendsResponse,
251
+ ReportingControllerGetCashFlowTrendsData,
252
+ ReportingControllerGetCashFlowTrendsResponse,
237
253
  ReportingControllerGenerateSnapshotData,
238
254
  ReportingControllerGenerateSnapshotResponse,
239
255
  ReportingControllerBackfillSnapshotsData,
@@ -569,6 +585,7 @@ export class BeanTransactionsService {
569
585
  * @param data.status Filter by transaction status
570
586
  * @param data.search Search in narration and payee fields (max 200 chars)
571
587
  * @param data.accountId Filter by account ID (transactions with postings to this account)
588
+ * @param data.category Filter by ADR-0075 functional category (Group segment); matches any posting to an Expenses/Income account whose derived Group segment equals this value
572
589
  * @returns TransactionListResponseDto Transaction list
573
590
  * @throws ApiError
574
591
  */
@@ -588,7 +605,8 @@ export class BeanTransactionsService {
588
605
  dateTo: data.dateTo,
589
606
  status: data.status,
590
607
  search: data.search,
591
- accountId: data.accountId
608
+ accountId: data.accountId,
609
+ category: data.category
592
610
  },
593
611
  errors: {
594
612
  400: 'Validation failed',
@@ -2460,6 +2478,181 @@ export class PropertiesService {
2460
2478
  }
2461
2479
  }
2462
2480
 
2481
+ export class LifeEventsService {
2482
+ /**
2483
+ * Create a new life event
2484
+ * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2485
+ * @param data The data for the request.
2486
+ * @param data.region Region code for tenant context (decorative for life events)
2487
+ * @param data.requestBody
2488
+ * @returns EventResponseDto Life event created successfully
2489
+ * @throws ApiError
2490
+ */
2491
+ public static eventControllerCreate(
2492
+ data: EventControllerCreateData
2493
+ ): CancelablePromise<EventControllerCreateResponse> {
2494
+ return __request(OpenAPI, {
2495
+ method: 'POST',
2496
+ url: '/api/v1/{region}/bean/events',
2497
+ path: {
2498
+ region: data.region
2499
+ },
2500
+ body: data.requestBody,
2501
+ mediaType: 'application/json',
2502
+ errors: {
2503
+ 409: 'Life event already exists for this (userId, type, date) combination'
2504
+ }
2505
+ });
2506
+ }
2507
+
2508
+ /**
2509
+ * List user life events
2510
+ * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2511
+ * @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
2520
+ * @throws ApiError
2521
+ */
2522
+ public static eventControllerFindAll(
2523
+ data: EventControllerFindAllData
2524
+ ): CancelablePromise<EventControllerFindAllResponse> {
2525
+ return __request(OpenAPI, {
2526
+ method: 'GET',
2527
+ url: '/api/v1/{region}/bean/events',
2528
+ path: {
2529
+ region: data.region
2530
+ },
2531
+ 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
2538
+ }
2539
+ });
2540
+ }
2541
+
2542
+ /**
2543
+ * Get life event by ID
2544
+ * Returns a single life event by its ID. Returns ETag header.
2545
+ * @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
2549
+ * @throws ApiError
2550
+ */
2551
+ public static eventControllerFindOne(
2552
+ data: EventControllerFindOneData
2553
+ ): CancelablePromise<EventControllerFindOneResponse> {
2554
+ return __request(OpenAPI, {
2555
+ method: 'GET',
2556
+ url: '/api/v1/{region}/bean/events/{id}',
2557
+ path: {
2558
+ id: data.id,
2559
+ region: data.region
2560
+ },
2561
+ errors: {
2562
+ 404: 'Life event not found'
2563
+ }
2564
+ });
2565
+ }
2566
+
2567
+ /**
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.
2570
+ * @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)
2573
+ * @param data.requestBody
2574
+ * @returns EventResponseDto Life event updated successfully
2575
+ * @throws ApiError
2576
+ */
2577
+ public static eventControllerUpdate(
2578
+ data: EventControllerUpdateData
2579
+ ): CancelablePromise<EventControllerUpdateResponse> {
2580
+ return __request(OpenAPI, {
2581
+ method: 'PUT',
2582
+ url: '/api/v1/{region}/bean/events/{id}',
2583
+ path: {
2584
+ id: data.id,
2585
+ region: data.region
2586
+ },
2587
+ body: data.requestBody,
2588
+ mediaType: 'application/json',
2589
+ 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)'
2594
+ }
2595
+ });
2596
+ }
2597
+
2598
+ /**
2599
+ * Delete a life event
2600
+ * Deletes a life event entry (hard delete). Returns 204.
2601
+ * @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
2605
+ * @throws ApiError
2606
+ */
2607
+ public static eventControllerDelete(
2608
+ data: EventControllerDeleteData
2609
+ ): CancelablePromise<EventControllerDeleteResponse> {
2610
+ return __request(OpenAPI, {
2611
+ method: 'DELETE',
2612
+ url: '/api/v1/{region}/bean/events/{id}',
2613
+ path: {
2614
+ id: data.id,
2615
+ region: data.region
2616
+ },
2617
+ errors: {
2618
+ 404: 'Life event not found'
2619
+ }
2620
+ });
2621
+ }
2622
+
2623
+ /**
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.
2626
+ * @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
2632
+ * @throws ApiError
2633
+ */
2634
+ public static eventControllerGetSlice(
2635
+ data: EventControllerGetSliceData
2636
+ ): CancelablePromise<EventControllerGetSliceResponse> {
2637
+ return __request(OpenAPI, {
2638
+ method: 'GET',
2639
+ url: '/api/v1/{region}/bean/events/{id}/slice',
2640
+ path: {
2641
+ id: data.id,
2642
+ region: data.region
2643
+ },
2644
+ query: {
2645
+ accountPattern: data.accountPattern,
2646
+ granularity: data.granularity
2647
+ },
2648
+ errors: {
2649
+ 400: 'accountPattern query param is empty',
2650
+ 404: 'Life event not found'
2651
+ }
2652
+ });
2653
+ }
2654
+ }
2655
+
2463
2656
  export class BeanExportService {
2464
2657
  /**
2465
2658
  * Export Beancount ledger as ZIP
@@ -3097,6 +3290,36 @@ export class DashboardService {
3097
3290
  }
3098
3291
  });
3099
3292
  }
3293
+
3294
+ /**
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
3297
+ * @param data The data for the request.
3298
+ * @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
3302
+ * @throws ApiError
3303
+ */
3304
+ public static dashboardControllerGetExpenses(
3305
+ data: DashboardControllerGetExpensesData
3306
+ ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3307
+ return __request(OpenAPI, {
3308
+ method: 'GET',
3309
+ url: '/api/v1/{region}/dashboard/expenses',
3310
+ path: {
3311
+ region: data.region
3312
+ },
3313
+ query: {
3314
+ groupBy: data.groupBy,
3315
+ period: data.period
3316
+ },
3317
+ errors: {
3318
+ 400: 'Invalid groupBy or period',
3319
+ 401: 'User not authenticated'
3320
+ }
3321
+ });
3322
+ }
3100
3323
  }
3101
3324
 
3102
3325
  export class InvestmentService {
@@ -3341,6 +3564,42 @@ export class ReportingService {
3341
3564
  });
3342
3565
  }
3343
3566
 
3567
+ /**
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
+ *
3577
+ * @param data The data for the request.
3578
+ * @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
3582
+ * @throws ApiError
3583
+ */
3584
+ public static reportingControllerGetCashFlowTrends(
3585
+ data: ReportingControllerGetCashFlowTrendsData
3586
+ ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
3587
+ return __request(OpenAPI, {
3588
+ method: 'GET',
3589
+ url: '/api/v1/{region}/reporting/cash-flow/trends',
3590
+ path: {
3591
+ region: data.region
3592
+ },
3593
+ query: {
3594
+ period: data.period,
3595
+ granularity: data.granularity
3596
+ },
3597
+ errors: {
3598
+ 401: 'User not authenticated'
3599
+ }
3600
+ });
3601
+ }
3602
+
3344
3603
  /**
3345
3604
  * Generate portfolio snapshot
3346
3605
  *