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