@powerhousedao/contributor-billing 0.1.53 → 1.0.0-dev.10
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/dist/document-models/account-transactions/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/account-transactions/gen/schema/zod.js +3 -3
- package/dist/document-models/account-transactions/module.d.ts +1 -1
- package/dist/document-models/account-transactions/module.d.ts.map +1 -1
- package/dist/document-models/account-transactions/module.js +1 -1
- package/dist/document-models/accounts/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/accounts/module.d.ts +1 -1
- package/dist/document-models/accounts/module.d.ts.map +1 -1
- package/dist/document-models/accounts/module.js +1 -1
- package/dist/document-models/billing-statement/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/billing-statement/gen/schema/zod.js +4 -4
- package/dist/document-models/billing-statement/module.d.ts +1 -1
- package/dist/document-models/billing-statement/module.d.ts.map +1 -1
- package/dist/document-models/billing-statement/module.js +1 -1
- package/dist/document-models/expense-report/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/expense-report/gen/schema/zod.js +38 -18
- package/dist/document-models/expense-report/module.d.ts +1 -1
- package/dist/document-models/expense-report/module.d.ts.map +1 -1
- package/dist/document-models/expense-report/module.js +1 -1
- package/dist/document-models/invoice/gen/document-model.d.ts.map +1 -1
- package/dist/document-models/invoice/gen/document-model.js +150 -150
- package/dist/document-models/invoice/gen/schema/types.d.ts +3 -6
- package/dist/document-models/invoice/gen/schema/types.d.ts.map +1 -1
- package/dist/document-models/invoice/gen/schema/zod.d.ts +2 -8
- package/dist/document-models/invoice/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/invoice/gen/schema/zod.js +14 -25
- package/dist/document-models/invoice/module.d.ts +1 -1
- package/dist/document-models/invoice/module.d.ts.map +1 -1
- package/dist/document-models/invoice/module.js +1 -1
- package/dist/document-models/invoice/src/reducers/general.d.ts.map +1 -1
- package/dist/document-models/invoice/src/reducers/general.js +8 -0
- package/dist/document-models/invoice/src/reducers/items.d.ts.map +1 -1
- package/dist/document-models/invoice/src/reducers/items.js +2 -1
- package/dist/document-models/invoice/src/reducers/parties.d.ts.map +1 -1
- package/dist/document-models/invoice/src/reducers/parties.js +6 -2
- package/dist/document-models/invoice/src/reducers/transitions.d.ts +0 -5
- package/dist/document-models/invoice/src/reducers/transitions.d.ts.map +1 -1
- package/dist/document-models/invoice/src/reducers/transitions.js +19 -6
- package/dist/document-models/invoice/tests/general.test.js +11 -2
- package/dist/document-models/invoice/tests/items.test.js +1 -1
- package/dist/document-models/invoice/tests/parties.test.js +1 -1
- package/dist/document-models/invoice/tests/transitions.test.js +7 -2
- package/dist/document-models/operational-hub-profile/module.d.ts +1 -1
- package/dist/document-models/operational-hub-profile/module.d.ts.map +1 -1
- package/dist/document-models/operational-hub-profile/module.js +1 -1
- package/dist/document-models/snapshot-report/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/snapshot-report/gen/schema/zod.js +12 -12
- package/dist/document-models/snapshot-report/module.d.ts +1 -1
- package/dist/document-models/snapshot-report/module.d.ts.map +1 -1
- package/dist/document-models/snapshot-report/module.js +1 -1
- package/dist/editors/accounts-editor/editor.d.ts.map +1 -1
- package/dist/editors/accounts-editor/editor.js +2 -2
- package/dist/editors/builder-team-admin/components/DriveExplorer.d.ts.map +1 -1
- package/dist/editors/builder-team-admin/components/DriveExplorer.js +64 -4
- package/dist/editors/builder-team-admin/module.js +1 -1
- package/dist/editors/contributor-billing/components/DashboardHome.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/DashboardHome.js +2 -8
- package/dist/editors/contributor-billing/components/DocumentDropZone.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/DocumentDropZone.js +37 -8
- package/dist/editors/contributor-billing/components/DriveContents.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/DriveContents.js +4 -1
- package/dist/editors/contributor-billing/components/DriveExplorer.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/DriveExplorer.js +54 -3
- package/dist/editors/contributor-billing/components/FolderTree.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/FolderTree.js +6 -15
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts +2 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.js +41 -6
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.js +16 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.d.ts +3 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.js +13 -11
- package/dist/editors/contributor-billing/components/MonthReportCard.d.ts +11 -4
- package/dist/editors/contributor-billing/components/MonthReportCard.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/MonthReportCard.js +55 -6
- package/dist/editors/contributor-billing/components/MonthlyReportsOverview.d.ts +1 -1
- package/dist/editors/contributor-billing/components/MonthlyReportsOverview.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/MonthlyReportsOverview.js +104 -7
- package/dist/editors/contributor-billing/components/ReportingView.d.ts +0 -3
- package/dist/editors/contributor-billing/components/ReportingView.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/ReportingView.js +65 -8
- package/dist/editors/contributor-billing/components/ToastRenderer.d.ts +2 -0
- package/dist/editors/contributor-billing/components/ToastRenderer.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/ToastRenderer.js +14 -0
- package/dist/editors/contributor-billing/components/cbToast.d.ts +16 -0
- package/dist/editors/contributor-billing/components/cbToast.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/cbToast.js +29 -0
- package/dist/editors/contributor-billing/hooks/useDocumentAutoPlacement.d.ts.map +1 -1
- package/dist/editors/contributor-billing/hooks/useDocumentAutoPlacement.js +42 -2
- package/dist/editors/contributor-billing/hooks/useMonthlyReports.d.ts +4 -0
- package/dist/editors/contributor-billing/hooks/useMonthlyReports.d.ts.map +1 -1
- package/dist/editors/contributor-billing/hooks/useMonthlyReports.js +4 -0
- package/dist/editors/contributor-billing/module.js +1 -1
- package/dist/editors/invoice/InvoicePDF.d.ts.map +1 -1
- package/dist/editors/invoice/InvoicePDF.js +12 -9
- package/dist/editors/invoice/editor.d.ts.map +1 -1
- package/dist/editors/invoice/editor.js +6 -10
- package/dist/editors/invoice/exportUBL.d.ts.map +1 -1
- package/dist/editors/invoice/exportUBL.js +1 -2
- package/dist/editors/invoice/ingestPDF.js +1 -1
- package/dist/editors/invoice/invoiceToGnosis.d.ts.map +1 -1
- package/dist/editors/invoice/invoiceToGnosis.js +25 -22
- package/dist/editors/invoice/invoiceToast.d.ts +4 -0
- package/dist/editors/invoice/invoiceToast.d.ts.map +1 -0
- package/dist/editors/invoice/invoiceToast.js +6 -0
- package/dist/editors/invoice/legalEntity/legalEntity.d.ts +2 -1
- package/dist/editors/invoice/legalEntity/legalEntity.d.ts.map +1 -1
- package/dist/editors/invoice/legalEntity/legalEntity.js +3 -14
- package/dist/editors/invoice/legalEntity/walletSection.d.ts +1 -0
- package/dist/editors/invoice/legalEntity/walletSection.d.ts.map +1 -1
- package/dist/editors/invoice/legalEntity/walletSection.js +2 -2
- package/dist/editors/invoice/lineItems.js +1 -1
- package/dist/editors/invoice/requestFinance.d.ts +3 -2
- package/dist/editors/invoice/requestFinance.d.ts.map +1 -1
- package/dist/editors/invoice/requestFinance.js +38 -42
- package/dist/editors/invoice/validation/validationHandler.d.ts +1 -1
- package/dist/editors/invoice/validation/validationHandler.d.ts.map +1 -1
- package/dist/editors/invoice/validation/validationHandler.js +15 -2
- package/dist/editors/invoice/validation/validationManager.d.ts +1 -1
- package/dist/editors/invoice/validation/validationManager.d.ts.map +1 -1
- package/dist/editors/invoice/validation/validationManager.js +2 -1
- package/dist/editors/invoice/validation/validationRules.d.ts +1 -0
- package/dist/editors/invoice/validation/validationRules.d.ts.map +1 -1
- package/dist/editors/invoice/validation/validationRules.js +26 -1
- package/dist/editors/snapshot-report-editor/components/DateRangePicker.d.ts +19 -0
- package/dist/editors/snapshot-report-editor/components/DateRangePicker.d.ts.map +1 -0
- package/dist/editors/snapshot-report-editor/components/DateRangePicker.js +66 -0
- package/dist/editors/snapshot-report-editor/editor.d.ts.map +1 -1
- package/dist/editors/snapshot-report-editor/editor.js +72 -48
- package/dist/scripts/download-all-drive-documents/download-drive-documents.d.ts +33 -0
- package/dist/scripts/download-all-drive-documents/download-drive-documents.d.ts.map +1 -0
- package/dist/scripts/download-all-drive-documents/download-drive-documents.js +583 -0
- package/dist/scripts/invoice/requestFinance.d.ts +18 -1
- package/dist/scripts/invoice/requestFinance.d.ts.map +1 -1
- package/dist/scripts/invoice/requestFinance.js +17 -5
- package/dist/scripts/upload-phd-documents/upload-phd-documents.d.ts +20 -0
- package/dist/scripts/upload-phd-documents/upload-phd-documents.d.ts.map +1 -0
- package/dist/scripts/upload-phd-documents/upload-phd-documents.js +313 -0
- package/dist/style.css +201 -106
- package/dist/subgraphs/budget-statements/resolvers.d.ts +38 -0
- package/dist/subgraphs/budget-statements/resolvers.d.ts.map +1 -1
- package/dist/subgraphs/budget-statements/resolvers.js +192 -62
- package/dist/subgraphs/budget-statements/resolvers.test.d.ts +2 -0
- package/dist/subgraphs/budget-statements/resolvers.test.d.ts.map +1 -0
- package/dist/subgraphs/budget-statements/resolvers.test.js +339 -0
- package/dist/subgraphs/budget-statements/schema.d.ts.map +1 -1
- package/dist/subgraphs/budget-statements/schema.js +8 -0
- package/dist/subgraphs/index.d.ts +0 -1
- package/dist/subgraphs/index.d.ts.map +1 -1
- package/dist/subgraphs/index.js +0 -1
- package/dist/subgraphs/invoice-addon/customResolvers.d.ts +70 -11
- package/dist/subgraphs/invoice-addon/customResolvers.d.ts.map +1 -1
- package/dist/subgraphs/invoice-addon/customResolvers.js +12 -27
- package/package.json +35 -28
- package/dist/document-models/invoice/src/tests/document-model.test.d.ts +0 -10
- package/dist/document-models/invoice/src/tests/document-model.test.d.ts.map +0 -1
- package/dist/document-models/invoice/src/tests/document-model.test.js +0 -104
- package/dist/document-models/invoice/src/tests/general.test.d.ts +0 -6
- package/dist/document-models/invoice/src/tests/general.test.d.ts.map +0 -1
- package/dist/document-models/invoice/src/tests/general.test.js +0 -49
- package/dist/document-models/invoice/src/tests/items.test.d.ts +0 -6
- package/dist/document-models/invoice/src/tests/items.test.d.ts.map +0 -1
- package/dist/document-models/invoice/src/tests/items.test.js +0 -59
- package/dist/document-models/invoice/src/tests/parties.test.d.ts +0 -6
- package/dist/document-models/invoice/src/tests/parties.test.d.ts.map +0 -1
- package/dist/document-models/invoice/src/tests/parties.test.js +0 -69
- package/dist/document-models/invoice/src/tests/transitions.test.d.ts +0 -6
- package/dist/document-models/invoice/src/tests/transitions.test.d.ts.map +0 -1
- package/dist/document-models/invoice/src/tests/transitions.test.js +0 -59
- package/dist/document-models/invoice/utils/statusTransitions.d.ts +0 -13
- package/dist/document-models/invoice/utils/statusTransitions.d.ts.map +0 -1
- package/dist/document-models/invoice/utils/statusTransitions.js +0 -13
- package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.d.ts +0 -15
- package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.d.ts.map +0 -1
- package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.js +0 -61
- package/dist/editors/contributor-billing/components/CreateHubProfileModal.d.ts +0 -12
- package/dist/editors/contributor-billing/components/CreateHubProfileModal.d.ts.map +0 -1
- package/dist/editors/contributor-billing/components/CreateHubProfileModal.js +0 -74
- package/dist/subgraphs/resources-services/index.d.ts +0 -11
- package/dist/subgraphs/resources-services/index.d.ts.map +0 -1
- package/dist/subgraphs/resources-services/index.js +0 -11
- package/dist/subgraphs/resources-services/resolvers.d.ts +0 -3
- package/dist/subgraphs/resources-services/resolvers.d.ts.map +0 -1
- package/dist/subgraphs/resources-services/resolvers.js +0 -462
- package/dist/subgraphs/resources-services/schema.d.ts +0 -3
- package/dist/subgraphs/resources-services/schema.d.ts.map +0 -1
- package/dist/subgraphs/resources-services/schema.js +0 -284
|
@@ -1,38 +1,47 @@
|
|
|
1
1
|
import {} from "@powerhousedao/reactor-api";
|
|
2
|
+
// Helper to extract YYYY-MM-DD from an ISO date string without Date object
|
|
3
|
+
// to avoid timezone-dependent parsing
|
|
4
|
+
export const extractIsoDate = (dateStr) => {
|
|
5
|
+
const match = dateStr.match(/^(\d{4}-\d{2}-\d{2})/);
|
|
6
|
+
return match ? match[1] : null;
|
|
7
|
+
};
|
|
2
8
|
// Helper to create a period key from start and end dates
|
|
3
|
-
const getPeriodKey = (periodStart, periodEnd) => {
|
|
9
|
+
export const getPeriodKey = (periodStart, periodEnd) => {
|
|
4
10
|
if (!periodStart || !periodEnd)
|
|
5
11
|
return null;
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
if (isNaN(startDate.getTime()) || isNaN(endDate.getTime()))
|
|
12
|
+
const start = extractIsoDate(periodStart);
|
|
13
|
+
const end = extractIsoDate(periodEnd);
|
|
14
|
+
if (!start || !end)
|
|
10
15
|
return null;
|
|
11
|
-
|
|
12
|
-
return `${formatDate(startDate)}_${formatDate(endDate)}`;
|
|
16
|
+
return `${start}_${end}`;
|
|
13
17
|
};
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
const MONTHS = [
|
|
19
|
+
"JAN",
|
|
20
|
+
"FEB",
|
|
21
|
+
"MAR",
|
|
22
|
+
"APR",
|
|
23
|
+
"MAY",
|
|
24
|
+
"JUN",
|
|
25
|
+
"JUL",
|
|
26
|
+
"AUG",
|
|
27
|
+
"SEP",
|
|
28
|
+
"OCT",
|
|
29
|
+
"NOV",
|
|
30
|
+
"DEC",
|
|
31
|
+
];
|
|
32
|
+
// Helper to extract month key from an ISO date string (format: "SEP2025")
|
|
33
|
+
// Parses directly from the string to avoid timezone issues
|
|
34
|
+
export const getMonthKey = (dateStr) => {
|
|
16
35
|
if (!dateStr)
|
|
17
36
|
return null;
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
37
|
+
const match = dateStr.match(/^(\d{4})-(\d{2})/);
|
|
38
|
+
if (!match)
|
|
39
|
+
return null;
|
|
40
|
+
const year = match[1];
|
|
41
|
+
const monthIndex = parseInt(match[2], 10) - 1;
|
|
42
|
+
if (monthIndex < 0 || monthIndex > 11)
|
|
20
43
|
return null;
|
|
21
|
-
|
|
22
|
-
"JAN",
|
|
23
|
-
"FEB",
|
|
24
|
-
"MAR",
|
|
25
|
-
"APR",
|
|
26
|
-
"MAY",
|
|
27
|
-
"JUN",
|
|
28
|
-
"JUL",
|
|
29
|
-
"AUG",
|
|
30
|
-
"SEP",
|
|
31
|
-
"OCT",
|
|
32
|
-
"NOV",
|
|
33
|
-
"DEC",
|
|
34
|
-
];
|
|
35
|
-
return `${months[date.getMonth()]}${date.getFullYear()}`;
|
|
44
|
+
return `${MONTHS[monthIndex]}${year}`;
|
|
36
45
|
};
|
|
37
46
|
// Helper to sort budget statements by month (most recent first)
|
|
38
47
|
const sortByMonth = (a, b) => {
|
|
@@ -126,15 +135,24 @@ export const getResolvers = (subgraph) => {
|
|
|
126
135
|
const drivesToScan = drives;
|
|
127
136
|
for (const driveId of drivesToScan) {
|
|
128
137
|
const docsIds = await reactor.getDocuments(driveId);
|
|
129
|
-
const docs = await Promise.all(docsIds.map(async (docId) =>
|
|
138
|
+
const docs = await Promise.all(docsIds.map(async (docId) => {
|
|
139
|
+
try {
|
|
140
|
+
return await reactor.getDocument(docId);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
}));
|
|
130
146
|
for (const doc of docs) {
|
|
147
|
+
if (!doc)
|
|
148
|
+
continue;
|
|
131
149
|
const docType = doc.header.documentType;
|
|
132
150
|
if (docType === "powerhouse/snapshot-report") {
|
|
133
151
|
const snapshotDoc = doc;
|
|
134
152
|
const ownerId = snapshotDoc.state.global.ownerIds?.[0] ?? null;
|
|
135
|
-
//
|
|
136
|
-
|
|
137
|
-
|
|
153
|
+
// Don't filter snapshot reports by teamId here — snapshots are often
|
|
154
|
+
// owned by the operational hub, not individual teams. The opHub sharing
|
|
155
|
+
// mechanism (Step 4) will associate them with the correct teams later.
|
|
138
156
|
if (allowedBuilderPhids &&
|
|
139
157
|
ownerId &&
|
|
140
158
|
!allowedBuilderPhids.has(ownerId))
|
|
@@ -162,9 +180,50 @@ export const getResolvers = (subgraph) => {
|
|
|
162
180
|
}
|
|
163
181
|
}
|
|
164
182
|
}
|
|
165
|
-
// Step 2:
|
|
183
|
+
// Step 2: Resolve builder profiles and build opHub lookup
|
|
184
|
+
// We need this before grouping so snapshot reports can be shared across op hub members
|
|
185
|
+
const resolvedProfiles = new Map();
|
|
186
|
+
const builderToOpHub = new Map();
|
|
187
|
+
const resolveProfile = async (phid) => {
|
|
188
|
+
if (resolvedProfiles.has(phid))
|
|
189
|
+
return resolvedProfiles.get(phid);
|
|
190
|
+
let doc = builderProfileDocs.get(phid) || null;
|
|
191
|
+
if (!doc) {
|
|
192
|
+
try {
|
|
193
|
+
doc = await reactor.getDocument(phid);
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
// Profile may not exist
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const state = doc
|
|
200
|
+
? (doc.state
|
|
201
|
+
?.global ?? null)
|
|
202
|
+
: null;
|
|
203
|
+
resolvedProfiles.set(phid, state);
|
|
204
|
+
if (state?.operationalHubMember?.phid) {
|
|
205
|
+
builderToOpHub.set(phid, state.operationalHubMember.phid);
|
|
206
|
+
}
|
|
207
|
+
return state;
|
|
208
|
+
};
|
|
209
|
+
// Pre-resolve all builder profiles we'll need
|
|
210
|
+
const allOwnerIds = new Set();
|
|
211
|
+
for (const doc of snapshotReportDocs) {
|
|
212
|
+
const id = doc.state.global.ownerIds?.[0];
|
|
213
|
+
if (id)
|
|
214
|
+
allOwnerIds.add(id);
|
|
215
|
+
}
|
|
216
|
+
for (const doc of expenseReportDocs) {
|
|
217
|
+
const id = doc.state.global.ownerId;
|
|
218
|
+
if (id)
|
|
219
|
+
allOwnerIds.add(id);
|
|
220
|
+
}
|
|
221
|
+
await Promise.all(Array.from(allOwnerIds).map((id) => resolveProfile(id)));
|
|
222
|
+
// Step 3: Group reports by ownerId AND period
|
|
166
223
|
// Key format: "ownerId_periodStart_periodEnd"
|
|
167
224
|
const budgetStatementsByOwnerAndPeriod = new Map();
|
|
225
|
+
// Index snapshot reports by opHub + period so they can be shared
|
|
226
|
+
const snapshotByOpHub = new Map();
|
|
168
227
|
// Group snapshot reports
|
|
169
228
|
for (const snapshotDoc of snapshotReportDocs) {
|
|
170
229
|
const state = snapshotDoc.state.global;
|
|
@@ -185,6 +244,11 @@ export const getResolvers = (subgraph) => {
|
|
|
185
244
|
}
|
|
186
245
|
budgetStatementsByOwnerAndPeriod.get(key).snapshotReport =
|
|
187
246
|
snapshotDoc;
|
|
247
|
+
// Also index by opHub + period for sharing across subteams
|
|
248
|
+
const opHubPhid = builderToOpHub.get(ownerId);
|
|
249
|
+
if (opHubPhid) {
|
|
250
|
+
snapshotByOpHub.set(`${opHubPhid}_${periodKey}`, snapshotDoc);
|
|
251
|
+
}
|
|
188
252
|
}
|
|
189
253
|
// Group expense reports and match with snapshot reports
|
|
190
254
|
for (const expenseDoc of expenseReportDocs) {
|
|
@@ -206,25 +270,22 @@ export const getResolvers = (subgraph) => {
|
|
|
206
270
|
}
|
|
207
271
|
budgetStatementsByOwnerAndPeriod.get(key).expenseReport = expenseDoc;
|
|
208
272
|
}
|
|
209
|
-
// Step
|
|
273
|
+
// Step 4: Fill in missing snapshot reports from op hub siblings
|
|
274
|
+
for (const entry of budgetStatementsByOwnerAndPeriod.values()) {
|
|
275
|
+
if (entry.snapshotReport)
|
|
276
|
+
continue; // already has a direct match
|
|
277
|
+
const opHubPhid = builderToOpHub.get(entry.ownerId);
|
|
278
|
+
if (!opHubPhid)
|
|
279
|
+
continue;
|
|
280
|
+
const opHubSnapshot = snapshotByOpHub.get(`${opHubPhid}_${entry.periodKey}`);
|
|
281
|
+
if (opHubSnapshot) {
|
|
282
|
+
entry.snapshotReport = opHubSnapshot;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Step 5: Build the budget statements
|
|
210
286
|
const budgetStatements = [];
|
|
211
287
|
for (const [key, { ownerId, periodKey, snapshotReport, expenseReport },] of budgetStatementsByOwnerAndPeriod.entries()) {
|
|
212
|
-
|
|
213
|
-
let builderProfileDoc = builderProfileDocs.get(ownerId) || null;
|
|
214
|
-
// Try to fetch directly if not found
|
|
215
|
-
if (!builderProfileDoc) {
|
|
216
|
-
try {
|
|
217
|
-
builderProfileDoc =
|
|
218
|
-
await reactor.getDocument(ownerId);
|
|
219
|
-
}
|
|
220
|
-
catch {
|
|
221
|
-
// Ignore errors - profile may not exist
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
// Build owner object
|
|
225
|
-
const ownerState = builderProfileDoc
|
|
226
|
-
? (builderProfileDoc.state?.global ?? null)
|
|
227
|
-
: null;
|
|
288
|
+
const ownerState = resolvedProfiles.get(ownerId) ?? null;
|
|
228
289
|
const owner = {
|
|
229
290
|
id: ownerId,
|
|
230
291
|
name: ownerState?.name || "Unknown",
|
|
@@ -238,7 +299,7 @@ export const getResolvers = (subgraph) => {
|
|
|
238
299
|
const month = getMonthKey(periodStartDate) || periodKey;
|
|
239
300
|
// Build snapshot report data
|
|
240
301
|
const snapshotReportData = snapshotReport
|
|
241
|
-
? buildSnapshotReportData(snapshotReport
|
|
302
|
+
? buildSnapshotReportData(snapshotReport)
|
|
242
303
|
: {
|
|
243
304
|
startDate: "",
|
|
244
305
|
endDate: "",
|
|
@@ -257,19 +318,57 @@ export const getResolvers = (subgraph) => {
|
|
|
257
318
|
const status = expenseReport?.state.global.status || "DRAFT";
|
|
258
319
|
// Get lastModifiedAtUtcIso from the expense report document header
|
|
259
320
|
const lastModifiedAtUtcIso = expenseReport?.header.lastModifiedAtUtcIso || "";
|
|
321
|
+
// Get operational hub member from builder profile
|
|
322
|
+
const opHubMember = ownerState?.operationalHubMember ?? null;
|
|
323
|
+
const operationalHubMember = opHubMember?.phid || opHubMember?.name
|
|
324
|
+
? {
|
|
325
|
+
phid: opHubMember.phid || null,
|
|
326
|
+
name: opHubMember.name || null,
|
|
327
|
+
}
|
|
328
|
+
: null;
|
|
260
329
|
budgetStatements.push({
|
|
261
330
|
id: key,
|
|
262
331
|
owner,
|
|
332
|
+
operationalHubMember,
|
|
263
333
|
month,
|
|
264
334
|
status,
|
|
265
335
|
lastModifiedAtUtcIso,
|
|
336
|
+
reportedActuals: computeReportedActuals(expenseReportData),
|
|
337
|
+
netExpenseTxns: computeNetExpenseTxns(snapshotReportData),
|
|
266
338
|
snapshotReport: snapshotReportData,
|
|
267
339
|
expenseReport: expenseReportData,
|
|
268
340
|
});
|
|
269
341
|
}
|
|
342
|
+
// Aggregate reportedActuals by operational hub + month
|
|
343
|
+
// All builders in the same op hub for the same month share the same total
|
|
344
|
+
const opHubActuals = new Map();
|
|
345
|
+
for (const stmt of budgetStatements) {
|
|
346
|
+
const opHubPhid = stmt.operationalHubMember?.phid;
|
|
347
|
+
if (!opHubPhid)
|
|
348
|
+
continue;
|
|
349
|
+
const groupKey = `${opHubPhid}_${stmt.month}`;
|
|
350
|
+
const current = opHubActuals.get(groupKey) || 0;
|
|
351
|
+
opHubActuals.set(groupKey, current + (parseFloat(stmt.reportedActuals.value) || 0));
|
|
352
|
+
}
|
|
353
|
+
for (const stmt of budgetStatements) {
|
|
354
|
+
const opHubPhid = stmt.operationalHubMember?.phid;
|
|
355
|
+
if (!opHubPhid)
|
|
356
|
+
continue;
|
|
357
|
+
const groupKey = `${opHubPhid}_${stmt.month}`;
|
|
358
|
+
const total = opHubActuals.get(groupKey);
|
|
359
|
+
if (total !== undefined) {
|
|
360
|
+
stmt.reportedActuals = { unit: "USDS", value: String(total) };
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// When filtering by teamId, remove entries for other owners that were
|
|
364
|
+
// only collected because we don't filter snapshot reports by teamId
|
|
365
|
+
// (snapshots are often owned by the opHub, not individual teams).
|
|
366
|
+
const filteredStatements = teamId
|
|
367
|
+
? budgetStatements.filter((stmt) => stmt.owner.id === teamId)
|
|
368
|
+
: budgetStatements;
|
|
270
369
|
// Sort by month (most recent first)
|
|
271
|
-
|
|
272
|
-
return
|
|
370
|
+
filteredStatements.sort(sortByMonth);
|
|
371
|
+
return filteredStatements;
|
|
273
372
|
},
|
|
274
373
|
},
|
|
275
374
|
};
|
|
@@ -277,7 +376,7 @@ export const getResolvers = (subgraph) => {
|
|
|
277
376
|
/**
|
|
278
377
|
* Build snapshot report data from a SnapshotReportDocument
|
|
279
378
|
*/
|
|
280
|
-
function buildSnapshotReportData(doc
|
|
379
|
+
function buildSnapshotReportData(doc) {
|
|
281
380
|
const state = doc.state.global;
|
|
282
381
|
return {
|
|
283
382
|
startDate: state.reportPeriodStart || state.startDate || "",
|
|
@@ -304,7 +403,7 @@ function buildSnapshotReportData(doc, accountTransactionsDocs) {
|
|
|
304
403
|
datetime: tx.datetime,
|
|
305
404
|
txHash: tx.txHash,
|
|
306
405
|
counterParty: tx.counterParty || "",
|
|
307
|
-
counterPartyName: getCounterPartyName(tx.
|
|
406
|
+
counterPartyName: getCounterPartyName(tx.counterParty, state.snapshotAccounts),
|
|
308
407
|
amount: {
|
|
309
408
|
value: tx.amount,
|
|
310
409
|
unit: tx.token,
|
|
@@ -390,17 +489,48 @@ function buildExpenseReportData(doc) {
|
|
|
390
489
|
};
|
|
391
490
|
}
|
|
392
491
|
/**
|
|
393
|
-
* Get counter party name
|
|
492
|
+
* Get counter party name by matching the counter party address
|
|
493
|
+
* against snapshot account addresses.
|
|
394
494
|
*/
|
|
395
|
-
function getCounterPartyName(
|
|
396
|
-
if (!
|
|
495
|
+
function getCounterPartyName(counterPartyAddress, snapshotAccounts) {
|
|
496
|
+
if (!counterPartyAddress)
|
|
397
497
|
return "";
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
498
|
+
const account = snapshotAccounts.find((acc) => acc.accountAddress.toLowerCase() === counterPartyAddress.toLowerCase());
|
|
499
|
+
return account?.accountName || "";
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Sum of all line item actuals from expense report wallets
|
|
503
|
+
*/
|
|
504
|
+
export function computeReportedActuals(expenseReportData) {
|
|
505
|
+
let total = 0;
|
|
506
|
+
for (const wallet of expenseReportData.wallets) {
|
|
507
|
+
for (const item of wallet.lineItems) {
|
|
508
|
+
total += parseFloat(item.actuals.value) || 0;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return { unit: "USDS", value: String(total) };
|
|
512
|
+
}
|
|
513
|
+
// USD stablecoins to include in net expense calculation
|
|
514
|
+
const USD_STABLECOINS = new Set(["USDS", "USDC", "DAI"]);
|
|
515
|
+
/**
|
|
516
|
+
* Sum of outbound USD stablecoin transactions that leave the Internal wallet grouping.
|
|
517
|
+
* Excludes Swap (token conversion) and Internal (inter-wallet transfers) flowTypes.
|
|
518
|
+
* Only counts USDS, USDC, and DAI — excludes sUSDS, EURe, SKY, MKR, etc.
|
|
519
|
+
*/
|
|
520
|
+
export function computeNetExpenseTxns(snapshotReportData) {
|
|
521
|
+
let total = 0;
|
|
522
|
+
for (const account of snapshotReportData.accounts) {
|
|
523
|
+
if (account.type !== "Internal")
|
|
524
|
+
continue;
|
|
525
|
+
for (const tx of account.transactions) {
|
|
526
|
+
if (tx.direction !== "OUTFLOW")
|
|
527
|
+
continue;
|
|
528
|
+
if (tx.flowType === "Swap" || tx.flowType === "Internal")
|
|
529
|
+
continue;
|
|
530
|
+
if (!USD_STABLECOINS.has(tx.amount.unit))
|
|
531
|
+
continue;
|
|
532
|
+
total += parseFloat(tx.amount.value.value) || 0;
|
|
403
533
|
}
|
|
404
534
|
}
|
|
405
|
-
return "";
|
|
535
|
+
return { unit: "USDS", value: String(total) };
|
|
406
536
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolvers.test.d.ts","sourceRoot":"","sources":["../../../subgraphs/budget-statements/resolvers.test.ts"],"names":[],"mappings":""}
|