@robosystems/client 0.2.49 → 0.3.0
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.
- package/extensions/InvestorClient.d.ts +91 -0
- package/extensions/InvestorClient.js +223 -0
- package/extensions/InvestorClient.ts +501 -0
- package/extensions/LedgerClient.d.ts +183 -309
- package/extensions/LedgerClient.js +268 -587
- package/extensions/LedgerClient.ts +777 -903
- package/extensions/ReportClient.d.ts +77 -115
- package/extensions/ReportClient.js +124 -211
- package/extensions/ReportClient.ts +298 -358
- package/extensions/config.js +1 -1
- package/extensions/config.ts +1 -1
- package/extensions/graphql/client.d.ts +46 -0
- package/extensions/graphql/client.js +75 -0
- package/extensions/graphql/client.ts +82 -0
- package/extensions/graphql/generated/graphql.d.ts +1786 -0
- package/extensions/graphql/generated/graphql.js +2671 -0
- package/extensions/graphql/generated/graphql.ts +4491 -0
- package/extensions/graphql/queries/investor/holdings.d.ts +8 -0
- package/extensions/graphql/queries/investor/holdings.js +36 -0
- package/extensions/graphql/queries/investor/holdings.ts +34 -0
- package/extensions/graphql/queries/investor/portfolio.d.ts +4 -0
- package/extensions/graphql/queries/investor/portfolio.js +21 -0
- package/extensions/graphql/queries/investor/portfolio.ts +19 -0
- package/extensions/graphql/queries/investor/portfolios.d.ts +4 -0
- package/extensions/graphql/queries/investor/portfolios.js +29 -0
- package/extensions/graphql/queries/investor/portfolios.ts +27 -0
- package/extensions/graphql/queries/investor/position.d.ts +4 -0
- package/extensions/graphql/queries/investor/position.js +33 -0
- package/extensions/graphql/queries/investor/position.ts +31 -0
- package/extensions/graphql/queries/investor/positions.d.ts +8 -0
- package/extensions/graphql/queries/investor/positions.js +57 -0
- package/extensions/graphql/queries/investor/positions.ts +55 -0
- package/extensions/graphql/queries/investor/securities.d.ts +8 -0
- package/extensions/graphql/queries/investor/securities.js +50 -0
- package/extensions/graphql/queries/investor/securities.ts +48 -0
- package/extensions/graphql/queries/investor/security.d.ts +4 -0
- package/extensions/graphql/queries/investor/security.js +26 -0
- package/extensions/graphql/queries/investor/security.ts +24 -0
- package/extensions/graphql/queries/ledger/accountRollups.d.ts +7 -0
- package/extensions/graphql/queries/ledger/accountRollups.js +36 -0
- package/extensions/graphql/queries/ledger/accountRollups.ts +34 -0
- package/extensions/graphql/queries/ledger/accountTree.d.ts +11 -0
- package/extensions/graphql/queries/ledger/accountTree.js +61 -0
- package/extensions/graphql/queries/ledger/accountTree.ts +59 -0
- package/extensions/graphql/queries/ledger/accounts.d.ts +8 -0
- package/extensions/graphql/queries/ledger/accounts.js +45 -0
- package/extensions/graphql/queries/ledger/accounts.ts +43 -0
- package/extensions/graphql/queries/ledger/closingBookStructures.d.ts +6 -0
- package/extensions/graphql/queries/ledger/closingBookStructures.js +27 -0
- package/extensions/graphql/queries/ledger/closingBookStructures.ts +25 -0
- package/extensions/graphql/queries/ledger/elements.d.ts +6 -0
- package/extensions/graphql/queries/ledger/elements.js +56 -0
- package/extensions/graphql/queries/ledger/elements.ts +54 -0
- package/extensions/graphql/queries/ledger/entities.d.ts +7 -0
- package/extensions/graphql/queries/ledger/entities.js +31 -0
- package/extensions/graphql/queries/ledger/entities.ts +29 -0
- package/extensions/graphql/queries/ledger/entity.d.ts +14 -0
- package/extensions/graphql/queries/ledger/entity.js +55 -0
- package/extensions/graphql/queries/ledger/entity.ts +54 -0
- package/extensions/graphql/queries/ledger/fiscalCalendar.d.ts +8 -0
- package/extensions/graphql/queries/ledger/fiscalCalendar.js +35 -0
- package/extensions/graphql/queries/ledger/fiscalCalendar.ts +33 -0
- package/extensions/graphql/queries/ledger/mappedTrialBalance.d.ts +9 -0
- package/extensions/graphql/queries/ledger/mappedTrialBalance.js +29 -0
- package/extensions/graphql/queries/ledger/mappedTrialBalance.ts +27 -0
- package/extensions/graphql/queries/ledger/mapping.d.ts +5 -0
- package/extensions/graphql/queries/ledger/mapping.js +35 -0
- package/extensions/graphql/queries/ledger/mapping.ts +33 -0
- package/extensions/graphql/queries/ledger/mappingCoverage.d.ts +5 -0
- package/extensions/graphql/queries/ledger/mappingCoverage.js +22 -0
- package/extensions/graphql/queries/ledger/mappingCoverage.ts +20 -0
- package/extensions/graphql/queries/ledger/mappings.d.ts +6 -0
- package/extensions/graphql/queries/ledger/mappings.js +23 -0
- package/extensions/graphql/queries/ledger/mappings.ts +21 -0
- package/extensions/graphql/queries/ledger/periodCloseStatus.d.ts +6 -0
- package/extensions/graphql/queries/ledger/periodCloseStatus.js +29 -0
- package/extensions/graphql/queries/ledger/periodCloseStatus.ts +27 -0
- package/extensions/graphql/queries/ledger/periodDrafts.d.ts +8 -0
- package/extensions/graphql/queries/ledger/periodDrafts.js +45 -0
- package/extensions/graphql/queries/ledger/periodDrafts.ts +43 -0
- package/extensions/graphql/queries/ledger/publishList.d.ts +5 -0
- package/extensions/graphql/queries/ledger/publishList.js +29 -0
- package/extensions/graphql/queries/ledger/publishList.ts +27 -0
- package/extensions/graphql/queries/ledger/publishLists.d.ts +5 -0
- package/extensions/graphql/queries/ledger/publishLists.js +29 -0
- package/extensions/graphql/queries/ledger/publishLists.ts +27 -0
- package/extensions/graphql/queries/ledger/report.d.ts +5 -0
- package/extensions/graphql/queries/ledger/report.js +40 -0
- package/extensions/graphql/queries/ledger/report.ts +38 -0
- package/extensions/graphql/queries/ledger/reportingTaxonomy.d.ts +6 -0
- package/extensions/graphql/queries/ledger/reportingTaxonomy.js +27 -0
- package/extensions/graphql/queries/ledger/reportingTaxonomy.ts +25 -0
- package/extensions/graphql/queries/ledger/reports.d.ts +8 -0
- package/extensions/graphql/queries/ledger/reports.js +45 -0
- package/extensions/graphql/queries/ledger/reports.ts +43 -0
- package/extensions/graphql/queries/ledger/scheduleFacts.d.ts +7 -0
- package/extensions/graphql/queries/ledger/scheduleFacts.js +24 -0
- package/extensions/graphql/queries/ledger/scheduleFacts.ts +22 -0
- package/extensions/graphql/queries/ledger/schedules.d.ts +6 -0
- package/extensions/graphql/queries/ledger/schedules.js +24 -0
- package/extensions/graphql/queries/ledger/schedules.ts +22 -0
- package/extensions/graphql/queries/ledger/statement.d.ts +9 -0
- package/extensions/graphql/queries/ledger/statement.js +43 -0
- package/extensions/graphql/queries/ledger/statement.ts +41 -0
- package/extensions/graphql/queries/ledger/structures.d.ts +5 -0
- package/extensions/graphql/queries/ledger/structures.js +22 -0
- package/extensions/graphql/queries/ledger/structures.ts +20 -0
- package/extensions/graphql/queries/ledger/summary.d.ts +7 -0
- package/extensions/graphql/queries/ledger/summary.js +25 -0
- package/extensions/graphql/queries/ledger/summary.ts +23 -0
- package/extensions/graphql/queries/ledger/taxonomies.d.ts +5 -0
- package/extensions/graphql/queries/ledger/taxonomies.js +28 -0
- package/extensions/graphql/queries/ledger/taxonomies.ts +26 -0
- package/extensions/graphql/queries/ledger/transaction.d.ts +6 -0
- package/extensions/graphql/queries/ledger/transaction.js +49 -0
- package/extensions/graphql/queries/ledger/transaction.ts +47 -0
- package/extensions/graphql/queries/ledger/transactions.d.ts +7 -0
- package/extensions/graphql/queries/ledger/transactions.js +49 -0
- package/extensions/graphql/queries/ledger/transactions.ts +47 -0
- package/extensions/graphql/queries/ledger/trialBalance.d.ts +7 -0
- package/extensions/graphql/queries/ledger/trialBalance.js +28 -0
- package/extensions/graphql/queries/ledger/trialBalance.ts +26 -0
- package/extensions/graphql/queries/ledger/unmappedElements.d.ts +8 -0
- package/extensions/graphql/queries/ledger/unmappedElements.js +29 -0
- package/extensions/graphql/queries/ledger/unmappedElements.ts +27 -0
- package/extensions/hooks.d.ts +1 -1
- package/extensions/index.d.ts +5 -1
- package/extensions/index.js +13 -1
- package/extensions/index.ts +14 -0
- package/index.ts +2 -2
- package/package.json +14 -5
- package/sdk/index.d.ts +2 -2
- package/sdk/index.js +38 -73
- package/sdk/index.ts +2 -2
- package/sdk/sdk.gen.d.ts +100 -325
- package/sdk/sdk.gen.js +228 -592
- package/sdk/sdk.gen.ts +193 -556
- package/sdk/types.gen.d.ts +4522 -7708
- package/sdk/types.gen.ts +4569 -7983
- package/sdk.gen.d.ts +100 -325
- package/sdk.gen.js +228 -592
- package/sdk.gen.ts +193 -556
- package/types.gen.d.ts +4522 -7708
- package/types.gen.ts +4569 -7983
- package/extensions/AgentClient.test.ts +0 -403
- package/extensions/LedgerClient.test.ts +0 -1655
- package/extensions/OperationClient.test.ts +0 -365
- package/extensions/QueryClient.test.ts +0 -432
- package/extensions/ReportClient.test.ts +0 -828
- package/extensions/SSEClient.test.ts +0 -375
- package/extensions/config.test.ts +0 -199
- package/extensions/hooks.test.ts +0 -373
- package/extensions/index.test.ts +0 -420
- package/sdk-extensions/AgentClient.d.ts +0 -82
- package/sdk-extensions/AgentClient.js +0 -218
- package/sdk-extensions/AgentClient.test.ts +0 -403
- package/sdk-extensions/AgentClient.ts +0 -321
- package/sdk-extensions/LedgerClient.d.ts +0 -416
- package/sdk-extensions/LedgerClient.js +0 -737
- package/sdk-extensions/LedgerClient.test.ts +0 -1655
- package/sdk-extensions/LedgerClient.ts +0 -1249
- package/sdk-extensions/OperationClient.d.ts +0 -65
- package/sdk-extensions/OperationClient.js +0 -251
- package/sdk-extensions/OperationClient.test.ts +0 -365
- package/sdk-extensions/OperationClient.ts +0 -324
- package/sdk-extensions/QueryClient.d.ts +0 -52
- package/sdk-extensions/QueryClient.js +0 -313
- package/sdk-extensions/QueryClient.test.ts +0 -432
- package/sdk-extensions/QueryClient.ts +0 -420
- package/sdk-extensions/README.md +0 -901
- package/sdk-extensions/ReportClient.d.ts +0 -151
- package/sdk-extensions/ReportClient.js +0 -278
- package/sdk-extensions/ReportClient.test.ts +0 -828
- package/sdk-extensions/ReportClient.ts +0 -486
- package/sdk-extensions/SSEClient.d.ts +0 -62
- package/sdk-extensions/SSEClient.js +0 -154
- package/sdk-extensions/SSEClient.test.ts +0 -375
- package/sdk-extensions/SSEClient.ts +0 -210
- package/sdk-extensions/config.d.ts +0 -57
- package/sdk-extensions/config.js +0 -152
- package/sdk-extensions/config.test.ts +0 -199
- package/sdk-extensions/config.ts +0 -175
- package/sdk-extensions/hooks.d.ts +0 -110
- package/sdk-extensions/hooks.js +0 -384
- package/sdk-extensions/hooks.test.ts +0 -373
- package/sdk-extensions/hooks.ts +0 -459
- package/sdk-extensions/index.d.ts +0 -63
- package/sdk-extensions/index.js +0 -164
- package/sdk-extensions/index.test.ts +0 -420
- package/sdk-extensions/index.ts +0 -203
|
@@ -3,174 +3,259 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Ledger Client for RoboSystems API
|
|
5
5
|
*
|
|
6
|
-
* High-level
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* High-level facade for everything the RoboLedger domain exposes:
|
|
7
|
+
* entity, chart of accounts, transactions, taxonomy + mappings, fiscal
|
|
8
|
+
* calendar, schedules, reports, and publish lists.
|
|
9
|
+
*
|
|
10
|
+
* **Transport split:**
|
|
11
|
+
* - **Reads** go through GraphQL at `/extensions/{graph_id}/graphql`
|
|
12
|
+
* (via `graphql-request`, with typed documents produced by GraphQL
|
|
13
|
+
* Code Generator). The graph is in the URL, not in the query.
|
|
14
|
+
* - **Writes** go through named command operations at
|
|
15
|
+
* `/extensions/roboledger/{graph_id}/operations/{operation_name}`
|
|
16
|
+
* (via the OpenAPI-generated `opXxx` functions in `../sdk/sdk.gen`).
|
|
17
|
+
* Each command returns an `OperationEnvelope`; the facade unwraps
|
|
18
|
+
* `envelope.result` and returns a friendly camelCase type.
|
|
19
|
+
*
|
|
20
|
+
* Consumers don't need to know which transport a method uses — the
|
|
21
|
+
* facade signature stays stable. The only trick is that write method
|
|
22
|
+
* results are cast from the envelope's untyped `result` field.
|
|
9
23
|
*/
|
|
10
24
|
|
|
25
|
+
import type { TypedDocumentNode } from '@graphql-typed-document-node/core'
|
|
26
|
+
import { ClientError } from 'graphql-request'
|
|
11
27
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
getLedgerTransaction,
|
|
27
|
-
getLedgerTrialBalance,
|
|
28
|
-
getMappedTrialBalance,
|
|
29
|
-
getMappingCoverage,
|
|
30
|
-
getMappingDetail,
|
|
31
|
-
getPeriodCloseStatus,
|
|
32
|
-
getReportingTaxonomy,
|
|
33
|
-
getScheduleFacts,
|
|
34
|
-
initializeLedger,
|
|
35
|
-
listElements,
|
|
36
|
-
listLedgerAccounts,
|
|
37
|
-
listLedgerTransactions,
|
|
38
|
-
listMappings,
|
|
39
|
-
listPeriodDrafts,
|
|
40
|
-
listSchedules,
|
|
41
|
-
listStructures,
|
|
42
|
-
reopenFiscalPeriod,
|
|
43
|
-
setCloseTarget,
|
|
44
|
-
truncateSchedule,
|
|
28
|
+
opAutoMapElements,
|
|
29
|
+
opClosePeriod,
|
|
30
|
+
opCreateClosingEntry,
|
|
31
|
+
opCreateManualClosingEntry,
|
|
32
|
+
opCreateMappingAssociation,
|
|
33
|
+
opCreateSchedule,
|
|
34
|
+
opCreateStructure,
|
|
35
|
+
opCreateTaxonomy,
|
|
36
|
+
opDeleteMappingAssociation,
|
|
37
|
+
opInitializeLedger,
|
|
38
|
+
opReopenPeriod,
|
|
39
|
+
opSetCloseTarget,
|
|
40
|
+
opTruncateSchedule,
|
|
41
|
+
opUpdateEntity,
|
|
45
42
|
} from '../sdk.gen'
|
|
46
43
|
import type {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
ClosePeriodRequest,
|
|
51
|
-
ClosePeriodResponse,
|
|
52
|
-
ClosingBookStructuresResponse,
|
|
53
|
-
ClosingEntryResponse,
|
|
54
|
-
CreateClosingEntryRequest,
|
|
44
|
+
AutoMapElementsOperation,
|
|
45
|
+
ClosePeriodOperation,
|
|
46
|
+
CreateClosingEntryOperation,
|
|
55
47
|
CreateManualClosingEntryRequest,
|
|
48
|
+
CreateMappingAssociationOperation,
|
|
56
49
|
CreateScheduleRequest,
|
|
57
|
-
|
|
50
|
+
CreateStructureRequest,
|
|
51
|
+
CreateTaxonomyRequest,
|
|
52
|
+
DeleteMappingAssociationOperation,
|
|
58
53
|
InitializeLedgerRequest,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
MappingDetailResponse,
|
|
65
|
-
PeriodCloseItemResponse,
|
|
66
|
-
PeriodCloseStatusResponse,
|
|
67
|
-
PeriodDraftsResponse,
|
|
68
|
-
ReopenPeriodRequest,
|
|
69
|
-
ScheduleCreatedResponse,
|
|
70
|
-
ScheduleFactResponse,
|
|
71
|
-
ScheduleFactsResponse,
|
|
72
|
-
ScheduleListResponse,
|
|
73
|
-
ScheduleSummaryResponse,
|
|
74
|
-
SetCloseTargetRequest,
|
|
75
|
-
TrialBalanceResponse,
|
|
76
|
-
TruncateScheduleRequest,
|
|
77
|
-
TruncateScheduleResponse,
|
|
54
|
+
OperationEnvelope,
|
|
55
|
+
ReopenPeriodOperation,
|
|
56
|
+
SetCloseTargetOperation,
|
|
57
|
+
TruncateScheduleOperation,
|
|
58
|
+
UpdateEntityRequest,
|
|
78
59
|
} from '../types.gen'
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
60
|
+
import { GraphQLClientCache } from './graphql/client'
|
|
61
|
+
import {
|
|
62
|
+
GetLedgerAccountRollupsDocument,
|
|
63
|
+
GetLedgerAccountTreeDocument,
|
|
64
|
+
GetLedgerClosingBookStructuresDocument,
|
|
65
|
+
GetLedgerEntityDocument,
|
|
66
|
+
GetLedgerFiscalCalendarDocument,
|
|
67
|
+
GetLedgerMappedTrialBalanceDocument,
|
|
68
|
+
GetLedgerMappingCoverageDocument,
|
|
69
|
+
GetLedgerMappingDocument,
|
|
70
|
+
GetLedgerPeriodCloseStatusDocument,
|
|
71
|
+
GetLedgerPeriodDraftsDocument,
|
|
72
|
+
GetLedgerReportingTaxonomyDocument,
|
|
73
|
+
GetLedgerScheduleFactsDocument,
|
|
74
|
+
GetLedgerSummaryDocument,
|
|
75
|
+
GetLedgerTransactionDocument,
|
|
76
|
+
GetLedgerTrialBalanceDocument,
|
|
77
|
+
ListLedgerAccountsDocument,
|
|
78
|
+
ListLedgerElementsDocument,
|
|
79
|
+
ListLedgerEntitiesDocument,
|
|
80
|
+
ListLedgerMappingsDocument,
|
|
81
|
+
ListLedgerSchedulesDocument,
|
|
82
|
+
ListLedgerStructuresDocument,
|
|
83
|
+
ListLedgerTaxonomiesDocument,
|
|
84
|
+
ListLedgerTransactionsDocument,
|
|
85
|
+
ListLedgerUnmappedElementsDocument,
|
|
86
|
+
type GetLedgerAccountRollupsQuery,
|
|
87
|
+
type GetLedgerAccountTreeQuery,
|
|
88
|
+
type GetLedgerClosingBookStructuresQuery,
|
|
89
|
+
type GetLedgerEntityQuery,
|
|
90
|
+
type GetLedgerFiscalCalendarQuery,
|
|
91
|
+
type GetLedgerMappedTrialBalanceQuery,
|
|
92
|
+
type GetLedgerMappingCoverageQuery,
|
|
93
|
+
type GetLedgerMappingQuery,
|
|
94
|
+
type GetLedgerPeriodCloseStatusQuery,
|
|
95
|
+
type GetLedgerPeriodDraftsQuery,
|
|
96
|
+
type GetLedgerReportingTaxonomyQuery,
|
|
97
|
+
type GetLedgerScheduleFactsQuery,
|
|
98
|
+
type GetLedgerSummaryQuery,
|
|
99
|
+
type GetLedgerTransactionQuery,
|
|
100
|
+
type GetLedgerTrialBalanceQuery,
|
|
101
|
+
type ListLedgerAccountsQuery,
|
|
102
|
+
type ListLedgerElementsQuery,
|
|
103
|
+
type ListLedgerEntitiesQuery,
|
|
104
|
+
type ListLedgerMappingsQuery,
|
|
105
|
+
type ListLedgerSchedulesQuery,
|
|
106
|
+
type ListLedgerStructuresQuery,
|
|
107
|
+
type ListLedgerTaxonomiesQuery,
|
|
108
|
+
type ListLedgerTransactionsQuery,
|
|
109
|
+
type ListLedgerUnmappedElementsQuery,
|
|
110
|
+
} from './graphql/generated/graphql'
|
|
111
|
+
|
|
112
|
+
// ── Friendly types derived from GraphQL codegen ────────────────────────
|
|
113
|
+
//
|
|
114
|
+
// These are the single source of truth for read payload shapes. Write
|
|
115
|
+
// methods also return these where the operation result is semantically
|
|
116
|
+
// the same thing (e.g. close-period returns the updated fiscal calendar,
|
|
117
|
+
// the same shape as the fiscalCalendar read).
|
|
118
|
+
|
|
119
|
+
export type LedgerEntity = NonNullable<GetLedgerEntityQuery['entity']>
|
|
120
|
+
export type LedgerEntitySummary = ListLedgerEntitiesQuery['entities'][number]
|
|
121
|
+
|
|
122
|
+
export type LedgerSummary = NonNullable<GetLedgerSummaryQuery['summary']>
|
|
123
|
+
|
|
124
|
+
export type LedgerAccountList = NonNullable<ListLedgerAccountsQuery['accounts']>
|
|
125
|
+
export type LedgerAccount = LedgerAccountList['accounts'][number]
|
|
126
|
+
export type LedgerAccountTree = NonNullable<GetLedgerAccountTreeQuery['accountTree']>
|
|
127
|
+
export type LedgerAccountRollups = NonNullable<GetLedgerAccountRollupsQuery['accountRollups']>
|
|
128
|
+
|
|
129
|
+
export type LedgerTrialBalance = NonNullable<GetLedgerTrialBalanceQuery['trialBalance']>
|
|
130
|
+
export type LedgerMappedTrialBalance = NonNullable<
|
|
131
|
+
GetLedgerMappedTrialBalanceQuery['mappedTrialBalance']
|
|
132
|
+
>
|
|
133
|
+
|
|
134
|
+
export type LedgerTransactionList = NonNullable<ListLedgerTransactionsQuery['transactions']>
|
|
135
|
+
export type LedgerTransactionListItem = LedgerTransactionList['transactions'][number]
|
|
136
|
+
export type LedgerTransaction = NonNullable<GetLedgerTransactionQuery['transaction']>
|
|
137
|
+
|
|
138
|
+
export type LedgerReportingTaxonomy = NonNullable<
|
|
139
|
+
GetLedgerReportingTaxonomyQuery['reportingTaxonomy']
|
|
140
|
+
>
|
|
141
|
+
export type LedgerTaxonomyList = NonNullable<ListLedgerTaxonomiesQuery['taxonomies']>
|
|
142
|
+
export type LedgerTaxonomy = LedgerTaxonomyList['taxonomies'][number]
|
|
143
|
+
|
|
144
|
+
export type LedgerElementList = NonNullable<ListLedgerElementsQuery['elements']>
|
|
145
|
+
export type LedgerElement = LedgerElementList['elements'][number]
|
|
146
|
+
export type LedgerUnmappedElement = ListLedgerUnmappedElementsQuery['unmappedElements'][number]
|
|
147
|
+
|
|
148
|
+
export type LedgerStructureList = NonNullable<ListLedgerStructuresQuery['structures']>
|
|
149
|
+
export type LedgerStructure = LedgerStructureList['structures'][number]
|
|
150
|
+
|
|
151
|
+
export type LedgerMappingList = NonNullable<ListLedgerMappingsQuery['mappings']>
|
|
152
|
+
export type LedgerMappingInfo = LedgerMappingList['structures'][number]
|
|
153
|
+
export type LedgerMapping = NonNullable<GetLedgerMappingQuery['mapping']>
|
|
154
|
+
export type LedgerMappingCoverage = NonNullable<GetLedgerMappingCoverageQuery['mappingCoverage']>
|
|
155
|
+
|
|
156
|
+
export type LedgerScheduleList = NonNullable<ListLedgerSchedulesQuery['schedules']>
|
|
157
|
+
export type LedgerSchedule = LedgerScheduleList['schedules'][number]
|
|
158
|
+
export type LedgerScheduleFacts = NonNullable<GetLedgerScheduleFactsQuery['scheduleFacts']>
|
|
159
|
+
export type LedgerScheduleFact = LedgerScheduleFacts['facts'][number]
|
|
160
|
+
|
|
161
|
+
export type LedgerPeriodCloseStatus = NonNullable<
|
|
162
|
+
GetLedgerPeriodCloseStatusQuery['periodCloseStatus']
|
|
163
|
+
>
|
|
164
|
+
export type LedgerPeriodCloseItem = LedgerPeriodCloseStatus['schedules'][number]
|
|
165
|
+
export type LedgerPeriodDrafts = NonNullable<GetLedgerPeriodDraftsQuery['periodDrafts']>
|
|
166
|
+
export type LedgerDraftEntry = LedgerPeriodDrafts['drafts'][number]
|
|
167
|
+
export type LedgerDraftLineItem = LedgerDraftEntry['lineItems'][number]
|
|
168
|
+
|
|
169
|
+
export type LedgerClosingBookStructures = NonNullable<
|
|
170
|
+
GetLedgerClosingBookStructuresQuery['closingBookStructures']
|
|
171
|
+
>
|
|
172
|
+
|
|
173
|
+
export type LedgerFiscalCalendar = NonNullable<GetLedgerFiscalCalendarQuery['fiscalCalendar']>
|
|
174
|
+
export type LedgerFiscalPeriod = LedgerFiscalCalendar['periods'][number]
|
|
175
|
+
|
|
176
|
+
// ── Write result shapes (envelope.result payloads) ─────────────────────
|
|
177
|
+
//
|
|
178
|
+
// Backend Pydantic models serialize these write results in snake_case.
|
|
179
|
+
// The facade converts to camelCase where the result is meaningful to
|
|
180
|
+
// consumers; for simple ack/ack-with-id payloads we keep the raw shape.
|
|
181
|
+
|
|
182
|
+
/** Snake-case shape returned in envelope.result for fiscal calendar writes. */
|
|
183
|
+
interface RawFiscalCalendar {
|
|
184
|
+
graph_id: string
|
|
185
|
+
fiscal_year_start_month: number
|
|
186
|
+
closed_through: string | null
|
|
187
|
+
close_target: string | null
|
|
188
|
+
gap_periods: number
|
|
189
|
+
catch_up_sequence: string[]
|
|
190
|
+
closeable_now: boolean
|
|
191
|
+
blockers: string[]
|
|
192
|
+
last_close_at: string | null
|
|
193
|
+
initialized_at: string | null
|
|
194
|
+
last_sync_at: string | null
|
|
195
|
+
periods: Array<{
|
|
196
|
+
name: string
|
|
197
|
+
start_date: string
|
|
198
|
+
end_date: string
|
|
199
|
+
status: string
|
|
200
|
+
closed_at: string | null
|
|
201
|
+
}>
|
|
89
202
|
}
|
|
90
203
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
structureType: string
|
|
96
|
-
taxonomyId: string
|
|
97
|
-
isActive: boolean
|
|
204
|
+
interface RawInitializeLedgerResult {
|
|
205
|
+
fiscal_calendar: RawFiscalCalendar
|
|
206
|
+
periods_created: number
|
|
207
|
+
warnings: string[]
|
|
98
208
|
}
|
|
99
209
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
highConfidence: number
|
|
106
|
-
mediumConfidence: number
|
|
107
|
-
lowConfidence: number
|
|
210
|
+
interface RawClosePeriodResult {
|
|
211
|
+
period: string
|
|
212
|
+
entries_posted: number
|
|
213
|
+
target_auto_advanced: boolean
|
|
214
|
+
fiscal_calendar: RawFiscalCalendar
|
|
108
215
|
}
|
|
109
216
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
217
|
+
interface RawClosingEntryResult {
|
|
218
|
+
outcome: ClosingEntryOutcome
|
|
219
|
+
entry_id: string | null
|
|
220
|
+
status: string | null
|
|
221
|
+
posting_date: string | null
|
|
222
|
+
memo: string | null
|
|
223
|
+
debit_element_id: string | null
|
|
224
|
+
credit_element_id: string | null
|
|
225
|
+
amount: number | null
|
|
226
|
+
reason: string | null
|
|
114
227
|
}
|
|
115
228
|
|
|
116
|
-
|
|
117
|
-
|
|
229
|
+
interface RawScheduleCreatedResult {
|
|
230
|
+
structure_id: string
|
|
118
231
|
name: string
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
totalPeriods: number
|
|
123
|
-
periodsWithEntries: number
|
|
232
|
+
taxonomy_id: string
|
|
233
|
+
total_periods: number
|
|
234
|
+
total_facts: number
|
|
124
235
|
}
|
|
125
236
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
totalFacts: number
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export interface ScheduleFact {
|
|
135
|
-
elementId: string
|
|
136
|
-
elementName: string
|
|
137
|
-
value: number
|
|
138
|
-
periodStart: string
|
|
139
|
-
periodEnd: string
|
|
237
|
+
interface RawTruncateScheduleResult {
|
|
238
|
+
structure_id: string
|
|
239
|
+
new_end_date: string
|
|
240
|
+
facts_deleted: number
|
|
241
|
+
reason: string
|
|
140
242
|
}
|
|
141
243
|
|
|
142
|
-
export interface
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
status: string
|
|
147
|
-
entryId: string | null
|
|
244
|
+
export interface InitializeLedgerResult {
|
|
245
|
+
fiscalCalendar: LedgerFiscalCalendar
|
|
246
|
+
periodsCreated: number
|
|
247
|
+
warnings: string[]
|
|
148
248
|
}
|
|
149
249
|
|
|
150
|
-
export interface
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
totalDraft: number
|
|
156
|
-
totalPosted: number
|
|
250
|
+
export interface ClosePeriodResult {
|
|
251
|
+
period: string
|
|
252
|
+
entriesPosted: number
|
|
253
|
+
targetAutoAdvanced: boolean
|
|
254
|
+
fiscalCalendar: LedgerFiscalCalendar
|
|
157
255
|
}
|
|
158
256
|
|
|
159
|
-
/**
|
|
160
|
-
* Outcome of an idempotent `createClosingEntry` call.
|
|
161
|
-
*
|
|
162
|
-
* - `created` — no prior draft, new draft created
|
|
163
|
-
* - `unchanged` — prior draft matches current schedule fact, no-op
|
|
164
|
-
* - `regenerated` — prior draft was stale, replaced with a fresh one
|
|
165
|
-
* - `removed` — prior draft existed but schedule no longer covers this period
|
|
166
|
-
* - `skipped` — no prior draft and no in-scope fact; nothing to do
|
|
167
|
-
*/
|
|
168
257
|
export type ClosingEntryOutcome = 'created' | 'unchanged' | 'regenerated' | 'removed' | 'skipped'
|
|
169
258
|
|
|
170
|
-
/**
|
|
171
|
-
* Result of an idempotent closing-entry call. `entry_id`, `amount`, and
|
|
172
|
-
* related fields are null for `removed` and `skipped` outcomes.
|
|
173
|
-
*/
|
|
174
259
|
export interface ClosingEntry {
|
|
175
260
|
outcome: ClosingEntryOutcome
|
|
176
261
|
entryId: string | null
|
|
@@ -183,33 +268,25 @@ export interface ClosingEntry {
|
|
|
183
268
|
reason: string | null
|
|
184
269
|
}
|
|
185
270
|
|
|
186
|
-
export
|
|
187
|
-
|
|
188
|
-
// ── Fiscal calendar types ──────────────────────────────────────────────
|
|
189
|
-
|
|
190
|
-
export interface FiscalPeriodSummary {
|
|
271
|
+
export interface ScheduleCreated {
|
|
272
|
+
structureId: string
|
|
191
273
|
name: string
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
closedAt: string | null
|
|
274
|
+
taxonomyId: string
|
|
275
|
+
totalPeriods: number
|
|
276
|
+
totalFacts: number
|
|
196
277
|
}
|
|
197
278
|
|
|
198
|
-
export interface
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
gapPeriods: number
|
|
204
|
-
catchUpSequence: string[]
|
|
205
|
-
closeableNow: boolean
|
|
206
|
-
blockers: string[]
|
|
207
|
-
lastCloseAt: string | null
|
|
208
|
-
initializedAt: string | null
|
|
209
|
-
lastSyncAt: string | null
|
|
210
|
-
periods: FiscalPeriodSummary[]
|
|
279
|
+
export interface TruncateScheduleResult {
|
|
280
|
+
structureId: string
|
|
281
|
+
newEndDate: string
|
|
282
|
+
factsDeleted: number
|
|
283
|
+
reason: string
|
|
211
284
|
}
|
|
212
285
|
|
|
286
|
+
export type LedgerEntryType = 'standard' | 'adjusting' | 'closing' | 'reversing'
|
|
287
|
+
|
|
288
|
+
// ── Caller-facing option interfaces ────────────────────────────────────
|
|
289
|
+
|
|
213
290
|
export interface InitializeLedgerOptions {
|
|
214
291
|
closedThrough?: string | null
|
|
215
292
|
fiscalYearStartMonth?: number
|
|
@@ -218,59 +295,11 @@ export interface InitializeLedgerOptions {
|
|
|
218
295
|
note?: string | null
|
|
219
296
|
}
|
|
220
297
|
|
|
221
|
-
export interface InitializeLedgerResult {
|
|
222
|
-
fiscalCalendar: FiscalCalendarState
|
|
223
|
-
periodsCreated: number
|
|
224
|
-
warnings: string[]
|
|
225
|
-
}
|
|
226
|
-
|
|
227
298
|
export interface ClosePeriodOptions {
|
|
228
299
|
note?: string | null
|
|
229
300
|
allowStaleSync?: boolean
|
|
230
301
|
}
|
|
231
302
|
|
|
232
|
-
export interface ClosePeriodResult {
|
|
233
|
-
period: string
|
|
234
|
-
entriesPosted: number
|
|
235
|
-
targetAutoAdvanced: boolean
|
|
236
|
-
fiscalCalendar: FiscalCalendarState
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
export interface DraftLineItemView {
|
|
240
|
-
lineItemId: string
|
|
241
|
-
elementId: string
|
|
242
|
-
elementCode: string | null
|
|
243
|
-
elementName: string
|
|
244
|
-
debitAmount: number
|
|
245
|
-
creditAmount: number
|
|
246
|
-
description: string | null
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
export interface DraftEntryView {
|
|
250
|
-
entryId: string
|
|
251
|
-
postingDate: string
|
|
252
|
-
type: string
|
|
253
|
-
memo: string | null
|
|
254
|
-
provenance: string | null
|
|
255
|
-
sourceStructureId: string | null
|
|
256
|
-
sourceStructureName: string | null
|
|
257
|
-
lineItems: DraftLineItemView[]
|
|
258
|
-
totalDebit: number
|
|
259
|
-
totalCredit: number
|
|
260
|
-
balanced: boolean
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
export interface PeriodDraftsView {
|
|
264
|
-
period: string
|
|
265
|
-
periodStart: string
|
|
266
|
-
periodEnd: string
|
|
267
|
-
draftCount: number
|
|
268
|
-
totalDebit: number
|
|
269
|
-
totalCredit: number
|
|
270
|
-
allBalanced: boolean
|
|
271
|
-
drafts: DraftEntryView[]
|
|
272
|
-
}
|
|
273
|
-
|
|
274
303
|
export interface ManualClosingLineItem {
|
|
275
304
|
elementId: string
|
|
276
305
|
debitAmount?: number
|
|
@@ -290,13 +319,6 @@ export interface TruncateScheduleOptions {
|
|
|
290
319
|
reason: string
|
|
291
320
|
}
|
|
292
321
|
|
|
293
|
-
export interface TruncateScheduleResult {
|
|
294
|
-
structureId: string
|
|
295
|
-
newEndDate: string
|
|
296
|
-
factsDeleted: number
|
|
297
|
-
reason: string
|
|
298
|
-
}
|
|
299
|
-
|
|
300
322
|
export interface CreateScheduleOptions {
|
|
301
323
|
name: string
|
|
302
324
|
elementIds: string[]
|
|
@@ -321,230 +343,259 @@ export interface CreateScheduleOptions {
|
|
|
321
343
|
|
|
322
344
|
// ── Client ──────────────────────────────────────────────────────────────
|
|
323
345
|
|
|
346
|
+
interface LedgerClientConfig {
|
|
347
|
+
baseUrl: string
|
|
348
|
+
credentials?: 'include' | 'same-origin' | 'omit'
|
|
349
|
+
headers?: Record<string, string>
|
|
350
|
+
token?: string
|
|
351
|
+
}
|
|
352
|
+
|
|
324
353
|
export class LedgerClient {
|
|
325
|
-
private config:
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
354
|
+
private config: LedgerClientConfig
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Per-graph GraphQL client cache. The first call for a given graph
|
|
358
|
+
* creates a `GraphQLClient` bound to `/extensions/{graph_id}/graphql`;
|
|
359
|
+
* subsequent calls reuse it.
|
|
360
|
+
*/
|
|
361
|
+
private gql: GraphQLClientCache
|
|
331
362
|
|
|
332
|
-
constructor(config: {
|
|
333
|
-
baseUrl: string
|
|
334
|
-
credentials?: 'include' | 'same-origin' | 'omit'
|
|
335
|
-
headers?: Record<string, string>
|
|
336
|
-
token?: string
|
|
337
|
-
}) {
|
|
363
|
+
constructor(config: LedgerClientConfig) {
|
|
338
364
|
this.config = config
|
|
365
|
+
this.gql = new GraphQLClientCache(config)
|
|
339
366
|
}
|
|
340
367
|
|
|
341
368
|
// ── Entity ──────────────────────────────────────────────────────────
|
|
342
369
|
|
|
343
370
|
/**
|
|
344
371
|
* Get the entity (company/organization) for this graph.
|
|
372
|
+
* Returns null when the ledger has no entity yet.
|
|
345
373
|
*/
|
|
346
374
|
async getEntity(graphId: string): Promise<LedgerEntity | null> {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
const data = response.data as Record<string, unknown>
|
|
357
|
-
return {
|
|
358
|
-
id: data.id as string,
|
|
359
|
-
name: data.name as string,
|
|
360
|
-
legalName: (data.legal_name as string) ?? null,
|
|
361
|
-
entityType: (data.entity_type as string) ?? null,
|
|
362
|
-
industry: (data.industry as string) ?? null,
|
|
363
|
-
status: (data.status as string) ?? null,
|
|
364
|
-
}
|
|
375
|
+
return this.gqlQuery(
|
|
376
|
+
graphId,
|
|
377
|
+
GetLedgerEntityDocument,
|
|
378
|
+
undefined,
|
|
379
|
+
'Get entity',
|
|
380
|
+
(data) => data.entity
|
|
381
|
+
)
|
|
365
382
|
}
|
|
366
383
|
|
|
367
|
-
|
|
384
|
+
/** List all entities for this graph, optionally filtered by source system. */
|
|
385
|
+
async listEntities(
|
|
386
|
+
graphId: string,
|
|
387
|
+
options?: { source?: string }
|
|
388
|
+
): Promise<LedgerEntitySummary[]> {
|
|
389
|
+
return this.gqlQuery(
|
|
390
|
+
graphId,
|
|
391
|
+
ListLedgerEntitiesDocument,
|
|
392
|
+
{ source: options?.source ?? null },
|
|
393
|
+
'List entities',
|
|
394
|
+
(data) => data.entities
|
|
395
|
+
)
|
|
396
|
+
}
|
|
368
397
|
|
|
369
398
|
/**
|
|
370
|
-
*
|
|
399
|
+
* Update the entity for this graph. Only non-null fields are applied.
|
|
400
|
+
* Returns the updated entity.
|
|
371
401
|
*/
|
|
372
|
-
async
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
402
|
+
async updateEntity(graphId: string, updates: UpdateEntityRequest): Promise<LedgerEntity> {
|
|
403
|
+
const envelope = await this.callOperation(
|
|
404
|
+
'Update entity',
|
|
405
|
+
opUpdateEntity({
|
|
406
|
+
path: { graph_id: graphId },
|
|
407
|
+
body: updates,
|
|
408
|
+
})
|
|
409
|
+
)
|
|
410
|
+
return envelope.result as unknown as LedgerEntity
|
|
411
|
+
}
|
|
376
412
|
|
|
377
|
-
|
|
378
|
-
throw new Error(`List accounts failed: ${JSON.stringify(response.error)}`)
|
|
379
|
-
}
|
|
413
|
+
// ── Summary ────────────────────────────────────────────────────────
|
|
380
414
|
|
|
381
|
-
|
|
415
|
+
/** Ledger rollup counts + QB sync metadata. */
|
|
416
|
+
async getSummary(graphId: string): Promise<LedgerSummary | null> {
|
|
417
|
+
return this.gqlQuery(
|
|
418
|
+
graphId,
|
|
419
|
+
GetLedgerSummaryDocument,
|
|
420
|
+
undefined,
|
|
421
|
+
'Get summary',
|
|
422
|
+
(data) => data.summary
|
|
423
|
+
)
|
|
382
424
|
}
|
|
383
425
|
|
|
384
|
-
|
|
385
|
-
* Get the account tree (hierarchical).
|
|
386
|
-
*/
|
|
387
|
-
async getAccountTree(graphId: string): Promise<AccountTreeResponse> {
|
|
388
|
-
const response = await getLedgerAccountTree({
|
|
389
|
-
path: { graph_id: graphId },
|
|
390
|
-
})
|
|
426
|
+
// ── Accounts (Chart of Accounts) ───────────────────────────────────
|
|
391
427
|
|
|
392
|
-
|
|
393
|
-
|
|
428
|
+
/** List CoA accounts with optional filters and pagination. */
|
|
429
|
+
async listAccounts(
|
|
430
|
+
graphId: string,
|
|
431
|
+
options?: {
|
|
432
|
+
classification?: string
|
|
433
|
+
isActive?: boolean
|
|
434
|
+
limit?: number
|
|
435
|
+
offset?: number
|
|
394
436
|
}
|
|
395
|
-
|
|
396
|
-
return
|
|
437
|
+
): Promise<LedgerAccountList | null> {
|
|
438
|
+
return this.gqlQuery(
|
|
439
|
+
graphId,
|
|
440
|
+
ListLedgerAccountsDocument,
|
|
441
|
+
{
|
|
442
|
+
classification: options?.classification ?? null,
|
|
443
|
+
isActive: options?.isActive ?? null,
|
|
444
|
+
limit: options?.limit ?? 100,
|
|
445
|
+
offset: options?.offset ?? 0,
|
|
446
|
+
},
|
|
447
|
+
'List accounts',
|
|
448
|
+
(data) => data.accounts
|
|
449
|
+
)
|
|
397
450
|
}
|
|
398
451
|
|
|
399
|
-
|
|
452
|
+
/** Hierarchical Chart of Accounts (up to 4 levels deep). */
|
|
453
|
+
async getAccountTree(graphId: string): Promise<LedgerAccountTree | null> {
|
|
454
|
+
return this.gqlQuery(
|
|
455
|
+
graphId,
|
|
456
|
+
GetLedgerAccountTreeDocument,
|
|
457
|
+
undefined,
|
|
458
|
+
'Get account tree',
|
|
459
|
+
(data) => data.accountTree
|
|
460
|
+
)
|
|
461
|
+
}
|
|
400
462
|
|
|
401
|
-
/**
|
|
402
|
-
|
|
403
|
-
*/
|
|
404
|
-
async listTransactions(
|
|
463
|
+
/** Accounts rolled up to reporting concepts via a mapping structure. */
|
|
464
|
+
async getAccountRollups(
|
|
405
465
|
graphId: string,
|
|
406
|
-
options?: {
|
|
407
|
-
): Promise<
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
466
|
+
options?: { mappingId?: string; startDate?: string; endDate?: string }
|
|
467
|
+
): Promise<LedgerAccountRollups | null> {
|
|
468
|
+
return this.gqlQuery(
|
|
469
|
+
graphId,
|
|
470
|
+
GetLedgerAccountRollupsDocument,
|
|
471
|
+
{
|
|
472
|
+
mappingId: options?.mappingId ?? null,
|
|
473
|
+
startDate: options?.startDate ?? null,
|
|
474
|
+
endDate: options?.endDate ?? null,
|
|
415
475
|
},
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
throw new Error(`List transactions failed: ${JSON.stringify(response.error)}`)
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
return response.data as LedgerTransactionListResponse
|
|
476
|
+
'Get account rollups',
|
|
477
|
+
(data) => data.accountRollups
|
|
478
|
+
)
|
|
423
479
|
}
|
|
424
480
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
async
|
|
481
|
+
// ── Transactions ────────────────────────────────────────────────────
|
|
482
|
+
|
|
483
|
+
/** List transactions with optional type + date filters and pagination. */
|
|
484
|
+
async listTransactions(
|
|
429
485
|
graphId: string,
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
if (response.error) {
|
|
437
|
-
throw new Error(`Get transaction failed: ${JSON.stringify(response.error)}`)
|
|
486
|
+
options?: {
|
|
487
|
+
type?: string
|
|
488
|
+
startDate?: string
|
|
489
|
+
endDate?: string
|
|
490
|
+
limit?: number
|
|
491
|
+
offset?: number
|
|
438
492
|
}
|
|
493
|
+
): Promise<LedgerTransactionList | null> {
|
|
494
|
+
return this.gqlQuery(
|
|
495
|
+
graphId,
|
|
496
|
+
ListLedgerTransactionsDocument,
|
|
497
|
+
{
|
|
498
|
+
type: options?.type ?? null,
|
|
499
|
+
startDate: options?.startDate ?? null,
|
|
500
|
+
endDate: options?.endDate ?? null,
|
|
501
|
+
limit: options?.limit ?? 100,
|
|
502
|
+
offset: options?.offset ?? 0,
|
|
503
|
+
},
|
|
504
|
+
'List transactions',
|
|
505
|
+
(data) => data.transactions
|
|
506
|
+
)
|
|
507
|
+
}
|
|
439
508
|
|
|
440
|
-
|
|
509
|
+
/** Get transaction detail with entries + line items. */
|
|
510
|
+
async getTransaction(graphId: string, transactionId: string): Promise<LedgerTransaction | null> {
|
|
511
|
+
return this.gqlQuery(
|
|
512
|
+
graphId,
|
|
513
|
+
GetLedgerTransactionDocument,
|
|
514
|
+
{ transactionId },
|
|
515
|
+
'Get transaction',
|
|
516
|
+
(data) => data.transaction
|
|
517
|
+
)
|
|
441
518
|
}
|
|
442
519
|
|
|
443
520
|
// ── Trial Balance ──────────────────────────────────────────────────
|
|
444
521
|
|
|
445
|
-
/**
|
|
446
|
-
* Get trial balance (CoA-level debits/credits).
|
|
447
|
-
*/
|
|
522
|
+
/** Trial balance by raw CoA account. */
|
|
448
523
|
async getTrialBalance(
|
|
449
524
|
graphId: string,
|
|
450
525
|
options?: { startDate?: string; endDate?: string }
|
|
451
|
-
): Promise<
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
526
|
+
): Promise<LedgerTrialBalance | null> {
|
|
527
|
+
return this.gqlQuery(
|
|
528
|
+
graphId,
|
|
529
|
+
GetLedgerTrialBalanceDocument,
|
|
530
|
+
{
|
|
531
|
+
startDate: options?.startDate ?? null,
|
|
532
|
+
endDate: options?.endDate ?? null,
|
|
457
533
|
},
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
throw new Error(`Get trial balance failed: ${JSON.stringify(response.error)}`)
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
return response.data as TrialBalanceResponse
|
|
534
|
+
'Get trial balance',
|
|
535
|
+
(data) => data.trialBalance
|
|
536
|
+
)
|
|
465
537
|
}
|
|
466
538
|
|
|
467
|
-
/**
|
|
468
|
-
* Get mapped trial balance (CoA rolled up to GAAP concepts).
|
|
469
|
-
*/
|
|
539
|
+
/** Trial balance rolled up to GAAP reporting concepts via a mapping. */
|
|
470
540
|
async getMappedTrialBalance(
|
|
471
541
|
graphId: string,
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
542
|
+
mappingId: string,
|
|
543
|
+
options?: { startDate?: string; endDate?: string }
|
|
544
|
+
): Promise<LedgerMappedTrialBalance | null> {
|
|
545
|
+
return this.gqlQuery(
|
|
546
|
+
graphId,
|
|
547
|
+
GetLedgerMappedTrialBalanceDocument,
|
|
548
|
+
{
|
|
549
|
+
mappingId,
|
|
550
|
+
startDate: options?.startDate ?? null,
|
|
551
|
+
endDate: options?.endDate ?? null,
|
|
480
552
|
},
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
throw new Error(`Get mapped trial balance failed: ${JSON.stringify(response.error)}`)
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
return response.data
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
// ── Summary ────────────────────────────────────────────────────────
|
|
491
|
-
|
|
492
|
-
/**
|
|
493
|
-
* Get ledger summary (account count, transaction count, date range).
|
|
494
|
-
*/
|
|
495
|
-
async getSummary(graphId: string): Promise<LedgerSummaryResponse> {
|
|
496
|
-
const response = await getLedgerSummary({
|
|
497
|
-
path: { graph_id: graphId },
|
|
498
|
-
})
|
|
499
|
-
|
|
500
|
-
if (response.error) {
|
|
501
|
-
throw new Error(`Get summary failed: ${JSON.stringify(response.error)}`)
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
return response.data as LedgerSummaryResponse
|
|
553
|
+
'Get mapped trial balance',
|
|
554
|
+
(data) => data.mappedTrialBalance
|
|
555
|
+
)
|
|
505
556
|
}
|
|
506
557
|
|
|
507
558
|
// ── Taxonomy ────────────────────────────────────────────────────────
|
|
508
559
|
|
|
509
|
-
/**
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
throw new Error(`Get reporting taxonomy failed: ${JSON.stringify(response.error)}`)
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
return response.data
|
|
560
|
+
/** Get the locked US GAAP reporting taxonomy for this graph. */
|
|
561
|
+
async getReportingTaxonomy(graphId: string): Promise<LedgerReportingTaxonomy | null> {
|
|
562
|
+
return this.gqlQuery(
|
|
563
|
+
graphId,
|
|
564
|
+
GetLedgerReportingTaxonomyDocument,
|
|
565
|
+
undefined,
|
|
566
|
+
'Get reporting taxonomy',
|
|
567
|
+
(data) => data.reportingTaxonomy
|
|
568
|
+
)
|
|
522
569
|
}
|
|
523
570
|
|
|
524
|
-
/**
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
571
|
+
/** List active taxonomies with optional type filter. */
|
|
572
|
+
async listTaxonomies(
|
|
573
|
+
graphId: string,
|
|
574
|
+
options?: { taxonomyType?: string }
|
|
575
|
+
): Promise<LedgerTaxonomy[]> {
|
|
576
|
+
const list = await this.gqlQuery(
|
|
577
|
+
graphId,
|
|
578
|
+
ListLedgerTaxonomiesDocument,
|
|
579
|
+
{ taxonomyType: options?.taxonomyType ?? null },
|
|
580
|
+
'List taxonomies',
|
|
581
|
+
(data) => data.taxonomies
|
|
582
|
+
)
|
|
583
|
+
return list?.taxonomies ?? []
|
|
584
|
+
}
|
|
536
585
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
586
|
+
/** Create a new taxonomy (used for CoA + mapping taxonomies). */
|
|
587
|
+
async createTaxonomy(
|
|
588
|
+
graphId: string,
|
|
589
|
+
body: CreateTaxonomyRequest
|
|
590
|
+
): Promise<Record<string, unknown>> {
|
|
591
|
+
const envelope = await this.callOperation(
|
|
592
|
+
'Create taxonomy',
|
|
593
|
+
opCreateTaxonomy({ path: { graph_id: graphId }, body })
|
|
594
|
+
)
|
|
595
|
+
return (envelope.result ?? {}) as Record<string, unknown>
|
|
543
596
|
}
|
|
544
597
|
|
|
545
|
-
/**
|
|
546
|
-
* List elements (CoA accounts, GAAP concepts, etc.).
|
|
547
|
-
*/
|
|
598
|
+
/** List elements (CoA accounts, GAAP concepts, etc.) with filters. */
|
|
548
599
|
async listElements(
|
|
549
600
|
graphId: string,
|
|
550
601
|
options?: {
|
|
@@ -555,184 +606,183 @@ export class LedgerClient {
|
|
|
555
606
|
limit?: number
|
|
556
607
|
offset?: number
|
|
557
608
|
}
|
|
558
|
-
): Promise<
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
609
|
+
): Promise<LedgerElementList | null> {
|
|
610
|
+
return this.gqlQuery(
|
|
611
|
+
graphId,
|
|
612
|
+
ListLedgerElementsDocument,
|
|
613
|
+
{
|
|
614
|
+
taxonomyId: options?.taxonomyId ?? null,
|
|
615
|
+
source: options?.source ?? null,
|
|
616
|
+
classification: options?.classification ?? null,
|
|
617
|
+
isAbstract: options?.isAbstract ?? null,
|
|
618
|
+
limit: options?.limit ?? 100,
|
|
619
|
+
offset: options?.offset ?? 0,
|
|
568
620
|
},
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
}
|
|
621
|
+
'List elements',
|
|
622
|
+
(data) => data.elements
|
|
623
|
+
)
|
|
624
|
+
}
|
|
574
625
|
|
|
575
|
-
|
|
626
|
+
/** CoA elements not yet mapped to a reporting concept. */
|
|
627
|
+
async listUnmappedElements(
|
|
628
|
+
graphId: string,
|
|
629
|
+
options?: { mappingId?: string }
|
|
630
|
+
): Promise<LedgerUnmappedElement[]> {
|
|
631
|
+
return this.gqlQuery(
|
|
632
|
+
graphId,
|
|
633
|
+
ListLedgerUnmappedElementsDocument,
|
|
634
|
+
{ mappingId: options?.mappingId ?? null },
|
|
635
|
+
'List unmapped elements',
|
|
636
|
+
(data) => data.unmappedElements
|
|
637
|
+
)
|
|
576
638
|
}
|
|
577
639
|
|
|
578
|
-
// ──
|
|
640
|
+
// ── Structures ──────────────────────────────────────────────────────
|
|
579
641
|
|
|
580
|
-
/**
|
|
581
|
-
|
|
582
|
-
* Returns the created mapping info.
|
|
583
|
-
*/
|
|
584
|
-
async createMappingStructure(
|
|
642
|
+
/** List reporting structures (IS, BS, CF, schedules) with optional filters. */
|
|
643
|
+
async listStructures(
|
|
585
644
|
graphId: string,
|
|
586
|
-
options?: {
|
|
587
|
-
): Promise<
|
|
588
|
-
const
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
taxonomy_id: options?.taxonomyId ?? 'tax_usgaap_reporting',
|
|
645
|
+
options?: { taxonomyId?: string; structureType?: string }
|
|
646
|
+
): Promise<LedgerStructure[]> {
|
|
647
|
+
const list = await this.gqlQuery(
|
|
648
|
+
graphId,
|
|
649
|
+
ListLedgerStructuresDocument,
|
|
650
|
+
{
|
|
651
|
+
taxonomyId: options?.taxonomyId ?? null,
|
|
652
|
+
structureType: options?.structureType ?? null,
|
|
595
653
|
},
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
const data = response.data as Record<string, unknown>
|
|
603
|
-
return {
|
|
604
|
-
id: data.id as string,
|
|
605
|
-
name: data.name as string,
|
|
606
|
-
description: (data.description as string) ?? null,
|
|
607
|
-
structureType: data.structure_type as string,
|
|
608
|
-
taxonomyId: data.taxonomy_id as string,
|
|
609
|
-
isActive: (data.is_active as boolean) ?? true,
|
|
610
|
-
}
|
|
654
|
+
'List structures',
|
|
655
|
+
(data) => data.structures
|
|
656
|
+
)
|
|
657
|
+
return list?.structures ?? []
|
|
611
658
|
}
|
|
612
659
|
|
|
613
660
|
/**
|
|
614
|
-
*
|
|
661
|
+
* Create a new structure. Most common use is a CoA→reporting mapping
|
|
662
|
+
* structure; also used for custom statement + schedule structures.
|
|
615
663
|
*/
|
|
616
|
-
async
|
|
617
|
-
const
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
throw new Error(`List mappings failed: ${JSON.stringify(response.error)}`)
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
const data = response.data as { structures?: Array<Record<string, unknown>> }
|
|
626
|
-
return (data.structures ?? []).map((s) => ({
|
|
627
|
-
id: s.id as string,
|
|
628
|
-
name: s.name as string,
|
|
629
|
-
description: (s.description as string) ?? null,
|
|
630
|
-
structureType: s.structure_type as string,
|
|
631
|
-
taxonomyId: s.taxonomy_id as string,
|
|
632
|
-
isActive: (s.is_active as boolean) ?? true,
|
|
633
|
-
}))
|
|
664
|
+
async createStructure(graphId: string, body: CreateStructureRequest): Promise<LedgerMappingInfo> {
|
|
665
|
+
const envelope = await this.callOperation(
|
|
666
|
+
'Create structure',
|
|
667
|
+
opCreateStructure({ path: { graph_id: graphId }, body })
|
|
668
|
+
)
|
|
669
|
+
return envelope.result as unknown as LedgerMappingInfo
|
|
634
670
|
}
|
|
635
671
|
|
|
636
|
-
|
|
637
|
-
* Get mapping detail — all associations with element names.
|
|
638
|
-
*/
|
|
639
|
-
async getMappingDetail(graphId: string, mappingId: string): Promise<MappingDetailResponse> {
|
|
640
|
-
const response = await getMappingDetail({
|
|
641
|
-
path: { graph_id: graphId, mapping_id: mappingId },
|
|
642
|
-
})
|
|
643
|
-
|
|
644
|
-
if (response.error) {
|
|
645
|
-
throw new Error(`Get mapping detail failed: ${JSON.stringify(response.error)}`)
|
|
646
|
-
}
|
|
672
|
+
// ── Mappings ────────────────────────────────────────────────────────
|
|
647
673
|
|
|
648
|
-
|
|
674
|
+
/** List active CoA→reporting mapping structures. */
|
|
675
|
+
async listMappings(graphId: string): Promise<LedgerMappingInfo[]> {
|
|
676
|
+
const list = await this.gqlQuery(
|
|
677
|
+
graphId,
|
|
678
|
+
ListLedgerMappingsDocument,
|
|
679
|
+
undefined,
|
|
680
|
+
'List mappings',
|
|
681
|
+
(data) => data.mappings
|
|
682
|
+
)
|
|
683
|
+
return list?.structures ?? []
|
|
649
684
|
}
|
|
650
685
|
|
|
651
|
-
/**
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
throw new Error(`Get mapping coverage failed: ${JSON.stringify(response.error)}`)
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
const data = response.data as MappingCoverageResponse
|
|
664
|
-
return {
|
|
665
|
-
totalCoaElements: data.total_coa_elements ?? 0,
|
|
666
|
-
mappedCount: data.mapped_count ?? 0,
|
|
667
|
-
unmappedCount: data.unmapped_count ?? 0,
|
|
668
|
-
coveragePercent: data.coverage_percent ?? 0,
|
|
669
|
-
highConfidence: data.high_confidence ?? 0,
|
|
670
|
-
mediumConfidence: data.medium_confidence ?? 0,
|
|
671
|
-
lowConfidence: data.low_confidence ?? 0,
|
|
672
|
-
}
|
|
686
|
+
/** Get a mapping structure with all its associations. */
|
|
687
|
+
async getMapping(graphId: string, mappingId: string): Promise<LedgerMapping | null> {
|
|
688
|
+
return this.gqlQuery(
|
|
689
|
+
graphId,
|
|
690
|
+
GetLedgerMappingDocument,
|
|
691
|
+
{ mappingId },
|
|
692
|
+
'Get mapping',
|
|
693
|
+
(data) => data.mapping
|
|
694
|
+
)
|
|
673
695
|
}
|
|
674
696
|
|
|
675
|
-
/**
|
|
676
|
-
|
|
677
|
-
*/
|
|
678
|
-
async createMapping(
|
|
697
|
+
/** Mapping coverage stats — how many CoA elements are mapped. */
|
|
698
|
+
async getMappingCoverage(
|
|
679
699
|
graphId: string,
|
|
680
|
-
mappingId: string
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
to_element_id: toElementId,
|
|
690
|
-
confidence: confidence ?? 1.0,
|
|
691
|
-
},
|
|
692
|
-
})
|
|
693
|
-
|
|
694
|
-
if (response.error) {
|
|
695
|
-
throw new Error(`Create mapping failed: ${JSON.stringify(response.error)}`)
|
|
696
|
-
}
|
|
700
|
+
mappingId: string
|
|
701
|
+
): Promise<LedgerMappingCoverage | null> {
|
|
702
|
+
return this.gqlQuery(
|
|
703
|
+
graphId,
|
|
704
|
+
GetLedgerMappingCoverageDocument,
|
|
705
|
+
{ mappingId },
|
|
706
|
+
'Get mapping coverage',
|
|
707
|
+
(data) => data.mappingCoverage
|
|
708
|
+
)
|
|
697
709
|
}
|
|
698
710
|
|
|
699
|
-
/**
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
711
|
+
/** Create a manual mapping association between two elements. */
|
|
712
|
+
async createMappingAssociation(
|
|
713
|
+
graphId: string,
|
|
714
|
+
body: CreateMappingAssociationOperation
|
|
715
|
+
): Promise<Record<string, unknown>> {
|
|
716
|
+
const envelope = await this.callOperation(
|
|
717
|
+
'Create mapping association',
|
|
718
|
+
opCreateMappingAssociation({ path: { graph_id: graphId }, body })
|
|
719
|
+
)
|
|
720
|
+
return (envelope.result ?? {}) as Record<string, unknown>
|
|
721
|
+
}
|
|
706
722
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
723
|
+
/** Delete a mapping association. */
|
|
724
|
+
async deleteMappingAssociation(
|
|
725
|
+
graphId: string,
|
|
726
|
+
body: DeleteMappingAssociationOperation
|
|
727
|
+
): Promise<{ deleted: boolean }> {
|
|
728
|
+
const envelope = await this.callOperation(
|
|
729
|
+
'Delete mapping association',
|
|
730
|
+
opDeleteMappingAssociation({ path: { graph_id: graphId }, body })
|
|
731
|
+
)
|
|
732
|
+
return (envelope.result ?? { deleted: true }) as { deleted: boolean }
|
|
710
733
|
}
|
|
711
734
|
|
|
712
735
|
/**
|
|
713
|
-
* Trigger AI
|
|
714
|
-
*
|
|
736
|
+
* Trigger the AI MappingAgent. Returns the operation id — async; the
|
|
737
|
+
* agent runs in the background. Consumers can subscribe to progress
|
|
738
|
+
* via `/v1/operations/{operationId}/stream`.
|
|
715
739
|
*/
|
|
716
|
-
async
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
740
|
+
async autoMapElements(
|
|
741
|
+
graphId: string,
|
|
742
|
+
body: AutoMapElementsOperation
|
|
743
|
+
): Promise<{ operationId: string; status: OperationEnvelope['status'] }> {
|
|
744
|
+
const envelope = await this.callOperation(
|
|
745
|
+
'Auto-map elements',
|
|
746
|
+
opAutoMapElements({ path: { graph_id: graphId }, body })
|
|
747
|
+
)
|
|
748
|
+
return { operationId: envelope.operationId, status: envelope.status }
|
|
749
|
+
}
|
|
720
750
|
|
|
721
|
-
|
|
722
|
-
throw new Error(`Auto-map failed: ${JSON.stringify(response.error)}`)
|
|
723
|
-
}
|
|
751
|
+
// ── Schedules ──────────────────────────────────────────────────────
|
|
724
752
|
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
753
|
+
/** List all schedule structures with metadata. */
|
|
754
|
+
async listSchedules(graphId: string): Promise<LedgerSchedule[]> {
|
|
755
|
+
const list = await this.gqlQuery(
|
|
756
|
+
graphId,
|
|
757
|
+
ListLedgerSchedulesDocument,
|
|
758
|
+
undefined,
|
|
759
|
+
'List schedules',
|
|
760
|
+
(data) => data.schedules
|
|
761
|
+
)
|
|
762
|
+
return list?.schedules ?? []
|
|
729
763
|
}
|
|
730
764
|
|
|
731
|
-
|
|
765
|
+
/** Schedule facts optionally filtered by period window. */
|
|
766
|
+
async getScheduleFacts(
|
|
767
|
+
graphId: string,
|
|
768
|
+
structureId: string,
|
|
769
|
+
options?: { periodStart?: string; periodEnd?: string }
|
|
770
|
+
): Promise<LedgerScheduleFact[]> {
|
|
771
|
+
const facts = await this.gqlQuery(
|
|
772
|
+
graphId,
|
|
773
|
+
GetLedgerScheduleFactsDocument,
|
|
774
|
+
{
|
|
775
|
+
structureId,
|
|
776
|
+
periodStart: options?.periodStart ?? null,
|
|
777
|
+
periodEnd: options?.periodEnd ?? null,
|
|
778
|
+
},
|
|
779
|
+
'Get schedule facts',
|
|
780
|
+
(data) => data.scheduleFacts
|
|
781
|
+
)
|
|
782
|
+
return facts?.facts ?? []
|
|
783
|
+
}
|
|
732
784
|
|
|
733
|
-
/**
|
|
734
|
-
* Create a schedule with pre-generated monthly facts.
|
|
735
|
-
*/
|
|
785
|
+
/** Create a new schedule with pre-generated monthly facts. */
|
|
736
786
|
async createSchedule(graphId: string, options: CreateScheduleOptions): Promise<ScheduleCreated> {
|
|
737
787
|
const body: CreateScheduleRequest = {
|
|
738
788
|
name: options.name,
|
|
@@ -757,124 +807,75 @@ export class LedgerClient {
|
|
|
757
807
|
}
|
|
758
808
|
: undefined,
|
|
759
809
|
}
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
path: { graph_id: graphId },
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
if (response.error) {
|
|
767
|
-
throw new Error(`Create schedule failed: ${JSON.stringify(response.error)}`)
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
const data = response.data as ScheduleCreatedResponse
|
|
810
|
+
const envelope = await this.callOperation(
|
|
811
|
+
'Create schedule',
|
|
812
|
+
opCreateSchedule({ path: { graph_id: graphId }, body })
|
|
813
|
+
)
|
|
814
|
+
const raw = envelope.result as unknown as RawScheduleCreatedResult
|
|
771
815
|
return {
|
|
772
|
-
structureId:
|
|
773
|
-
name:
|
|
774
|
-
taxonomyId:
|
|
775
|
-
totalPeriods:
|
|
776
|
-
totalFacts:
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
/**
|
|
781
|
-
* List all schedules for a graph.
|
|
782
|
-
*/
|
|
783
|
-
async listSchedules(graphId: string): Promise<Schedule[]> {
|
|
784
|
-
const response = await listSchedules({
|
|
785
|
-
path: { graph_id: graphId },
|
|
786
|
-
})
|
|
787
|
-
|
|
788
|
-
if (response.error) {
|
|
789
|
-
throw new Error(`List schedules failed: ${JSON.stringify(response.error)}`)
|
|
816
|
+
structureId: raw.structure_id,
|
|
817
|
+
name: raw.name,
|
|
818
|
+
taxonomyId: raw.taxonomy_id,
|
|
819
|
+
totalPeriods: raw.total_periods,
|
|
820
|
+
totalFacts: raw.total_facts,
|
|
790
821
|
}
|
|
791
|
-
|
|
792
|
-
const data = response.data as ScheduleListResponse
|
|
793
|
-
return (data.schedules ?? []).map((s: ScheduleSummaryResponse) => ({
|
|
794
|
-
structureId: s.structure_id,
|
|
795
|
-
name: s.name,
|
|
796
|
-
taxonomyName: s.taxonomy_name,
|
|
797
|
-
entryTemplate: s.entry_template ?? null,
|
|
798
|
-
scheduleMetadata: s.schedule_metadata ?? null,
|
|
799
|
-
totalPeriods: s.total_periods,
|
|
800
|
-
periodsWithEntries: s.periods_with_entries,
|
|
801
|
-
}))
|
|
802
822
|
}
|
|
803
823
|
|
|
804
|
-
/**
|
|
805
|
-
|
|
806
|
-
*/
|
|
807
|
-
async getScheduleFacts(
|
|
824
|
+
/** Truncate a schedule — end it early at `newEndDate`. */
|
|
825
|
+
async truncateSchedule(
|
|
808
826
|
graphId: string,
|
|
809
827
|
structureId: string,
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
828
|
+
options: TruncateScheduleOptions
|
|
829
|
+
): Promise<TruncateScheduleResult> {
|
|
830
|
+
const body: TruncateScheduleOperation = {
|
|
831
|
+
structure_id: structureId,
|
|
832
|
+
new_end_date: options.newEndDate,
|
|
833
|
+
reason: options.reason,
|
|
834
|
+
}
|
|
835
|
+
const envelope = await this.callOperation(
|
|
836
|
+
'Truncate schedule',
|
|
837
|
+
opTruncateSchedule({ path: { graph_id: graphId }, body })
|
|
838
|
+
)
|
|
839
|
+
const raw = envelope.result as unknown as RawTruncateScheduleResult
|
|
840
|
+
return {
|
|
841
|
+
structureId: raw.structure_id,
|
|
842
|
+
newEndDate: raw.new_end_date,
|
|
843
|
+
factsDeleted: raw.facts_deleted,
|
|
844
|
+
reason: raw.reason,
|
|
823
845
|
}
|
|
824
|
-
|
|
825
|
-
const data = response.data as ScheduleFactsResponse
|
|
826
|
-
return (data.facts ?? []).map((f: ScheduleFactResponse) => ({
|
|
827
|
-
elementId: f.element_id,
|
|
828
|
-
elementName: f.element_name,
|
|
829
|
-
value: f.value,
|
|
830
|
-
periodStart: f.period_start,
|
|
831
|
-
periodEnd: f.period_end,
|
|
832
|
-
}))
|
|
833
846
|
}
|
|
834
847
|
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
848
|
+
// ── Period close ────────────────────────────────────────────────────
|
|
849
|
+
|
|
850
|
+
/** Close status for all schedules in a fiscal period. */
|
|
838
851
|
async getPeriodCloseStatus(
|
|
839
852
|
graphId: string,
|
|
840
853
|
periodStart: string,
|
|
841
854
|
periodEnd: string
|
|
842
|
-
): Promise<
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
855
|
+
): Promise<LedgerPeriodCloseStatus | null> {
|
|
856
|
+
return this.gqlQuery(
|
|
857
|
+
graphId,
|
|
858
|
+
GetLedgerPeriodCloseStatusDocument,
|
|
859
|
+
{ periodStart, periodEnd },
|
|
860
|
+
'Get period close status',
|
|
861
|
+
(data) => data.periodCloseStatus
|
|
862
|
+
)
|
|
863
|
+
}
|
|
851
864
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
status: s.status,
|
|
862
|
-
entryId: s.entry_id ?? null,
|
|
863
|
-
})),
|
|
864
|
-
totalDraft: data.total_draft,
|
|
865
|
-
totalPosted: data.total_posted,
|
|
866
|
-
}
|
|
865
|
+
/** All draft entries in a period, fully expanded for review pre-close. */
|
|
866
|
+
async listPeriodDrafts(graphId: string, period: string): Promise<LedgerPeriodDrafts | null> {
|
|
867
|
+
return this.gqlQuery(
|
|
868
|
+
graphId,
|
|
869
|
+
GetLedgerPeriodDraftsDocument,
|
|
870
|
+
{ period },
|
|
871
|
+
'List period drafts',
|
|
872
|
+
(data) => data.periodDrafts
|
|
873
|
+
)
|
|
867
874
|
}
|
|
868
875
|
|
|
869
876
|
/**
|
|
870
|
-
* Idempotently create (or refresh) a draft closing entry from a
|
|
871
|
-
*
|
|
872
|
-
*
|
|
873
|
-
* - `created` — new draft
|
|
874
|
-
* - `unchanged` — existing draft still matches the schedule; no-op
|
|
875
|
-
* - `regenerated` — existing draft was stale; replaced
|
|
876
|
-
* - `removed` — schedule no longer covers this period; stale draft deleted
|
|
877
|
-
* - `skipped` — no existing draft and no in-scope fact; nothing to do
|
|
877
|
+
* Idempotently create (or refresh) a draft closing entry from a
|
|
878
|
+
* schedule for a period. See `ClosingEntryOutcome` for semantics.
|
|
878
879
|
*/
|
|
879
880
|
async createClosingEntry(
|
|
880
881
|
graphId: string,
|
|
@@ -884,76 +885,73 @@ export class LedgerClient {
|
|
|
884
885
|
periodEnd: string,
|
|
885
886
|
memo?: string
|
|
886
887
|
): Promise<ClosingEntry> {
|
|
887
|
-
const body:
|
|
888
|
+
const body: CreateClosingEntryOperation = {
|
|
889
|
+
structure_id: structureId,
|
|
888
890
|
posting_date: postingDate,
|
|
889
891
|
period_start: periodStart,
|
|
890
892
|
period_end: periodEnd,
|
|
891
893
|
memo: memo ?? undefined,
|
|
892
894
|
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
path: { graph_id: graphId,
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
if (response.error) {
|
|
900
|
-
throw new Error(`Create closing entry failed: ${JSON.stringify(response.error)}`)
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
const data = response.data as ClosingEntryResponse
|
|
904
|
-
return toClosingEntry(data)
|
|
895
|
+
const envelope = await this.callOperation(
|
|
896
|
+
'Create closing entry',
|
|
897
|
+
opCreateClosingEntry({ path: { graph_id: graphId }, body })
|
|
898
|
+
)
|
|
899
|
+
return rawToClosingEntry(envelope.result as unknown as RawClosingEntryResult)
|
|
905
900
|
}
|
|
906
901
|
|
|
907
|
-
// ── Closing Book ─────────────────────────────────────────────────────
|
|
908
|
-
|
|
909
902
|
/**
|
|
910
|
-
*
|
|
911
|
-
*
|
|
912
|
-
* and period close grouped into categories.
|
|
903
|
+
* Create a manual balanced closing entry (not tied to a schedule).
|
|
904
|
+
* Used for disposals, adjustments, and one-off closing events.
|
|
913
905
|
*/
|
|
914
|
-
async
|
|
915
|
-
const response = await getClosingBookStructures({
|
|
916
|
-
path: { graph_id: graphId },
|
|
917
|
-
})
|
|
918
|
-
|
|
919
|
-
if (response.error) {
|
|
920
|
-
throw new Error(`Get closing book structures failed: ${JSON.stringify(response.error)}`)
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
return response.data as ClosingBookStructuresResponse
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
/**
|
|
927
|
-
* Get account rollups — CoA accounts grouped by reporting element with balances.
|
|
928
|
-
* Shows how company-specific accounts roll up to standardized reporting lines.
|
|
929
|
-
*/
|
|
930
|
-
async getAccountRollups(
|
|
906
|
+
async createManualClosingEntry(
|
|
931
907
|
graphId: string,
|
|
932
|
-
options
|
|
933
|
-
): Promise<
|
|
934
|
-
const
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
throw new Error(`Get account rollups failed: ${JSON.stringify(response.error)}`)
|
|
908
|
+
options: CreateManualClosingEntryOptions
|
|
909
|
+
): Promise<ClosingEntry> {
|
|
910
|
+
const body: CreateManualClosingEntryRequest = {
|
|
911
|
+
posting_date: options.postingDate,
|
|
912
|
+
memo: options.memo,
|
|
913
|
+
entry_type: options.entryType,
|
|
914
|
+
line_items: options.lineItems.map((li) => ({
|
|
915
|
+
element_id: li.elementId,
|
|
916
|
+
debit_amount: li.debitAmount ?? 0,
|
|
917
|
+
credit_amount: li.creditAmount ?? 0,
|
|
918
|
+
description: li.description ?? null,
|
|
919
|
+
})),
|
|
945
920
|
}
|
|
921
|
+
const envelope = await this.callOperation(
|
|
922
|
+
'Create manual closing entry',
|
|
923
|
+
opCreateManualClosingEntry({ path: { graph_id: graphId }, body })
|
|
924
|
+
)
|
|
925
|
+
return rawToClosingEntry(envelope.result as unknown as RawClosingEntryResult)
|
|
926
|
+
}
|
|
946
927
|
|
|
947
|
-
|
|
928
|
+
// ── Closing book ───────────────────────────────────────────────────
|
|
929
|
+
|
|
930
|
+
/** Grouped closing book structures for the close-screen sidebar. */
|
|
931
|
+
async getClosingBookStructures(graphId: string): Promise<LedgerClosingBookStructures | null> {
|
|
932
|
+
return this.gqlQuery(
|
|
933
|
+
graphId,
|
|
934
|
+
GetLedgerClosingBookStructuresDocument,
|
|
935
|
+
undefined,
|
|
936
|
+
'Get closing book structures',
|
|
937
|
+
(data) => data.closingBookStructures
|
|
938
|
+
)
|
|
948
939
|
}
|
|
949
940
|
|
|
950
|
-
// ── Fiscal Calendar
|
|
941
|
+
// ── Fiscal Calendar ────────────────────────────────────────────────
|
|
942
|
+
|
|
943
|
+
/** Current fiscal calendar state — pointers, gap, closeable status. */
|
|
944
|
+
async getFiscalCalendar(graphId: string): Promise<LedgerFiscalCalendar | null> {
|
|
945
|
+
return this.gqlQuery(
|
|
946
|
+
graphId,
|
|
947
|
+
GetLedgerFiscalCalendarDocument,
|
|
948
|
+
undefined,
|
|
949
|
+
'Get fiscal calendar',
|
|
950
|
+
(data) => data.fiscalCalendar
|
|
951
|
+
)
|
|
952
|
+
}
|
|
951
953
|
|
|
952
|
-
/**
|
|
953
|
-
* Initialize the fiscal calendar for a graph. Creates FiscalPeriod rows
|
|
954
|
-
* for the data window, sets `closed_through` / `close_target`, and emits
|
|
955
|
-
* an `initialized` audit event. Fails with 409 if already initialized.
|
|
956
|
-
*/
|
|
954
|
+
/** One-time ledger initialization — seed fiscal calendar + periods. */
|
|
957
955
|
async initializeLedger(
|
|
958
956
|
graphId: string,
|
|
959
957
|
options?: InitializeLedgerOptions
|
|
@@ -965,255 +963,131 @@ export class LedgerClient {
|
|
|
965
963
|
auto_seed_schedules: options?.autoSeedSchedules,
|
|
966
964
|
note: options?.note ?? null,
|
|
967
965
|
}
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
path: { graph_id: graphId },
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
if (response.error) {
|
|
975
|
-
throw new Error(`Initialize ledger failed: ${JSON.stringify(response.error)}`)
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
const data = response.data as InitializeLedgerResponse
|
|
966
|
+
const envelope = await this.callOperation(
|
|
967
|
+
'Initialize ledger',
|
|
968
|
+
opInitializeLedger({ path: { graph_id: graphId }, body })
|
|
969
|
+
)
|
|
970
|
+
const raw = envelope.result as unknown as RawInitializeLedgerResult
|
|
979
971
|
return {
|
|
980
|
-
fiscalCalendar:
|
|
981
|
-
periodsCreated:
|
|
982
|
-
warnings:
|
|
972
|
+
fiscalCalendar: rawFiscalCalendarToCamel(raw.fiscal_calendar),
|
|
973
|
+
periodsCreated: raw.periods_created ?? 0,
|
|
974
|
+
warnings: raw.warnings ?? [],
|
|
983
975
|
}
|
|
984
976
|
}
|
|
985
977
|
|
|
986
|
-
/**
|
|
987
|
-
* Get the current fiscal calendar state — pointers, gap, closeable status.
|
|
988
|
-
*/
|
|
989
|
-
async getFiscalCalendar(graphId: string): Promise<FiscalCalendarState> {
|
|
990
|
-
const response = await getFiscalCalendar({
|
|
991
|
-
path: { graph_id: graphId },
|
|
992
|
-
})
|
|
993
|
-
|
|
994
|
-
if (response.error) {
|
|
995
|
-
throw new Error(`Get fiscal calendar failed: ${JSON.stringify(response.error)}`)
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
return toFiscalCalendarState(response.data as FiscalCalendarResponse)
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
/**
|
|
1002
|
-
* Set the close target for a graph. Validates that the target is not in
|
|
1003
|
-
* the future and not before `closed_through`.
|
|
1004
|
-
*/
|
|
978
|
+
/** Set the user-controlled close target (YYYY-MM). */
|
|
1005
979
|
async setCloseTarget(
|
|
1006
980
|
graphId: string,
|
|
1007
981
|
period: string,
|
|
1008
982
|
note?: string | null
|
|
1009
|
-
): Promise<
|
|
1010
|
-
const body:
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
path: { graph_id: graphId },
|
|
1017
|
-
body,
|
|
1018
|
-
})
|
|
1019
|
-
|
|
1020
|
-
if (response.error) {
|
|
1021
|
-
throw new Error(`Set close target failed: ${JSON.stringify(response.error)}`)
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
return toFiscalCalendarState(response.data as FiscalCalendarResponse)
|
|
983
|
+
): Promise<LedgerFiscalCalendar> {
|
|
984
|
+
const body: SetCloseTargetOperation = { period, note: note ?? null }
|
|
985
|
+
const envelope = await this.callOperation(
|
|
986
|
+
'Set close target',
|
|
987
|
+
opSetCloseTarget({ path: { graph_id: graphId }, body })
|
|
988
|
+
)
|
|
989
|
+
return rawFiscalCalendarToCamel(envelope.result as unknown as RawFiscalCalendar)
|
|
1025
990
|
}
|
|
1026
991
|
|
|
1027
|
-
/**
|
|
1028
|
-
* Close a fiscal period — the final commit action.
|
|
1029
|
-
*
|
|
1030
|
-
* Validates closeable gates, transitions all draft entries in the period
|
|
1031
|
-
* to `posted`, marks the FiscalPeriod closed, and advances `closed_through`
|
|
1032
|
-
* (auto-advancing `close_target` when reached).
|
|
1033
|
-
*/
|
|
992
|
+
/** Close a fiscal period — the final commit action. */
|
|
1034
993
|
async closePeriod(
|
|
1035
994
|
graphId: string,
|
|
1036
995
|
period: string,
|
|
1037
996
|
options?: ClosePeriodOptions
|
|
1038
997
|
): Promise<ClosePeriodResult> {
|
|
1039
|
-
const body:
|
|
998
|
+
const body: ClosePeriodOperation = {
|
|
999
|
+
period,
|
|
1040
1000
|
note: options?.note ?? null,
|
|
1041
1001
|
allow_stale_sync: options?.allowStaleSync,
|
|
1042
1002
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
path: { graph_id: graphId,
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
if (response.error) {
|
|
1050
|
-
throw new Error(`Close period failed: ${JSON.stringify(response.error)}`)
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
const data = response.data as ClosePeriodResponse
|
|
1003
|
+
const envelope = await this.callOperation(
|
|
1004
|
+
'Close period',
|
|
1005
|
+
opClosePeriod({ path: { graph_id: graphId }, body })
|
|
1006
|
+
)
|
|
1007
|
+
const raw = envelope.result as unknown as RawClosePeriodResult
|
|
1054
1008
|
return {
|
|
1055
|
-
period:
|
|
1056
|
-
entriesPosted:
|
|
1057
|
-
targetAutoAdvanced:
|
|
1058
|
-
fiscalCalendar:
|
|
1009
|
+
period: raw.period,
|
|
1010
|
+
entriesPosted: raw.entries_posted ?? 0,
|
|
1011
|
+
targetAutoAdvanced: raw.target_auto_advanced ?? false,
|
|
1012
|
+
fiscalCalendar: rawFiscalCalendarToCamel(raw.fiscal_calendar),
|
|
1059
1013
|
}
|
|
1060
1014
|
}
|
|
1061
1015
|
|
|
1062
|
-
/**
|
|
1063
|
-
* Reopen a closed fiscal period. Requires a non-empty `reason` for the
|
|
1064
|
-
* audit log. Posted entries stay posted; the period transitions to
|
|
1065
|
-
* `closing` so the user can post adjustments and re-close.
|
|
1066
|
-
*/
|
|
1016
|
+
/** Reopen a closed fiscal period. Requires a reason for the audit log. */
|
|
1067
1017
|
async reopenPeriod(
|
|
1068
1018
|
graphId: string,
|
|
1069
1019
|
period: string,
|
|
1070
1020
|
reason: string,
|
|
1071
1021
|
note?: string | null
|
|
1072
|
-
): Promise<
|
|
1073
|
-
const body:
|
|
1022
|
+
): Promise<LedgerFiscalCalendar> {
|
|
1023
|
+
const body: ReopenPeriodOperation = {
|
|
1024
|
+
period,
|
|
1074
1025
|
reason,
|
|
1075
1026
|
note: note ?? null,
|
|
1076
1027
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
path: { graph_id: graphId,
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
if (response.error) {
|
|
1084
|
-
throw new Error(`Reopen period failed: ${JSON.stringify(response.error)}`)
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
|
-
return toFiscalCalendarState(response.data as FiscalCalendarResponse)
|
|
1028
|
+
const envelope = await this.callOperation(
|
|
1029
|
+
'Reopen period',
|
|
1030
|
+
opReopenPeriod({ path: { graph_id: graphId }, body })
|
|
1031
|
+
)
|
|
1032
|
+
return rawFiscalCalendarToCamel(envelope.result as unknown as RawFiscalCalendar)
|
|
1088
1033
|
}
|
|
1089
1034
|
|
|
1090
|
-
|
|
1091
|
-
* List all draft entries in a fiscal period for review before close.
|
|
1092
|
-
* Fully expanded with line items, element metadata, and per-entry balance.
|
|
1093
|
-
*
|
|
1094
|
-
* Pure read — call repeatedly without side effects.
|
|
1095
|
-
*/
|
|
1096
|
-
async listPeriodDrafts(graphId: string, period: string): Promise<PeriodDraftsView> {
|
|
1097
|
-
const response = await listPeriodDrafts({
|
|
1098
|
-
path: { graph_id: graphId, period },
|
|
1099
|
-
})
|
|
1035
|
+
// Reports, statements, and publish lists live on `ReportClient`.
|
|
1100
1036
|
|
|
1101
|
-
|
|
1102
|
-
throw new Error(`List period drafts failed: ${JSON.stringify(response.error)}`)
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
const data = response.data as PeriodDraftsResponse
|
|
1106
|
-
return {
|
|
1107
|
-
period: data.period,
|
|
1108
|
-
periodStart: data.period_start,
|
|
1109
|
-
periodEnd: data.period_end,
|
|
1110
|
-
draftCount: data.draft_count,
|
|
1111
|
-
totalDebit: data.total_debit,
|
|
1112
|
-
totalCredit: data.total_credit,
|
|
1113
|
-
allBalanced: data.all_balanced,
|
|
1114
|
-
drafts: (data.drafts ?? []).map((d) => ({
|
|
1115
|
-
entryId: d.entry_id,
|
|
1116
|
-
postingDate: d.posting_date,
|
|
1117
|
-
type: d.type,
|
|
1118
|
-
memo: d.memo ?? null,
|
|
1119
|
-
provenance: d.provenance ?? null,
|
|
1120
|
-
sourceStructureId: d.source_structure_id ?? null,
|
|
1121
|
-
sourceStructureName: d.source_structure_name ?? null,
|
|
1122
|
-
lineItems: d.line_items.map((li) => ({
|
|
1123
|
-
lineItemId: li.line_item_id,
|
|
1124
|
-
elementId: li.element_id,
|
|
1125
|
-
elementCode: li.element_code ?? null,
|
|
1126
|
-
elementName: li.element_name,
|
|
1127
|
-
debitAmount: li.debit_amount,
|
|
1128
|
-
creditAmount: li.credit_amount,
|
|
1129
|
-
description: li.description ?? null,
|
|
1130
|
-
})),
|
|
1131
|
-
totalDebit: d.total_debit,
|
|
1132
|
-
totalCredit: d.total_credit,
|
|
1133
|
-
balanced: d.balanced,
|
|
1134
|
-
})),
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
// ── Schedule mutations ──────────────────────────────────────────────
|
|
1037
|
+
// ── Internal helpers ────────────────────────────────────────────────
|
|
1139
1038
|
|
|
1140
1039
|
/**
|
|
1141
|
-
*
|
|
1142
|
-
*
|
|
1143
|
-
* produced. Historical posted facts are preserved.
|
|
1144
|
-
*
|
|
1145
|
-
* `new_end_date` must be a month-end date (service enforces this).
|
|
1040
|
+
* Run a typed GraphQL query against the per-graph endpoint and
|
|
1041
|
+
* translate ClientError into a readable facade error.
|
|
1146
1042
|
*/
|
|
1147
|
-
async
|
|
1043
|
+
private async gqlQuery<TData, TVars extends object, TResult>(
|
|
1148
1044
|
graphId: string,
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
structureId: data.structure_id,
|
|
1169
|
-
newEndDate: data.new_end_date,
|
|
1170
|
-
factsDeleted: data.facts_deleted,
|
|
1171
|
-
reason: data.reason,
|
|
1045
|
+
document: TypedDocumentNode<TData, TVars>,
|
|
1046
|
+
variables: TVars | undefined,
|
|
1047
|
+
label: string,
|
|
1048
|
+
pick: (data: TData) => TResult
|
|
1049
|
+
): Promise<TResult> {
|
|
1050
|
+
try {
|
|
1051
|
+
const client = this.gql.get(graphId)
|
|
1052
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1053
|
+
const raw = client.request as (doc: unknown, vars?: unknown) => Promise<any>
|
|
1054
|
+
// graphql-request's overloads don't cleanly resolve for generic
|
|
1055
|
+
// helpers wrapping codegen's `Exact<>` var types, so we bypass
|
|
1056
|
+
// the typed overload with a narrow cast of `request` itself.
|
|
1057
|
+
const data = (await raw.call(client, document, variables)) as TData
|
|
1058
|
+
return pick(data)
|
|
1059
|
+
} catch (err) {
|
|
1060
|
+
if (err instanceof ClientError) {
|
|
1061
|
+
throw new Error(`${label} failed: ${JSON.stringify(err.response.errors ?? err.message)}`)
|
|
1062
|
+
}
|
|
1063
|
+
throw err
|
|
1172
1064
|
}
|
|
1173
1065
|
}
|
|
1174
1066
|
|
|
1175
1067
|
/**
|
|
1176
|
-
*
|
|
1177
|
-
*
|
|
1178
|
-
* one-off closing events.
|
|
1179
|
-
*
|
|
1180
|
-
* Line items must sum to balanced debits/credits. Rejects entries
|
|
1181
|
-
* targeting an already-closed period.
|
|
1068
|
+
* Await an SDK-generated `opXxx(...)` call, throw a readable error on
|
|
1069
|
+
* non-2xx, and return the `OperationEnvelope` on success.
|
|
1182
1070
|
*/
|
|
1183
|
-
async
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
): Promise<
|
|
1187
|
-
const
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
entry_type: options.entryType,
|
|
1191
|
-
line_items: options.lineItems.map((li) => ({
|
|
1192
|
-
element_id: li.elementId,
|
|
1193
|
-
debit_amount: li.debitAmount ?? 0,
|
|
1194
|
-
credit_amount: li.creditAmount ?? 0,
|
|
1195
|
-
description: li.description ?? null,
|
|
1196
|
-
})),
|
|
1071
|
+
private async callOperation(
|
|
1072
|
+
label: string,
|
|
1073
|
+
call: Promise<{ data?: OperationEnvelope; error?: unknown }>
|
|
1074
|
+
): Promise<OperationEnvelope> {
|
|
1075
|
+
const response = await call
|
|
1076
|
+
if (response.error !== undefined) {
|
|
1077
|
+
throw new Error(`${label} failed: ${JSON.stringify(response.error)}`)
|
|
1197
1078
|
}
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
path: { graph_id: graphId },
|
|
1201
|
-
body,
|
|
1202
|
-
})
|
|
1203
|
-
|
|
1204
|
-
if (response.error) {
|
|
1205
|
-
throw new Error(`Create manual closing entry failed: ${JSON.stringify(response.error)}`)
|
|
1079
|
+
if (response.data === undefined) {
|
|
1080
|
+
throw new Error(`${label} failed: empty response`)
|
|
1206
1081
|
}
|
|
1207
|
-
|
|
1208
|
-
return toClosingEntry(response.data as ClosingEntryResponse)
|
|
1082
|
+
return response.data
|
|
1209
1083
|
}
|
|
1210
1084
|
}
|
|
1211
1085
|
|
|
1212
|
-
// ──
|
|
1086
|
+
// ── Module-private conversion helpers ─────────────────────────────────
|
|
1213
1087
|
|
|
1214
|
-
function
|
|
1088
|
+
function rawToClosingEntry(data: RawClosingEntryResult): ClosingEntry {
|
|
1215
1089
|
return {
|
|
1216
|
-
outcome: data.outcome
|
|
1090
|
+
outcome: data.outcome,
|
|
1217
1091
|
entryId: data.entry_id ?? null,
|
|
1218
1092
|
status: data.status ?? null,
|
|
1219
1093
|
postingDate: data.posting_date ?? null,
|
|
@@ -1225,20 +1099,20 @@ function toClosingEntry(data: ClosingEntryResponse): ClosingEntry {
|
|
|
1225
1099
|
}
|
|
1226
1100
|
}
|
|
1227
1101
|
|
|
1228
|
-
function
|
|
1102
|
+
function rawFiscalCalendarToCamel(raw: RawFiscalCalendar): LedgerFiscalCalendar {
|
|
1229
1103
|
return {
|
|
1230
|
-
graphId:
|
|
1231
|
-
fiscalYearStartMonth:
|
|
1232
|
-
closedThrough:
|
|
1233
|
-
closeTarget:
|
|
1234
|
-
gapPeriods:
|
|
1235
|
-
catchUpSequence:
|
|
1236
|
-
closeableNow:
|
|
1237
|
-
blockers:
|
|
1238
|
-
lastCloseAt:
|
|
1239
|
-
initializedAt:
|
|
1240
|
-
lastSyncAt:
|
|
1241
|
-
periods: (
|
|
1104
|
+
graphId: raw.graph_id,
|
|
1105
|
+
fiscalYearStartMonth: raw.fiscal_year_start_month,
|
|
1106
|
+
closedThrough: raw.closed_through ?? null,
|
|
1107
|
+
closeTarget: raw.close_target ?? null,
|
|
1108
|
+
gapPeriods: raw.gap_periods ?? 0,
|
|
1109
|
+
catchUpSequence: raw.catch_up_sequence ?? [],
|
|
1110
|
+
closeableNow: raw.closeable_now ?? false,
|
|
1111
|
+
blockers: raw.blockers ?? [],
|
|
1112
|
+
lastCloseAt: raw.last_close_at ?? null,
|
|
1113
|
+
initializedAt: raw.initialized_at ?? null,
|
|
1114
|
+
lastSyncAt: raw.last_sync_at ?? null,
|
|
1115
|
+
periods: (raw.periods ?? []).map((p) => ({
|
|
1242
1116
|
name: p.name,
|
|
1243
1117
|
startDate: p.start_date,
|
|
1244
1118
|
endDate: p.end_date,
|