@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
|
@@ -1,1249 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Ledger Client for RoboSystems API
|
|
5
|
-
*
|
|
6
|
-
* High-level client for all ledger concerns: chart of accounts, transactions,
|
|
7
|
-
* trial balance, taxonomy, mappings, and AI auto-mapping. This is the
|
|
8
|
-
* operational backbone — reports consume these as inputs.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
autoMapElements,
|
|
13
|
-
closeFiscalPeriod,
|
|
14
|
-
createClosingEntry,
|
|
15
|
-
createManualClosingEntry,
|
|
16
|
-
createMappingAssociation,
|
|
17
|
-
createSchedule,
|
|
18
|
-
createStructure,
|
|
19
|
-
deleteMappingAssociation,
|
|
20
|
-
getAccountRollups,
|
|
21
|
-
getClosingBookStructures,
|
|
22
|
-
getFiscalCalendar,
|
|
23
|
-
getLedgerAccountTree,
|
|
24
|
-
getLedgerEntity,
|
|
25
|
-
getLedgerSummary,
|
|
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,
|
|
45
|
-
} from '../sdk/sdk.gen'
|
|
46
|
-
import type {
|
|
47
|
-
AccountListResponse,
|
|
48
|
-
AccountRollupsResponse,
|
|
49
|
-
AccountTreeResponse,
|
|
50
|
-
ClosePeriodRequest,
|
|
51
|
-
ClosePeriodResponse,
|
|
52
|
-
ClosingBookStructuresResponse,
|
|
53
|
-
ClosingEntryResponse,
|
|
54
|
-
CreateClosingEntryRequest,
|
|
55
|
-
CreateManualClosingEntryRequest,
|
|
56
|
-
CreateScheduleRequest,
|
|
57
|
-
FiscalCalendarResponse,
|
|
58
|
-
InitializeLedgerRequest,
|
|
59
|
-
InitializeLedgerResponse,
|
|
60
|
-
LedgerSummaryResponse,
|
|
61
|
-
LedgerTransactionDetailResponse,
|
|
62
|
-
LedgerTransactionListResponse,
|
|
63
|
-
MappingCoverageResponse,
|
|
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,
|
|
78
|
-
} from '../sdk/types.gen'
|
|
79
|
-
|
|
80
|
-
// ── Friendly types ──────────────────────────────────────────────────────
|
|
81
|
-
|
|
82
|
-
export interface LedgerEntity {
|
|
83
|
-
id: string
|
|
84
|
-
name: string
|
|
85
|
-
legalName: string | null
|
|
86
|
-
entityType: string | null
|
|
87
|
-
industry: string | null
|
|
88
|
-
status: string | null
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export interface MappingInfo {
|
|
92
|
-
id: string
|
|
93
|
-
name: string
|
|
94
|
-
description: string | null
|
|
95
|
-
structureType: string
|
|
96
|
-
taxonomyId: string
|
|
97
|
-
isActive: boolean
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface MappingCoverage {
|
|
101
|
-
totalCoaElements: number
|
|
102
|
-
mappedCount: number
|
|
103
|
-
unmappedCount: number
|
|
104
|
-
coveragePercent: number
|
|
105
|
-
highConfidence: number
|
|
106
|
-
mediumConfidence: number
|
|
107
|
-
lowConfidence: number
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export interface Structure {
|
|
111
|
-
id: string
|
|
112
|
-
name: string
|
|
113
|
-
structureType: string
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export interface Schedule {
|
|
117
|
-
structureId: string
|
|
118
|
-
name: string
|
|
119
|
-
taxonomyName: string
|
|
120
|
-
entryTemplate: Record<string, unknown> | null
|
|
121
|
-
scheduleMetadata: Record<string, unknown> | null
|
|
122
|
-
totalPeriods: number
|
|
123
|
-
periodsWithEntries: number
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export interface ScheduleCreated {
|
|
127
|
-
structureId: string
|
|
128
|
-
name: string
|
|
129
|
-
taxonomyId: string
|
|
130
|
-
totalPeriods: number
|
|
131
|
-
totalFacts: number
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export interface ScheduleFact {
|
|
135
|
-
elementId: string
|
|
136
|
-
elementName: string
|
|
137
|
-
value: number
|
|
138
|
-
periodStart: string
|
|
139
|
-
periodEnd: string
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export interface PeriodCloseItem {
|
|
143
|
-
structureId: string
|
|
144
|
-
structureName: string
|
|
145
|
-
amount: number
|
|
146
|
-
status: string
|
|
147
|
-
entryId: string | null
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export interface PeriodCloseStatus {
|
|
151
|
-
fiscalPeriodStart: string
|
|
152
|
-
fiscalPeriodEnd: string
|
|
153
|
-
periodStatus: string
|
|
154
|
-
schedules: PeriodCloseItem[]
|
|
155
|
-
totalDraft: number
|
|
156
|
-
totalPosted: number
|
|
157
|
-
}
|
|
158
|
-
|
|
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
|
-
export type ClosingEntryOutcome = 'created' | 'unchanged' | 'regenerated' | 'removed' | 'skipped'
|
|
169
|
-
|
|
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
|
-
export interface ClosingEntry {
|
|
175
|
-
outcome: ClosingEntryOutcome
|
|
176
|
-
entryId: string | null
|
|
177
|
-
status: string | null
|
|
178
|
-
postingDate: string | null
|
|
179
|
-
memo: string | null
|
|
180
|
-
debitElementId: string | null
|
|
181
|
-
creditElementId: string | null
|
|
182
|
-
amount: number | null
|
|
183
|
-
reason: string | null
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export type LedgerEntryType = 'standard' | 'adjusting' | 'closing' | 'reversing'
|
|
187
|
-
|
|
188
|
-
// ── Fiscal calendar types ──────────────────────────────────────────────
|
|
189
|
-
|
|
190
|
-
export interface FiscalPeriodSummary {
|
|
191
|
-
name: string
|
|
192
|
-
startDate: string
|
|
193
|
-
endDate: string
|
|
194
|
-
status: string
|
|
195
|
-
closedAt: string | null
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
export interface FiscalCalendarState {
|
|
199
|
-
graphId: string
|
|
200
|
-
fiscalYearStartMonth: number
|
|
201
|
-
closedThrough: string | null
|
|
202
|
-
closeTarget: string | null
|
|
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[]
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export interface InitializeLedgerOptions {
|
|
214
|
-
closedThrough?: string | null
|
|
215
|
-
fiscalYearStartMonth?: number
|
|
216
|
-
earliestDataPeriod?: string | null
|
|
217
|
-
autoSeedSchedules?: boolean
|
|
218
|
-
note?: string | null
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export interface InitializeLedgerResult {
|
|
222
|
-
fiscalCalendar: FiscalCalendarState
|
|
223
|
-
periodsCreated: number
|
|
224
|
-
warnings: string[]
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export interface ClosePeriodOptions {
|
|
228
|
-
note?: string | null
|
|
229
|
-
allowStaleSync?: boolean
|
|
230
|
-
}
|
|
231
|
-
|
|
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
|
-
export interface ManualClosingLineItem {
|
|
275
|
-
elementId: string
|
|
276
|
-
debitAmount?: number
|
|
277
|
-
creditAmount?: number
|
|
278
|
-
description?: string | null
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
export interface CreateManualClosingEntryOptions {
|
|
282
|
-
postingDate: string
|
|
283
|
-
memo: string
|
|
284
|
-
lineItems: ManualClosingLineItem[]
|
|
285
|
-
entryType?: LedgerEntryType
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
export interface TruncateScheduleOptions {
|
|
289
|
-
newEndDate: string
|
|
290
|
-
reason: string
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
export interface TruncateScheduleResult {
|
|
294
|
-
structureId: string
|
|
295
|
-
newEndDate: string
|
|
296
|
-
factsDeleted: number
|
|
297
|
-
reason: string
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
export interface CreateScheduleOptions {
|
|
301
|
-
name: string
|
|
302
|
-
elementIds: string[]
|
|
303
|
-
periodStart: string
|
|
304
|
-
periodEnd: string
|
|
305
|
-
monthlyAmount: number
|
|
306
|
-
entryTemplate: {
|
|
307
|
-
debitElementId: string
|
|
308
|
-
creditElementId: string
|
|
309
|
-
entryType?: LedgerEntryType
|
|
310
|
-
memoTemplate?: string
|
|
311
|
-
}
|
|
312
|
-
taxonomyId?: string
|
|
313
|
-
scheduleMetadata?: {
|
|
314
|
-
method?: string
|
|
315
|
-
originalAmount?: number
|
|
316
|
-
residualValue?: number
|
|
317
|
-
usefulLifeMonths?: number
|
|
318
|
-
assetElementId?: string
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// ── Client ──────────────────────────────────────────────────────────────
|
|
323
|
-
|
|
324
|
-
export class LedgerClient {
|
|
325
|
-
private config: {
|
|
326
|
-
baseUrl: string
|
|
327
|
-
credentials?: 'include' | 'same-origin' | 'omit'
|
|
328
|
-
headers?: Record<string, string>
|
|
329
|
-
token?: string
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
constructor(config: {
|
|
333
|
-
baseUrl: string
|
|
334
|
-
credentials?: 'include' | 'same-origin' | 'omit'
|
|
335
|
-
headers?: Record<string, string>
|
|
336
|
-
token?: string
|
|
337
|
-
}) {
|
|
338
|
-
this.config = config
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// ── Entity ──────────────────────────────────────────────────────────
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Get the entity (company/organization) for this graph.
|
|
345
|
-
*/
|
|
346
|
-
async getEntity(graphId: string): Promise<LedgerEntity | null> {
|
|
347
|
-
const response = await getLedgerEntity({
|
|
348
|
-
path: { graph_id: graphId },
|
|
349
|
-
})
|
|
350
|
-
|
|
351
|
-
if (response.response.status === 404) return null
|
|
352
|
-
if (response.error) {
|
|
353
|
-
throw new Error(`Get entity failed: ${JSON.stringify(response.error)}`)
|
|
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
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// ── Accounts (Chart of Accounts) ───────────────────────────────────
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* List accounts (flat).
|
|
371
|
-
*/
|
|
372
|
-
async listAccounts(graphId: string): Promise<AccountListResponse> {
|
|
373
|
-
const response = await listLedgerAccounts({
|
|
374
|
-
path: { graph_id: graphId },
|
|
375
|
-
})
|
|
376
|
-
|
|
377
|
-
if (response.error) {
|
|
378
|
-
throw new Error(`List accounts failed: ${JSON.stringify(response.error)}`)
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
return response.data as AccountListResponse
|
|
382
|
-
}
|
|
383
|
-
|
|
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
|
-
})
|
|
391
|
-
|
|
392
|
-
if (response.error) {
|
|
393
|
-
throw new Error(`Get account tree failed: ${JSON.stringify(response.error)}`)
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
return response.data as AccountTreeResponse
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// ── Transactions ────────────────────────────────────────────────────
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* List transactions with optional date filters.
|
|
403
|
-
*/
|
|
404
|
-
async listTransactions(
|
|
405
|
-
graphId: string,
|
|
406
|
-
options?: { startDate?: string; endDate?: string; limit?: number; offset?: number }
|
|
407
|
-
): Promise<LedgerTransactionListResponse> {
|
|
408
|
-
const response = await listLedgerTransactions({
|
|
409
|
-
path: { graph_id: graphId },
|
|
410
|
-
query: {
|
|
411
|
-
start_date: options?.startDate,
|
|
412
|
-
end_date: options?.endDate,
|
|
413
|
-
limit: options?.limit,
|
|
414
|
-
offset: options?.offset,
|
|
415
|
-
},
|
|
416
|
-
})
|
|
417
|
-
|
|
418
|
-
if (response.error) {
|
|
419
|
-
throw new Error(`List transactions failed: ${JSON.stringify(response.error)}`)
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
return response.data as LedgerTransactionListResponse
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
/**
|
|
426
|
-
* Get transaction detail with entries and line items.
|
|
427
|
-
*/
|
|
428
|
-
async getTransaction(
|
|
429
|
-
graphId: string,
|
|
430
|
-
transactionId: string
|
|
431
|
-
): Promise<LedgerTransactionDetailResponse> {
|
|
432
|
-
const response = await getLedgerTransaction({
|
|
433
|
-
path: { graph_id: graphId, transaction_id: transactionId },
|
|
434
|
-
})
|
|
435
|
-
|
|
436
|
-
if (response.error) {
|
|
437
|
-
throw new Error(`Get transaction failed: ${JSON.stringify(response.error)}`)
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
return response.data as LedgerTransactionDetailResponse
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
// ── Trial Balance ──────────────────────────────────────────────────
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
* Get trial balance (CoA-level debits/credits).
|
|
447
|
-
*/
|
|
448
|
-
async getTrialBalance(
|
|
449
|
-
graphId: string,
|
|
450
|
-
options?: { startDate?: string; endDate?: string }
|
|
451
|
-
): Promise<TrialBalanceResponse> {
|
|
452
|
-
const response = await getLedgerTrialBalance({
|
|
453
|
-
path: { graph_id: graphId },
|
|
454
|
-
query: {
|
|
455
|
-
start_date: options?.startDate,
|
|
456
|
-
end_date: options?.endDate,
|
|
457
|
-
},
|
|
458
|
-
})
|
|
459
|
-
|
|
460
|
-
if (response.error) {
|
|
461
|
-
throw new Error(`Get trial balance failed: ${JSON.stringify(response.error)}`)
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
return response.data as TrialBalanceResponse
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
/**
|
|
468
|
-
* Get mapped trial balance (CoA rolled up to GAAP concepts).
|
|
469
|
-
*/
|
|
470
|
-
async getMappedTrialBalance(
|
|
471
|
-
graphId: string,
|
|
472
|
-
options?: { mappingId?: string; startDate?: string; endDate?: string }
|
|
473
|
-
): Promise<unknown> {
|
|
474
|
-
const response = await getMappedTrialBalance({
|
|
475
|
-
path: { graph_id: graphId },
|
|
476
|
-
query: {
|
|
477
|
-
mapping_id: options?.mappingId,
|
|
478
|
-
start_date: options?.startDate,
|
|
479
|
-
end_date: options?.endDate,
|
|
480
|
-
},
|
|
481
|
-
})
|
|
482
|
-
|
|
483
|
-
if (response.error) {
|
|
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
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
// ── Taxonomy ────────────────────────────────────────────────────────
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Get the reporting taxonomy (US GAAP seed).
|
|
511
|
-
*/
|
|
512
|
-
async getReportingTaxonomy(graphId: string): Promise<unknown> {
|
|
513
|
-
const response = await getReportingTaxonomy({
|
|
514
|
-
path: { graph_id: graphId },
|
|
515
|
-
})
|
|
516
|
-
|
|
517
|
-
if (response.error) {
|
|
518
|
-
throw new Error(`Get reporting taxonomy failed: ${JSON.stringify(response.error)}`)
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
return response.data
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
/**
|
|
525
|
-
* List reporting structures (IS, BS, CF) for a taxonomy.
|
|
526
|
-
*/
|
|
527
|
-
async listStructures(graphId: string, taxonomyId?: string): Promise<Structure[]> {
|
|
528
|
-
const response = await listStructures({
|
|
529
|
-
path: { graph_id: graphId },
|
|
530
|
-
query: taxonomyId ? { taxonomy_id: taxonomyId } : undefined,
|
|
531
|
-
})
|
|
532
|
-
|
|
533
|
-
if (response.error) {
|
|
534
|
-
throw new Error(`List structures failed: ${JSON.stringify(response.error)}`)
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
const data = response.data as { structures?: Array<Record<string, unknown>> }
|
|
538
|
-
return (data.structures ?? []).map((s) => ({
|
|
539
|
-
id: s.id as string,
|
|
540
|
-
name: s.name as string,
|
|
541
|
-
structureType: s.structure_type as string,
|
|
542
|
-
}))
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
/**
|
|
546
|
-
* List elements (CoA accounts, GAAP concepts, etc.).
|
|
547
|
-
*/
|
|
548
|
-
async listElements(
|
|
549
|
-
graphId: string,
|
|
550
|
-
options?: {
|
|
551
|
-
taxonomyId?: string
|
|
552
|
-
source?: string
|
|
553
|
-
classification?: string
|
|
554
|
-
isAbstract?: boolean
|
|
555
|
-
limit?: number
|
|
556
|
-
offset?: number
|
|
557
|
-
}
|
|
558
|
-
): Promise<unknown> {
|
|
559
|
-
const response = await listElements({
|
|
560
|
-
path: { graph_id: graphId },
|
|
561
|
-
query: {
|
|
562
|
-
taxonomy_id: options?.taxonomyId,
|
|
563
|
-
source: options?.source,
|
|
564
|
-
classification: options?.classification,
|
|
565
|
-
is_abstract: options?.isAbstract,
|
|
566
|
-
limit: options?.limit,
|
|
567
|
-
offset: options?.offset,
|
|
568
|
-
},
|
|
569
|
-
})
|
|
570
|
-
|
|
571
|
-
if (response.error) {
|
|
572
|
-
throw new Error(`List elements failed: ${JSON.stringify(response.error)}`)
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
return response.data
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
// ── Mappings ────────────────────────────────────────────────────────
|
|
579
|
-
|
|
580
|
-
/**
|
|
581
|
-
* Create a new CoA→GAAP mapping structure.
|
|
582
|
-
* Returns the created mapping info.
|
|
583
|
-
*/
|
|
584
|
-
async createMappingStructure(
|
|
585
|
-
graphId: string,
|
|
586
|
-
options?: { name?: string; description?: string; taxonomyId?: string }
|
|
587
|
-
): Promise<MappingInfo> {
|
|
588
|
-
const response = await createStructure({
|
|
589
|
-
path: { graph_id: graphId },
|
|
590
|
-
body: {
|
|
591
|
-
name: options?.name ?? 'CoA to Reporting',
|
|
592
|
-
description: options?.description ?? 'Map Chart of Accounts to US GAAP reporting concepts',
|
|
593
|
-
structure_type: 'coa_mapping',
|
|
594
|
-
taxonomy_id: options?.taxonomyId ?? 'tax_usgaap_reporting',
|
|
595
|
-
},
|
|
596
|
-
})
|
|
597
|
-
|
|
598
|
-
if (response.error) {
|
|
599
|
-
throw new Error(`Create mapping structure failed: ${JSON.stringify(response.error)}`)
|
|
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
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
/**
|
|
614
|
-
* List available CoA→GAAP mapping structures.
|
|
615
|
-
*/
|
|
616
|
-
async listMappings(graphId: string): Promise<MappingInfo[]> {
|
|
617
|
-
const response = await listMappings({
|
|
618
|
-
path: { graph_id: graphId },
|
|
619
|
-
})
|
|
620
|
-
|
|
621
|
-
if (response.error) {
|
|
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
|
-
}))
|
|
634
|
-
}
|
|
635
|
-
|
|
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
|
-
}
|
|
647
|
-
|
|
648
|
-
return response.data as MappingDetailResponse
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
/**
|
|
652
|
-
* Get mapping coverage — how many CoA elements are mapped.
|
|
653
|
-
*/
|
|
654
|
-
async getMappingCoverage(graphId: string, mappingId: string): Promise<MappingCoverage> {
|
|
655
|
-
const response = await getMappingCoverage({
|
|
656
|
-
path: { graph_id: graphId, mapping_id: mappingId },
|
|
657
|
-
})
|
|
658
|
-
|
|
659
|
-
if (response.error) {
|
|
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
|
-
}
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
/**
|
|
676
|
-
* Create a manual mapping association (CoA element → GAAP element).
|
|
677
|
-
*/
|
|
678
|
-
async createMapping(
|
|
679
|
-
graphId: string,
|
|
680
|
-
mappingId: string,
|
|
681
|
-
fromElementId: string,
|
|
682
|
-
toElementId: string,
|
|
683
|
-
confidence?: number
|
|
684
|
-
): Promise<void> {
|
|
685
|
-
const response = await createMappingAssociation({
|
|
686
|
-
path: { graph_id: graphId, mapping_id: mappingId },
|
|
687
|
-
body: {
|
|
688
|
-
from_element_id: fromElementId,
|
|
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
|
-
}
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
/**
|
|
700
|
-
* Delete a mapping association.
|
|
701
|
-
*/
|
|
702
|
-
async deleteMapping(graphId: string, mappingId: string, associationId: string): Promise<void> {
|
|
703
|
-
const response = await deleteMappingAssociation({
|
|
704
|
-
path: { graph_id: graphId, mapping_id: mappingId, association_id: associationId },
|
|
705
|
-
})
|
|
706
|
-
|
|
707
|
-
if (response.error) {
|
|
708
|
-
throw new Error(`Delete mapping failed: ${JSON.stringify(response.error)}`)
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
/**
|
|
713
|
-
* Trigger AI auto-mapping (MappingAgent).
|
|
714
|
-
* Returns immediately — the agent runs in the background.
|
|
715
|
-
*/
|
|
716
|
-
async autoMap(graphId: string, mappingId: string): Promise<{ operationId?: string }> {
|
|
717
|
-
const response = await autoMapElements({
|
|
718
|
-
path: { graph_id: graphId, mapping_id: mappingId },
|
|
719
|
-
})
|
|
720
|
-
|
|
721
|
-
if (response.error) {
|
|
722
|
-
throw new Error(`Auto-map failed: ${JSON.stringify(response.error)}`)
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
const data = response.data as Record<string, unknown> | undefined
|
|
726
|
-
return {
|
|
727
|
-
operationId: data?.operation_id as string | undefined,
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
// ── Schedules ──────────────────────────────────────────────────────
|
|
732
|
-
|
|
733
|
-
/**
|
|
734
|
-
* Create a schedule with pre-generated monthly facts.
|
|
735
|
-
*/
|
|
736
|
-
async createSchedule(graphId: string, options: CreateScheduleOptions): Promise<ScheduleCreated> {
|
|
737
|
-
const body: CreateScheduleRequest = {
|
|
738
|
-
name: options.name,
|
|
739
|
-
element_ids: options.elementIds,
|
|
740
|
-
period_start: options.periodStart,
|
|
741
|
-
period_end: options.periodEnd,
|
|
742
|
-
monthly_amount: options.monthlyAmount,
|
|
743
|
-
entry_template: {
|
|
744
|
-
debit_element_id: options.entryTemplate.debitElementId,
|
|
745
|
-
credit_element_id: options.entryTemplate.creditElementId,
|
|
746
|
-
entry_type: options.entryTemplate.entryType,
|
|
747
|
-
memo_template: options.entryTemplate.memoTemplate,
|
|
748
|
-
},
|
|
749
|
-
taxonomy_id: options.taxonomyId,
|
|
750
|
-
schedule_metadata: options.scheduleMetadata
|
|
751
|
-
? {
|
|
752
|
-
method: options.scheduleMetadata.method,
|
|
753
|
-
original_amount: options.scheduleMetadata.originalAmount,
|
|
754
|
-
residual_value: options.scheduleMetadata.residualValue,
|
|
755
|
-
useful_life_months: options.scheduleMetadata.usefulLifeMonths,
|
|
756
|
-
asset_element_id: options.scheduleMetadata.assetElementId,
|
|
757
|
-
}
|
|
758
|
-
: undefined,
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
const response = await createSchedule({
|
|
762
|
-
path: { graph_id: graphId },
|
|
763
|
-
body,
|
|
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
|
|
771
|
-
return {
|
|
772
|
-
structureId: data.structure_id,
|
|
773
|
-
name: data.name,
|
|
774
|
-
taxonomyId: data.taxonomy_id,
|
|
775
|
-
totalPeriods: data.total_periods,
|
|
776
|
-
totalFacts: data.total_facts,
|
|
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)}`)
|
|
790
|
-
}
|
|
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
|
-
}
|
|
803
|
-
|
|
804
|
-
/**
|
|
805
|
-
* Get facts for a schedule, optionally filtered by period.
|
|
806
|
-
*/
|
|
807
|
-
async getScheduleFacts(
|
|
808
|
-
graphId: string,
|
|
809
|
-
structureId: string,
|
|
810
|
-
periodStart?: string,
|
|
811
|
-
periodEnd?: string
|
|
812
|
-
): Promise<ScheduleFact[]> {
|
|
813
|
-
const response = await getScheduleFacts({
|
|
814
|
-
path: { graph_id: graphId, structure_id: structureId },
|
|
815
|
-
query: {
|
|
816
|
-
period_start: periodStart ?? null,
|
|
817
|
-
period_end: periodEnd ?? null,
|
|
818
|
-
},
|
|
819
|
-
})
|
|
820
|
-
|
|
821
|
-
if (response.error) {
|
|
822
|
-
throw new Error(`Get schedule facts failed: ${JSON.stringify(response.error)}`)
|
|
823
|
-
}
|
|
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
|
-
}
|
|
834
|
-
|
|
835
|
-
/**
|
|
836
|
-
* Get close status for all schedules in a fiscal period.
|
|
837
|
-
*/
|
|
838
|
-
async getPeriodCloseStatus(
|
|
839
|
-
graphId: string,
|
|
840
|
-
periodStart: string,
|
|
841
|
-
periodEnd: string
|
|
842
|
-
): Promise<PeriodCloseStatus> {
|
|
843
|
-
const response = await getPeriodCloseStatus({
|
|
844
|
-
path: { graph_id: graphId },
|
|
845
|
-
query: { period_start: periodStart, period_end: periodEnd },
|
|
846
|
-
})
|
|
847
|
-
|
|
848
|
-
if (response.error) {
|
|
849
|
-
throw new Error(`Get period close status failed: ${JSON.stringify(response.error)}`)
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
const data = response.data as PeriodCloseStatusResponse
|
|
853
|
-
return {
|
|
854
|
-
fiscalPeriodStart: data.fiscal_period_start,
|
|
855
|
-
fiscalPeriodEnd: data.fiscal_period_end,
|
|
856
|
-
periodStatus: data.period_status,
|
|
857
|
-
schedules: (data.schedules ?? []).map((s: PeriodCloseItemResponse) => ({
|
|
858
|
-
structureId: s.structure_id,
|
|
859
|
-
structureName: s.structure_name,
|
|
860
|
-
amount: s.amount,
|
|
861
|
-
status: s.status,
|
|
862
|
-
entryId: s.entry_id ?? null,
|
|
863
|
-
})),
|
|
864
|
-
totalDraft: data.total_draft,
|
|
865
|
-
totalPosted: data.total_posted,
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
/**
|
|
870
|
-
* Idempotently create (or refresh) a draft closing entry from a schedule's
|
|
871
|
-
* facts for a period. The `outcome` field describes what actually happened:
|
|
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
|
|
878
|
-
*/
|
|
879
|
-
async createClosingEntry(
|
|
880
|
-
graphId: string,
|
|
881
|
-
structureId: string,
|
|
882
|
-
postingDate: string,
|
|
883
|
-
periodStart: string,
|
|
884
|
-
periodEnd: string,
|
|
885
|
-
memo?: string
|
|
886
|
-
): Promise<ClosingEntry> {
|
|
887
|
-
const body: CreateClosingEntryRequest = {
|
|
888
|
-
posting_date: postingDate,
|
|
889
|
-
period_start: periodStart,
|
|
890
|
-
period_end: periodEnd,
|
|
891
|
-
memo: memo ?? undefined,
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
const response = await createClosingEntry({
|
|
895
|
-
path: { graph_id: graphId, structure_id: structureId },
|
|
896
|
-
body,
|
|
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)
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
// ── Closing Book ─────────────────────────────────────────────────────
|
|
908
|
-
|
|
909
|
-
/**
|
|
910
|
-
* Get all closing book structure categories for the sidebar.
|
|
911
|
-
* Returns statements, account rollups, schedules, trial balance,
|
|
912
|
-
* and period close grouped into categories.
|
|
913
|
-
*/
|
|
914
|
-
async getClosingBookStructures(graphId: string): Promise<ClosingBookStructuresResponse> {
|
|
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(
|
|
931
|
-
graphId: string,
|
|
932
|
-
options?: { mappingId?: string; startDate?: string; endDate?: string }
|
|
933
|
-
): Promise<AccountRollupsResponse> {
|
|
934
|
-
const response = await getAccountRollups({
|
|
935
|
-
path: { graph_id: graphId },
|
|
936
|
-
query: {
|
|
937
|
-
mapping_id: options?.mappingId,
|
|
938
|
-
start_date: options?.startDate,
|
|
939
|
-
end_date: options?.endDate,
|
|
940
|
-
},
|
|
941
|
-
})
|
|
942
|
-
|
|
943
|
-
if (response.error) {
|
|
944
|
-
throw new Error(`Get account rollups failed: ${JSON.stringify(response.error)}`)
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
return response.data as AccountRollupsResponse
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
// ── Fiscal Calendar ─────────────────────────────────────────────────
|
|
951
|
-
|
|
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
|
-
*/
|
|
957
|
-
async initializeLedger(
|
|
958
|
-
graphId: string,
|
|
959
|
-
options?: InitializeLedgerOptions
|
|
960
|
-
): Promise<InitializeLedgerResult> {
|
|
961
|
-
const body: InitializeLedgerRequest = {
|
|
962
|
-
closed_through: options?.closedThrough ?? null,
|
|
963
|
-
fiscal_year_start_month: options?.fiscalYearStartMonth,
|
|
964
|
-
earliest_data_period: options?.earliestDataPeriod ?? null,
|
|
965
|
-
auto_seed_schedules: options?.autoSeedSchedules,
|
|
966
|
-
note: options?.note ?? null,
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
const response = await initializeLedger({
|
|
970
|
-
path: { graph_id: graphId },
|
|
971
|
-
body,
|
|
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
|
|
979
|
-
return {
|
|
980
|
-
fiscalCalendar: toFiscalCalendarState(data.fiscal_calendar),
|
|
981
|
-
periodsCreated: data.periods_created ?? 0,
|
|
982
|
-
warnings: data.warnings ?? [],
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
|
|
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
|
-
*/
|
|
1005
|
-
async setCloseTarget(
|
|
1006
|
-
graphId: string,
|
|
1007
|
-
period: string,
|
|
1008
|
-
note?: string | null
|
|
1009
|
-
): Promise<FiscalCalendarState> {
|
|
1010
|
-
const body: SetCloseTargetRequest = {
|
|
1011
|
-
period,
|
|
1012
|
-
note: note ?? null,
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
const response = await setCloseTarget({
|
|
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)
|
|
1025
|
-
}
|
|
1026
|
-
|
|
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
|
-
*/
|
|
1034
|
-
async closePeriod(
|
|
1035
|
-
graphId: string,
|
|
1036
|
-
period: string,
|
|
1037
|
-
options?: ClosePeriodOptions
|
|
1038
|
-
): Promise<ClosePeriodResult> {
|
|
1039
|
-
const body: ClosePeriodRequest = {
|
|
1040
|
-
note: options?.note ?? null,
|
|
1041
|
-
allow_stale_sync: options?.allowStaleSync,
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
const response = await closeFiscalPeriod({
|
|
1045
|
-
path: { graph_id: graphId, period },
|
|
1046
|
-
body,
|
|
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
|
|
1054
|
-
return {
|
|
1055
|
-
period: data.period,
|
|
1056
|
-
entriesPosted: data.entries_posted ?? 0,
|
|
1057
|
-
targetAutoAdvanced: data.target_auto_advanced ?? false,
|
|
1058
|
-
fiscalCalendar: toFiscalCalendarState(data.fiscal_calendar),
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
|
|
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
|
-
*/
|
|
1067
|
-
async reopenPeriod(
|
|
1068
|
-
graphId: string,
|
|
1069
|
-
period: string,
|
|
1070
|
-
reason: string,
|
|
1071
|
-
note?: string | null
|
|
1072
|
-
): Promise<FiscalCalendarState> {
|
|
1073
|
-
const body: ReopenPeriodRequest = {
|
|
1074
|
-
reason,
|
|
1075
|
-
note: note ?? null,
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
const response = await reopenFiscalPeriod({
|
|
1079
|
-
path: { graph_id: graphId, period },
|
|
1080
|
-
body,
|
|
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)
|
|
1088
|
-
}
|
|
1089
|
-
|
|
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
|
-
})
|
|
1100
|
-
|
|
1101
|
-
if (response.error) {
|
|
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 ──────────────────────────────────────────────
|
|
1139
|
-
|
|
1140
|
-
/**
|
|
1141
|
-
* Truncate a schedule — end it early by deleting facts with
|
|
1142
|
-
* `period_start > new_end_date`, along with any stale draft entries they
|
|
1143
|
-
* produced. Historical posted facts are preserved.
|
|
1144
|
-
*
|
|
1145
|
-
* `new_end_date` must be a month-end date (service enforces this).
|
|
1146
|
-
*/
|
|
1147
|
-
async truncateSchedule(
|
|
1148
|
-
graphId: string,
|
|
1149
|
-
structureId: string,
|
|
1150
|
-
options: TruncateScheduleOptions
|
|
1151
|
-
): Promise<TruncateScheduleResult> {
|
|
1152
|
-
const body: TruncateScheduleRequest = {
|
|
1153
|
-
new_end_date: options.newEndDate,
|
|
1154
|
-
reason: options.reason,
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
const response = await truncateSchedule({
|
|
1158
|
-
path: { graph_id: graphId, structure_id: structureId },
|
|
1159
|
-
body,
|
|
1160
|
-
})
|
|
1161
|
-
|
|
1162
|
-
if (response.error) {
|
|
1163
|
-
throw new Error(`Truncate schedule failed: ${JSON.stringify(response.error)}`)
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
const data = response.data as TruncateScheduleResponse
|
|
1167
|
-
return {
|
|
1168
|
-
structureId: data.structure_id,
|
|
1169
|
-
newEndDate: data.new_end_date,
|
|
1170
|
-
factsDeleted: data.facts_deleted,
|
|
1171
|
-
reason: data.reason,
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
/**
|
|
1176
|
-
* Create a manual draft closing entry with arbitrary balanced line items.
|
|
1177
|
-
* Not tied to a schedule — used for disposals, adjustments, and other
|
|
1178
|
-
* one-off closing events.
|
|
1179
|
-
*
|
|
1180
|
-
* Line items must sum to balanced debits/credits. Rejects entries
|
|
1181
|
-
* targeting an already-closed period.
|
|
1182
|
-
*/
|
|
1183
|
-
async createManualClosingEntry(
|
|
1184
|
-
graphId: string,
|
|
1185
|
-
options: CreateManualClosingEntryOptions
|
|
1186
|
-
): Promise<ClosingEntry> {
|
|
1187
|
-
const body: CreateManualClosingEntryRequest = {
|
|
1188
|
-
posting_date: options.postingDate,
|
|
1189
|
-
memo: options.memo,
|
|
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
|
-
})),
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
const response = await createManualClosingEntry({
|
|
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)}`)
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
return toClosingEntry(response.data as ClosingEntryResponse)
|
|
1209
|
-
}
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
// ── Internal helpers ──────────────────────────────────────────────────
|
|
1213
|
-
|
|
1214
|
-
function toClosingEntry(data: ClosingEntryResponse): ClosingEntry {
|
|
1215
|
-
return {
|
|
1216
|
-
outcome: data.outcome as ClosingEntryOutcome,
|
|
1217
|
-
entryId: data.entry_id ?? null,
|
|
1218
|
-
status: data.status ?? null,
|
|
1219
|
-
postingDate: data.posting_date ?? null,
|
|
1220
|
-
memo: data.memo ?? null,
|
|
1221
|
-
debitElementId: data.debit_element_id ?? null,
|
|
1222
|
-
creditElementId: data.credit_element_id ?? null,
|
|
1223
|
-
amount: data.amount ?? null,
|
|
1224
|
-
reason: data.reason ?? null,
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
function toFiscalCalendarState(data: FiscalCalendarResponse): FiscalCalendarState {
|
|
1229
|
-
return {
|
|
1230
|
-
graphId: data.graph_id,
|
|
1231
|
-
fiscalYearStartMonth: data.fiscal_year_start_month,
|
|
1232
|
-
closedThrough: data.closed_through ?? null,
|
|
1233
|
-
closeTarget: data.close_target ?? null,
|
|
1234
|
-
gapPeriods: data.gap_periods ?? 0,
|
|
1235
|
-
catchUpSequence: data.catch_up_sequence ?? [],
|
|
1236
|
-
closeableNow: data.closeable_now ?? false,
|
|
1237
|
-
blockers: data.blockers ?? [],
|
|
1238
|
-
lastCloseAt: data.last_close_at ?? null,
|
|
1239
|
-
initializedAt: data.initialized_at ?? null,
|
|
1240
|
-
lastSyncAt: data.last_sync_at ?? null,
|
|
1241
|
-
periods: (data.periods ?? []).map((p) => ({
|
|
1242
|
-
name: p.name,
|
|
1243
|
-
startDate: p.start_date,
|
|
1244
|
-
endDate: p.end_date,
|
|
1245
|
-
status: p.status,
|
|
1246
|
-
closedAt: p.closed_at ?? null,
|
|
1247
|
-
})),
|
|
1248
|
-
}
|
|
1249
|
-
}
|