@robosystems/client 0.2.48 → 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 +213 -165
- package/extensions/LedgerClient.js +315 -393
- package/extensions/LedgerClient.ts +887 -564
- 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 -65
- package/sdk/index.ts +2 -2
- package/sdk/sdk.gen.d.ts +101 -220
- package/sdk/sdk.gen.js +251 -445
- package/sdk/sdk.gen.ts +216 -409
- package/sdk/types.gen.d.ts +4586 -7045
- package/sdk/types.gen.ts +4702 -7334
- package/sdk.gen.d.ts +101 -220
- package/sdk.gen.js +251 -445
- package/sdk.gen.ts +216 -409
- package/types.gen.d.ts +4586 -7045
- package/types.gen.ts +4702 -7334
- package/extensions/AgentClient.test.ts +0 -403
- package/extensions/LedgerClient.test.ts +0 -1138
- 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 -242
- package/sdk-extensions/LedgerClient.js +0 -496
- package/sdk-extensions/LedgerClient.test.ts +0 -1138
- package/sdk-extensions/LedgerClient.ts +0 -800
- 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,105 +3,269 @@
|
|
|
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
|
-
getMappingCoverage,
|
|
27
|
-
getMappingDetail,
|
|
28
|
-
getPeriodCloseStatus,
|
|
29
|
-
getReportingTaxonomy,
|
|
30
|
-
getScheduleFacts,
|
|
31
|
-
listElements,
|
|
32
|
-
listLedgerAccounts,
|
|
33
|
-
listLedgerTransactions,
|
|
34
|
-
listMappings,
|
|
35
|
-
listSchedules,
|
|
36
|
-
listStructures,
|
|
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,
|
|
37
42
|
} from '../sdk.gen'
|
|
38
43
|
import type {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
CreateClosingEntryRequest,
|
|
44
|
+
AutoMapElementsOperation,
|
|
45
|
+
ClosePeriodOperation,
|
|
46
|
+
CreateClosingEntryOperation,
|
|
47
|
+
CreateManualClosingEntryRequest,
|
|
48
|
+
CreateMappingAssociationOperation,
|
|
45
49
|
CreateScheduleRequest,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
ScheduleFactsResponse,
|
|
56
|
-
ScheduleListResponse,
|
|
57
|
-
ScheduleSummaryResponse,
|
|
58
|
-
TrialBalanceResponse,
|
|
50
|
+
CreateStructureRequest,
|
|
51
|
+
CreateTaxonomyRequest,
|
|
52
|
+
DeleteMappingAssociationOperation,
|
|
53
|
+
InitializeLedgerRequest,
|
|
54
|
+
OperationEnvelope,
|
|
55
|
+
ReopenPeriodOperation,
|
|
56
|
+
SetCloseTargetOperation,
|
|
57
|
+
TruncateScheduleOperation,
|
|
58
|
+
UpdateEntityRequest,
|
|
59
59
|
} from '../types.gen'
|
|
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
|
+
}>
|
|
202
|
+
}
|
|
60
203
|
|
|
61
|
-
|
|
204
|
+
interface RawInitializeLedgerResult {
|
|
205
|
+
fiscal_calendar: RawFiscalCalendar
|
|
206
|
+
periods_created: number
|
|
207
|
+
warnings: string[]
|
|
208
|
+
}
|
|
62
209
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
210
|
+
interface RawClosePeriodResult {
|
|
211
|
+
period: string
|
|
212
|
+
entries_posted: number
|
|
213
|
+
target_auto_advanced: boolean
|
|
214
|
+
fiscal_calendar: RawFiscalCalendar
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
interface RawClosingEntryResult {
|
|
218
|
+
outcome: ClosingEntryOutcome
|
|
219
|
+
entry_id: string | null
|
|
69
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
|
|
70
227
|
}
|
|
71
228
|
|
|
72
|
-
|
|
73
|
-
|
|
229
|
+
interface RawScheduleCreatedResult {
|
|
230
|
+
structure_id: string
|
|
74
231
|
name: string
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
isActive: boolean
|
|
232
|
+
taxonomy_id: string
|
|
233
|
+
total_periods: number
|
|
234
|
+
total_facts: number
|
|
79
235
|
}
|
|
80
236
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
highConfidence: number
|
|
87
|
-
mediumConfidence: number
|
|
88
|
-
lowConfidence: number
|
|
237
|
+
interface RawTruncateScheduleResult {
|
|
238
|
+
structure_id: string
|
|
239
|
+
new_end_date: string
|
|
240
|
+
facts_deleted: number
|
|
241
|
+
reason: string
|
|
89
242
|
}
|
|
90
243
|
|
|
91
|
-
export interface
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
244
|
+
export interface InitializeLedgerResult {
|
|
245
|
+
fiscalCalendar: LedgerFiscalCalendar
|
|
246
|
+
periodsCreated: number
|
|
247
|
+
warnings: string[]
|
|
95
248
|
}
|
|
96
249
|
|
|
97
|
-
export interface
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
250
|
+
export interface ClosePeriodResult {
|
|
251
|
+
period: string
|
|
252
|
+
entriesPosted: number
|
|
253
|
+
targetAutoAdvanced: boolean
|
|
254
|
+
fiscalCalendar: LedgerFiscalCalendar
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export type ClosingEntryOutcome = 'created' | 'unchanged' | 'regenerated' | 'removed' | 'skipped'
|
|
258
|
+
|
|
259
|
+
export interface ClosingEntry {
|
|
260
|
+
outcome: ClosingEntryOutcome
|
|
261
|
+
entryId: string | null
|
|
262
|
+
status: string | null
|
|
263
|
+
postingDate: string | null
|
|
264
|
+
memo: string | null
|
|
265
|
+
debitElementId: string | null
|
|
266
|
+
creditElementId: string | null
|
|
267
|
+
amount: number | null
|
|
268
|
+
reason: string | null
|
|
105
269
|
}
|
|
106
270
|
|
|
107
271
|
export interface ScheduleCreated {
|
|
@@ -112,39 +276,47 @@ export interface ScheduleCreated {
|
|
|
112
276
|
totalFacts: number
|
|
113
277
|
}
|
|
114
278
|
|
|
115
|
-
export interface
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
periodEnd: string
|
|
279
|
+
export interface TruncateScheduleResult {
|
|
280
|
+
structureId: string
|
|
281
|
+
newEndDate: string
|
|
282
|
+
factsDeleted: number
|
|
283
|
+
reason: string
|
|
121
284
|
}
|
|
122
285
|
|
|
123
|
-
export
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
286
|
+
export type LedgerEntryType = 'standard' | 'adjusting' | 'closing' | 'reversing'
|
|
287
|
+
|
|
288
|
+
// ── Caller-facing option interfaces ────────────────────────────────────
|
|
289
|
+
|
|
290
|
+
export interface InitializeLedgerOptions {
|
|
291
|
+
closedThrough?: string | null
|
|
292
|
+
fiscalYearStartMonth?: number
|
|
293
|
+
earliestDataPeriod?: string | null
|
|
294
|
+
autoSeedSchedules?: boolean
|
|
295
|
+
note?: string | null
|
|
129
296
|
}
|
|
130
297
|
|
|
131
|
-
export interface
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
periodStatus: string
|
|
135
|
-
schedules: PeriodCloseItem[]
|
|
136
|
-
totalDraft: number
|
|
137
|
-
totalPosted: number
|
|
298
|
+
export interface ClosePeriodOptions {
|
|
299
|
+
note?: string | null
|
|
300
|
+
allowStaleSync?: boolean
|
|
138
301
|
}
|
|
139
302
|
|
|
140
|
-
export interface
|
|
141
|
-
|
|
142
|
-
|
|
303
|
+
export interface ManualClosingLineItem {
|
|
304
|
+
elementId: string
|
|
305
|
+
debitAmount?: number
|
|
306
|
+
creditAmount?: number
|
|
307
|
+
description?: string | null
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export interface CreateManualClosingEntryOptions {
|
|
143
311
|
postingDate: string
|
|
144
312
|
memo: string
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
313
|
+
lineItems: ManualClosingLineItem[]
|
|
314
|
+
entryType?: LedgerEntryType
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export interface TruncateScheduleOptions {
|
|
318
|
+
newEndDate: string
|
|
319
|
+
reason: string
|
|
148
320
|
}
|
|
149
321
|
|
|
150
322
|
export interface CreateScheduleOptions {
|
|
@@ -156,7 +328,7 @@ export interface CreateScheduleOptions {
|
|
|
156
328
|
entryTemplate: {
|
|
157
329
|
debitElementId: string
|
|
158
330
|
creditElementId: string
|
|
159
|
-
entryType?:
|
|
331
|
+
entryType?: LedgerEntryType
|
|
160
332
|
memoTemplate?: string
|
|
161
333
|
}
|
|
162
334
|
taxonomyId?: string
|
|
@@ -171,230 +343,259 @@ export interface CreateScheduleOptions {
|
|
|
171
343
|
|
|
172
344
|
// ── Client ──────────────────────────────────────────────────────────────
|
|
173
345
|
|
|
346
|
+
interface LedgerClientConfig {
|
|
347
|
+
baseUrl: string
|
|
348
|
+
credentials?: 'include' | 'same-origin' | 'omit'
|
|
349
|
+
headers?: Record<string, string>
|
|
350
|
+
token?: string
|
|
351
|
+
}
|
|
352
|
+
|
|
174
353
|
export class LedgerClient {
|
|
175
|
-
private config:
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
headers?: Record<string, string>
|
|
186
|
-
token?: string
|
|
187
|
-
}) {
|
|
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
|
|
362
|
+
|
|
363
|
+
constructor(config: LedgerClientConfig) {
|
|
188
364
|
this.config = config
|
|
365
|
+
this.gql = new GraphQLClientCache(config)
|
|
189
366
|
}
|
|
190
367
|
|
|
191
368
|
// ── Entity ──────────────────────────────────────────────────────────
|
|
192
369
|
|
|
193
370
|
/**
|
|
194
371
|
* Get the entity (company/organization) for this graph.
|
|
372
|
+
* Returns null when the ledger has no entity yet.
|
|
195
373
|
*/
|
|
196
374
|
async getEntity(graphId: string): Promise<LedgerEntity | null> {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const data = response.data as Record<string, unknown>
|
|
207
|
-
return {
|
|
208
|
-
id: data.id as string,
|
|
209
|
-
name: data.name as string,
|
|
210
|
-
legalName: (data.legal_name as string) ?? null,
|
|
211
|
-
entityType: (data.entity_type as string) ?? null,
|
|
212
|
-
industry: (data.industry as string) ?? null,
|
|
213
|
-
status: (data.status as string) ?? null,
|
|
214
|
-
}
|
|
375
|
+
return this.gqlQuery(
|
|
376
|
+
graphId,
|
|
377
|
+
GetLedgerEntityDocument,
|
|
378
|
+
undefined,
|
|
379
|
+
'Get entity',
|
|
380
|
+
(data) => data.entity
|
|
381
|
+
)
|
|
215
382
|
}
|
|
216
383
|
|
|
217
|
-
|
|
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
|
+
}
|
|
218
397
|
|
|
219
398
|
/**
|
|
220
|
-
*
|
|
399
|
+
* Update the entity for this graph. Only non-null fields are applied.
|
|
400
|
+
* Returns the updated entity.
|
|
221
401
|
*/
|
|
222
|
-
async
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
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
|
+
}
|
|
226
412
|
|
|
227
|
-
|
|
228
|
-
throw new Error(`List accounts failed: ${JSON.stringify(response.error)}`)
|
|
229
|
-
}
|
|
413
|
+
// ── Summary ────────────────────────────────────────────────────────
|
|
230
414
|
|
|
231
|
-
|
|
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
|
+
)
|
|
232
424
|
}
|
|
233
425
|
|
|
234
|
-
|
|
235
|
-
* Get the account tree (hierarchical).
|
|
236
|
-
*/
|
|
237
|
-
async getAccountTree(graphId: string): Promise<AccountTreeResponse> {
|
|
238
|
-
const response = await getLedgerAccountTree({
|
|
239
|
-
path: { graph_id: graphId },
|
|
240
|
-
})
|
|
426
|
+
// ── Accounts (Chart of Accounts) ───────────────────────────────────
|
|
241
427
|
|
|
242
|
-
|
|
243
|
-
|
|
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
|
|
244
436
|
}
|
|
245
|
-
|
|
246
|
-
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
|
+
)
|
|
247
450
|
}
|
|
248
451
|
|
|
249
|
-
|
|
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
|
+
}
|
|
250
462
|
|
|
251
|
-
/**
|
|
252
|
-
|
|
253
|
-
*/
|
|
254
|
-
async listTransactions(
|
|
463
|
+
/** Accounts rolled up to reporting concepts via a mapping structure. */
|
|
464
|
+
async getAccountRollups(
|
|
255
465
|
graphId: string,
|
|
256
|
-
options?: {
|
|
257
|
-
): Promise<
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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,
|
|
265
475
|
},
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
throw new Error(`List transactions failed: ${JSON.stringify(response.error)}`)
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
return response.data as LedgerTransactionListResponse
|
|
476
|
+
'Get account rollups',
|
|
477
|
+
(data) => data.accountRollups
|
|
478
|
+
)
|
|
273
479
|
}
|
|
274
480
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
async
|
|
481
|
+
// ── Transactions ────────────────────────────────────────────────────
|
|
482
|
+
|
|
483
|
+
/** List transactions with optional type + date filters and pagination. */
|
|
484
|
+
async listTransactions(
|
|
279
485
|
graphId: string,
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
if (response.error) {
|
|
287
|
-
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
|
|
288
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
|
+
}
|
|
289
508
|
|
|
290
|
-
|
|
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
|
+
)
|
|
291
518
|
}
|
|
292
519
|
|
|
293
520
|
// ── Trial Balance ──────────────────────────────────────────────────
|
|
294
521
|
|
|
295
|
-
/**
|
|
296
|
-
* Get trial balance (CoA-level debits/credits).
|
|
297
|
-
*/
|
|
522
|
+
/** Trial balance by raw CoA account. */
|
|
298
523
|
async getTrialBalance(
|
|
299
524
|
graphId: string,
|
|
300
525
|
options?: { startDate?: string; endDate?: string }
|
|
301
|
-
): Promise<
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
526
|
+
): Promise<LedgerTrialBalance | null> {
|
|
527
|
+
return this.gqlQuery(
|
|
528
|
+
graphId,
|
|
529
|
+
GetLedgerTrialBalanceDocument,
|
|
530
|
+
{
|
|
531
|
+
startDate: options?.startDate ?? null,
|
|
532
|
+
endDate: options?.endDate ?? null,
|
|
307
533
|
},
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
throw new Error(`Get trial balance failed: ${JSON.stringify(response.error)}`)
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return response.data as TrialBalanceResponse
|
|
534
|
+
'Get trial balance',
|
|
535
|
+
(data) => data.trialBalance
|
|
536
|
+
)
|
|
315
537
|
}
|
|
316
538
|
|
|
317
|
-
/**
|
|
318
|
-
* Get mapped trial balance (CoA rolled up to GAAP concepts).
|
|
319
|
-
*/
|
|
539
|
+
/** Trial balance rolled up to GAAP reporting concepts via a mapping. */
|
|
320
540
|
async getMappedTrialBalance(
|
|
321
541
|
graphId: string,
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
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,
|
|
330
552
|
},
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
throw new Error(`Get mapped trial balance failed: ${JSON.stringify(response.error)}`)
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
return response.data
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// ── Summary ────────────────────────────────────────────────────────
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Get ledger summary (account count, transaction count, date range).
|
|
344
|
-
*/
|
|
345
|
-
async getSummary(graphId: string): Promise<LedgerSummaryResponse> {
|
|
346
|
-
const response = await getLedgerSummary({
|
|
347
|
-
path: { graph_id: graphId },
|
|
348
|
-
})
|
|
349
|
-
|
|
350
|
-
if (response.error) {
|
|
351
|
-
throw new Error(`Get summary failed: ${JSON.stringify(response.error)}`)
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
return response.data as LedgerSummaryResponse
|
|
553
|
+
'Get mapped trial balance',
|
|
554
|
+
(data) => data.mappedTrialBalance
|
|
555
|
+
)
|
|
355
556
|
}
|
|
356
557
|
|
|
357
558
|
// ── Taxonomy ────────────────────────────────────────────────────────
|
|
358
559
|
|
|
359
|
-
/**
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
throw new Error(`Get reporting taxonomy failed: ${JSON.stringify(response.error)}`)
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
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
|
+
)
|
|
372
569
|
}
|
|
373
570
|
|
|
374
|
-
/**
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
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
|
+
}
|
|
386
585
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
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>
|
|
393
596
|
}
|
|
394
597
|
|
|
395
|
-
/**
|
|
396
|
-
* List elements (CoA accounts, GAAP concepts, etc.).
|
|
397
|
-
*/
|
|
598
|
+
/** List elements (CoA accounts, GAAP concepts, etc.) with filters. */
|
|
398
599
|
async listElements(
|
|
399
600
|
graphId: string,
|
|
400
601
|
options?: {
|
|
@@ -405,184 +606,183 @@ export class LedgerClient {
|
|
|
405
606
|
limit?: number
|
|
406
607
|
offset?: number
|
|
407
608
|
}
|
|
408
|
-
): Promise<
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
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,
|
|
418
620
|
},
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
621
|
+
'List elements',
|
|
622
|
+
(data) => data.elements
|
|
623
|
+
)
|
|
624
|
+
}
|
|
424
625
|
|
|
425
|
-
|
|
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
|
+
)
|
|
426
638
|
}
|
|
427
639
|
|
|
428
|
-
// ──
|
|
640
|
+
// ── Structures ──────────────────────────────────────────────────────
|
|
429
641
|
|
|
430
|
-
/**
|
|
431
|
-
|
|
432
|
-
* Returns the created mapping info.
|
|
433
|
-
*/
|
|
434
|
-
async createMappingStructure(
|
|
642
|
+
/** List reporting structures (IS, BS, CF, schedules) with optional filters. */
|
|
643
|
+
async listStructures(
|
|
435
644
|
graphId: string,
|
|
436
|
-
options?: {
|
|
437
|
-
): Promise<
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
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,
|
|
445
653
|
},
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
const data = response.data as Record<string, unknown>
|
|
453
|
-
return {
|
|
454
|
-
id: data.id as string,
|
|
455
|
-
name: data.name as string,
|
|
456
|
-
description: (data.description as string) ?? null,
|
|
457
|
-
structureType: data.structure_type as string,
|
|
458
|
-
taxonomyId: data.taxonomy_id as string,
|
|
459
|
-
isActive: (data.is_active as boolean) ?? true,
|
|
460
|
-
}
|
|
654
|
+
'List structures',
|
|
655
|
+
(data) => data.structures
|
|
656
|
+
)
|
|
657
|
+
return list?.structures ?? []
|
|
461
658
|
}
|
|
462
659
|
|
|
463
660
|
/**
|
|
464
|
-
*
|
|
661
|
+
* Create a new structure. Most common use is a CoA→reporting mapping
|
|
662
|
+
* structure; also used for custom statement + schedule structures.
|
|
465
663
|
*/
|
|
466
|
-
async
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
throw new Error(`List mappings failed: ${JSON.stringify(response.error)}`)
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
const data = response.data as { structures?: Array<Record<string, unknown>> }
|
|
476
|
-
return (data.structures ?? []).map((s) => ({
|
|
477
|
-
id: s.id as string,
|
|
478
|
-
name: s.name as string,
|
|
479
|
-
description: (s.description as string) ?? null,
|
|
480
|
-
structureType: s.structure_type as string,
|
|
481
|
-
taxonomyId: s.taxonomy_id as string,
|
|
482
|
-
isActive: (s.is_active as boolean) ?? true,
|
|
483
|
-
}))
|
|
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
|
|
484
670
|
}
|
|
485
671
|
|
|
486
|
-
|
|
487
|
-
* Get mapping detail — all associations with element names.
|
|
488
|
-
*/
|
|
489
|
-
async getMappingDetail(graphId: string, mappingId: string): Promise<MappingDetailResponse> {
|
|
490
|
-
const response = await getMappingDetail({
|
|
491
|
-
path: { graph_id: graphId, mapping_id: mappingId },
|
|
492
|
-
})
|
|
493
|
-
|
|
494
|
-
if (response.error) {
|
|
495
|
-
throw new Error(`Get mapping detail failed: ${JSON.stringify(response.error)}`)
|
|
496
|
-
}
|
|
672
|
+
// ── Mappings ────────────────────────────────────────────────────────
|
|
497
673
|
|
|
498
|
-
|
|
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 ?? []
|
|
499
684
|
}
|
|
500
685
|
|
|
501
|
-
/**
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
throw new Error(`Get mapping coverage failed: ${JSON.stringify(response.error)}`)
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
const data = response.data as MappingCoverageResponse
|
|
514
|
-
return {
|
|
515
|
-
totalCoaElements: data.total_coa_elements ?? 0,
|
|
516
|
-
mappedCount: data.mapped_count ?? 0,
|
|
517
|
-
unmappedCount: data.unmapped_count ?? 0,
|
|
518
|
-
coveragePercent: data.coverage_percent ?? 0,
|
|
519
|
-
highConfidence: data.high_confidence ?? 0,
|
|
520
|
-
mediumConfidence: data.medium_confidence ?? 0,
|
|
521
|
-
lowConfidence: data.low_confidence ?? 0,
|
|
522
|
-
}
|
|
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
|
+
)
|
|
523
695
|
}
|
|
524
696
|
|
|
525
|
-
/**
|
|
526
|
-
|
|
527
|
-
*/
|
|
528
|
-
async createMapping(
|
|
697
|
+
/** Mapping coverage stats — how many CoA elements are mapped. */
|
|
698
|
+
async getMappingCoverage(
|
|
529
699
|
graphId: string,
|
|
530
|
-
mappingId: string
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
to_element_id: toElementId,
|
|
540
|
-
confidence: confidence ?? 1.0,
|
|
541
|
-
},
|
|
542
|
-
})
|
|
543
|
-
|
|
544
|
-
if (response.error) {
|
|
545
|
-
throw new Error(`Create mapping failed: ${JSON.stringify(response.error)}`)
|
|
546
|
-
}
|
|
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
|
+
)
|
|
547
709
|
}
|
|
548
710
|
|
|
549
|
-
/**
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
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
|
+
}
|
|
556
722
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
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 }
|
|
560
733
|
}
|
|
561
734
|
|
|
562
735
|
/**
|
|
563
|
-
* Trigger AI
|
|
564
|
-
*
|
|
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`.
|
|
565
739
|
*/
|
|
566
|
-
async
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
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
|
+
}
|
|
570
750
|
|
|
571
|
-
|
|
572
|
-
throw new Error(`Auto-map failed: ${JSON.stringify(response.error)}`)
|
|
573
|
-
}
|
|
751
|
+
// ── Schedules ──────────────────────────────────────────────────────
|
|
574
752
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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 ?? []
|
|
579
763
|
}
|
|
580
764
|
|
|
581
|
-
|
|
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
|
+
}
|
|
582
784
|
|
|
583
|
-
/**
|
|
584
|
-
* Create a schedule with pre-generated monthly facts.
|
|
585
|
-
*/
|
|
785
|
+
/** Create a new schedule with pre-generated monthly facts. */
|
|
586
786
|
async createSchedule(graphId: string, options: CreateScheduleOptions): Promise<ScheduleCreated> {
|
|
587
787
|
const body: CreateScheduleRequest = {
|
|
588
788
|
name: options.name,
|
|
@@ -607,117 +807,75 @@ export class LedgerClient {
|
|
|
607
807
|
}
|
|
608
808
|
: undefined,
|
|
609
809
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
path: { graph_id: graphId },
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
if (response.error) {
|
|
617
|
-
throw new Error(`Create schedule failed: ${JSON.stringify(response.error)}`)
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
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
|
|
621
815
|
return {
|
|
622
|
-
structureId:
|
|
623
|
-
name:
|
|
624
|
-
taxonomyId:
|
|
625
|
-
totalPeriods:
|
|
626
|
-
totalFacts:
|
|
816
|
+
structureId: raw.structure_id,
|
|
817
|
+
name: raw.name,
|
|
818
|
+
taxonomyId: raw.taxonomy_id,
|
|
819
|
+
totalPeriods: raw.total_periods,
|
|
820
|
+
totalFacts: raw.total_facts,
|
|
627
821
|
}
|
|
628
822
|
}
|
|
629
823
|
|
|
630
|
-
/**
|
|
631
|
-
|
|
632
|
-
*/
|
|
633
|
-
async listSchedules(graphId: string): Promise<Schedule[]> {
|
|
634
|
-
const response = await listSchedules({
|
|
635
|
-
path: { graph_id: graphId },
|
|
636
|
-
})
|
|
637
|
-
|
|
638
|
-
if (response.error) {
|
|
639
|
-
throw new Error(`List schedules failed: ${JSON.stringify(response.error)}`)
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
const data = response.data as ScheduleListResponse
|
|
643
|
-
return (data.schedules ?? []).map((s: ScheduleSummaryResponse) => ({
|
|
644
|
-
structureId: s.structure_id,
|
|
645
|
-
name: s.name,
|
|
646
|
-
taxonomyName: s.taxonomy_name,
|
|
647
|
-
entryTemplate: s.entry_template ?? null,
|
|
648
|
-
scheduleMetadata: s.schedule_metadata ?? null,
|
|
649
|
-
totalPeriods: s.total_periods,
|
|
650
|
-
periodsWithEntries: s.periods_with_entries,
|
|
651
|
-
}))
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
/**
|
|
655
|
-
* Get facts for a schedule, optionally filtered by period.
|
|
656
|
-
*/
|
|
657
|
-
async getScheduleFacts(
|
|
824
|
+
/** Truncate a schedule — end it early at `newEndDate`. */
|
|
825
|
+
async truncateSchedule(
|
|
658
826
|
graphId: string,
|
|
659
827
|
structureId: string,
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
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,
|
|
673
845
|
}
|
|
674
|
-
|
|
675
|
-
const data = response.data as ScheduleFactsResponse
|
|
676
|
-
return (data.facts ?? []).map((f: ScheduleFactResponse) => ({
|
|
677
|
-
elementId: f.element_id,
|
|
678
|
-
elementName: f.element_name,
|
|
679
|
-
value: f.value,
|
|
680
|
-
periodStart: f.period_start,
|
|
681
|
-
periodEnd: f.period_end,
|
|
682
|
-
}))
|
|
683
846
|
}
|
|
684
847
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
848
|
+
// ── Period close ────────────────────────────────────────────────────
|
|
849
|
+
|
|
850
|
+
/** Close status for all schedules in a fiscal period. */
|
|
688
851
|
async getPeriodCloseStatus(
|
|
689
852
|
graphId: string,
|
|
690
853
|
periodStart: string,
|
|
691
854
|
periodEnd: string
|
|
692
|
-
): Promise<
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
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
|
+
}
|
|
701
864
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
status: s.status,
|
|
712
|
-
entryId: s.entry_id ?? null,
|
|
713
|
-
})),
|
|
714
|
-
totalDraft: data.total_draft,
|
|
715
|
-
totalPosted: data.total_posted,
|
|
716
|
-
}
|
|
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
|
+
)
|
|
717
874
|
}
|
|
718
875
|
|
|
719
876
|
/**
|
|
720
|
-
*
|
|
877
|
+
* Idempotently create (or refresh) a draft closing entry from a
|
|
878
|
+
* schedule for a period. See `ClosingEntryOutcome` for semantics.
|
|
721
879
|
*/
|
|
722
880
|
async createClosingEntry(
|
|
723
881
|
graphId: string,
|
|
@@ -727,74 +885,239 @@ export class LedgerClient {
|
|
|
727
885
|
periodEnd: string,
|
|
728
886
|
memo?: string
|
|
729
887
|
): Promise<ClosingEntry> {
|
|
730
|
-
const body:
|
|
888
|
+
const body: CreateClosingEntryOperation = {
|
|
889
|
+
structure_id: structureId,
|
|
731
890
|
posting_date: postingDate,
|
|
732
891
|
period_start: periodStart,
|
|
733
892
|
period_end: periodEnd,
|
|
734
893
|
memo: memo ?? undefined,
|
|
735
894
|
}
|
|
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)
|
|
900
|
+
}
|
|
736
901
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
902
|
+
/**
|
|
903
|
+
* Create a manual balanced closing entry (not tied to a schedule).
|
|
904
|
+
* Used for disposals, adjustments, and one-off closing events.
|
|
905
|
+
*/
|
|
906
|
+
async createManualClosingEntry(
|
|
907
|
+
graphId: string,
|
|
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
|
+
})),
|
|
744
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
|
+
}
|
|
927
|
+
|
|
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
|
+
)
|
|
939
|
+
}
|
|
940
|
+
|
|
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
|
+
}
|
|
745
953
|
|
|
746
|
-
|
|
954
|
+
/** One-time ledger initialization — seed fiscal calendar + periods. */
|
|
955
|
+
async initializeLedger(
|
|
956
|
+
graphId: string,
|
|
957
|
+
options?: InitializeLedgerOptions
|
|
958
|
+
): Promise<InitializeLedgerResult> {
|
|
959
|
+
const body: InitializeLedgerRequest = {
|
|
960
|
+
closed_through: options?.closedThrough ?? null,
|
|
961
|
+
fiscal_year_start_month: options?.fiscalYearStartMonth,
|
|
962
|
+
earliest_data_period: options?.earliestDataPeriod ?? null,
|
|
963
|
+
auto_seed_schedules: options?.autoSeedSchedules,
|
|
964
|
+
note: options?.note ?? null,
|
|
965
|
+
}
|
|
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
|
|
747
971
|
return {
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
memo: data.memo,
|
|
752
|
-
debitElementId: data.debit_element_id,
|
|
753
|
-
creditElementId: data.credit_element_id,
|
|
754
|
-
amount: data.amount,
|
|
972
|
+
fiscalCalendar: rawFiscalCalendarToCamel(raw.fiscal_calendar),
|
|
973
|
+
periodsCreated: raw.periods_created ?? 0,
|
|
974
|
+
warnings: raw.warnings ?? [],
|
|
755
975
|
}
|
|
756
976
|
}
|
|
757
977
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
path: { graph_id: graphId },
|
|
768
|
-
|
|
978
|
+
/** Set the user-controlled close target (YYYY-MM). */
|
|
979
|
+
async setCloseTarget(
|
|
980
|
+
graphId: string,
|
|
981
|
+
period: string,
|
|
982
|
+
note?: string | null
|
|
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)
|
|
990
|
+
}
|
|
769
991
|
|
|
770
|
-
|
|
771
|
-
|
|
992
|
+
/** Close a fiscal period — the final commit action. */
|
|
993
|
+
async closePeriod(
|
|
994
|
+
graphId: string,
|
|
995
|
+
period: string,
|
|
996
|
+
options?: ClosePeriodOptions
|
|
997
|
+
): Promise<ClosePeriodResult> {
|
|
998
|
+
const body: ClosePeriodOperation = {
|
|
999
|
+
period,
|
|
1000
|
+
note: options?.note ?? null,
|
|
1001
|
+
allow_stale_sync: options?.allowStaleSync,
|
|
772
1002
|
}
|
|
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
|
|
1008
|
+
return {
|
|
1009
|
+
period: raw.period,
|
|
1010
|
+
entriesPosted: raw.entries_posted ?? 0,
|
|
1011
|
+
targetAutoAdvanced: raw.target_auto_advanced ?? false,
|
|
1012
|
+
fiscalCalendar: rawFiscalCalendarToCamel(raw.fiscal_calendar),
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
773
1015
|
|
|
774
|
-
|
|
1016
|
+
/** Reopen a closed fiscal period. Requires a reason for the audit log. */
|
|
1017
|
+
async reopenPeriod(
|
|
1018
|
+
graphId: string,
|
|
1019
|
+
period: string,
|
|
1020
|
+
reason: string,
|
|
1021
|
+
note?: string | null
|
|
1022
|
+
): Promise<LedgerFiscalCalendar> {
|
|
1023
|
+
const body: ReopenPeriodOperation = {
|
|
1024
|
+
period,
|
|
1025
|
+
reason,
|
|
1026
|
+
note: note ?? null,
|
|
1027
|
+
}
|
|
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)
|
|
775
1033
|
}
|
|
776
1034
|
|
|
1035
|
+
// Reports, statements, and publish lists live on `ReportClient`.
|
|
1036
|
+
|
|
1037
|
+
// ── Internal helpers ────────────────────────────────────────────────
|
|
1038
|
+
|
|
777
1039
|
/**
|
|
778
|
-
*
|
|
779
|
-
*
|
|
1040
|
+
* Run a typed GraphQL query against the per-graph endpoint and
|
|
1041
|
+
* translate ClientError into a readable facade error.
|
|
780
1042
|
*/
|
|
781
|
-
async
|
|
1043
|
+
private async gqlQuery<TData, TVars extends object, TResult>(
|
|
782
1044
|
graphId: string,
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
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
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
793
1066
|
|
|
794
|
-
|
|
795
|
-
|
|
1067
|
+
/**
|
|
1068
|
+
* Await an SDK-generated `opXxx(...)` call, throw a readable error on
|
|
1069
|
+
* non-2xx, and return the `OperationEnvelope` on success.
|
|
1070
|
+
*/
|
|
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)}`)
|
|
796
1078
|
}
|
|
1079
|
+
if (response.data === undefined) {
|
|
1080
|
+
throw new Error(`${label} failed: empty response`)
|
|
1081
|
+
}
|
|
1082
|
+
return response.data
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
// ── Module-private conversion helpers ─────────────────────────────────
|
|
1087
|
+
|
|
1088
|
+
function rawToClosingEntry(data: RawClosingEntryResult): ClosingEntry {
|
|
1089
|
+
return {
|
|
1090
|
+
outcome: data.outcome,
|
|
1091
|
+
entryId: data.entry_id ?? null,
|
|
1092
|
+
status: data.status ?? null,
|
|
1093
|
+
postingDate: data.posting_date ?? null,
|
|
1094
|
+
memo: data.memo ?? null,
|
|
1095
|
+
debitElementId: data.debit_element_id ?? null,
|
|
1096
|
+
creditElementId: data.credit_element_id ?? null,
|
|
1097
|
+
amount: data.amount ?? null,
|
|
1098
|
+
reason: data.reason ?? null,
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
797
1101
|
|
|
798
|
-
|
|
1102
|
+
function rawFiscalCalendarToCamel(raw: RawFiscalCalendar): LedgerFiscalCalendar {
|
|
1103
|
+
return {
|
|
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) => ({
|
|
1116
|
+
name: p.name,
|
|
1117
|
+
startDate: p.start_date,
|
|
1118
|
+
endDate: p.end_date,
|
|
1119
|
+
status: p.status,
|
|
1120
|
+
closedAt: p.closed_at ?? null,
|
|
1121
|
+
})),
|
|
799
1122
|
}
|
|
800
1123
|
}
|