@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.
Files changed (189) hide show
  1. package/dist/document-models/account-transactions/gen/schema/zod.d.ts.map +1 -1
  2. package/dist/document-models/account-transactions/gen/schema/zod.js +3 -3
  3. package/dist/document-models/account-transactions/module.d.ts +1 -1
  4. package/dist/document-models/account-transactions/module.d.ts.map +1 -1
  5. package/dist/document-models/account-transactions/module.js +1 -1
  6. package/dist/document-models/accounts/gen/schema/zod.d.ts.map +1 -1
  7. package/dist/document-models/accounts/module.d.ts +1 -1
  8. package/dist/document-models/accounts/module.d.ts.map +1 -1
  9. package/dist/document-models/accounts/module.js +1 -1
  10. package/dist/document-models/billing-statement/gen/schema/zod.d.ts.map +1 -1
  11. package/dist/document-models/billing-statement/gen/schema/zod.js +4 -4
  12. package/dist/document-models/billing-statement/module.d.ts +1 -1
  13. package/dist/document-models/billing-statement/module.d.ts.map +1 -1
  14. package/dist/document-models/billing-statement/module.js +1 -1
  15. package/dist/document-models/expense-report/gen/schema/zod.d.ts.map +1 -1
  16. package/dist/document-models/expense-report/gen/schema/zod.js +38 -18
  17. package/dist/document-models/expense-report/module.d.ts +1 -1
  18. package/dist/document-models/expense-report/module.d.ts.map +1 -1
  19. package/dist/document-models/expense-report/module.js +1 -1
  20. package/dist/document-models/invoice/gen/document-model.d.ts.map +1 -1
  21. package/dist/document-models/invoice/gen/document-model.js +150 -150
  22. package/dist/document-models/invoice/gen/schema/types.d.ts +3 -6
  23. package/dist/document-models/invoice/gen/schema/types.d.ts.map +1 -1
  24. package/dist/document-models/invoice/gen/schema/zod.d.ts +2 -8
  25. package/dist/document-models/invoice/gen/schema/zod.d.ts.map +1 -1
  26. package/dist/document-models/invoice/gen/schema/zod.js +14 -25
  27. package/dist/document-models/invoice/module.d.ts +1 -1
  28. package/dist/document-models/invoice/module.d.ts.map +1 -1
  29. package/dist/document-models/invoice/module.js +1 -1
  30. package/dist/document-models/invoice/src/reducers/general.d.ts.map +1 -1
  31. package/dist/document-models/invoice/src/reducers/general.js +8 -0
  32. package/dist/document-models/invoice/src/reducers/items.d.ts.map +1 -1
  33. package/dist/document-models/invoice/src/reducers/items.js +2 -1
  34. package/dist/document-models/invoice/src/reducers/parties.d.ts.map +1 -1
  35. package/dist/document-models/invoice/src/reducers/parties.js +6 -2
  36. package/dist/document-models/invoice/src/reducers/transitions.d.ts +0 -5
  37. package/dist/document-models/invoice/src/reducers/transitions.d.ts.map +1 -1
  38. package/dist/document-models/invoice/src/reducers/transitions.js +19 -6
  39. package/dist/document-models/invoice/tests/general.test.js +11 -2
  40. package/dist/document-models/invoice/tests/items.test.js +1 -1
  41. package/dist/document-models/invoice/tests/parties.test.js +1 -1
  42. package/dist/document-models/invoice/tests/transitions.test.js +7 -2
  43. package/dist/document-models/operational-hub-profile/module.d.ts +1 -1
  44. package/dist/document-models/operational-hub-profile/module.d.ts.map +1 -1
  45. package/dist/document-models/operational-hub-profile/module.js +1 -1
  46. package/dist/document-models/snapshot-report/gen/schema/zod.d.ts.map +1 -1
  47. package/dist/document-models/snapshot-report/gen/schema/zod.js +12 -12
  48. package/dist/document-models/snapshot-report/module.d.ts +1 -1
  49. package/dist/document-models/snapshot-report/module.d.ts.map +1 -1
  50. package/dist/document-models/snapshot-report/module.js +1 -1
  51. package/dist/editors/accounts-editor/editor.d.ts.map +1 -1
  52. package/dist/editors/accounts-editor/editor.js +2 -2
  53. package/dist/editors/builder-team-admin/components/DriveExplorer.d.ts.map +1 -1
  54. package/dist/editors/builder-team-admin/components/DriveExplorer.js +64 -4
  55. package/dist/editors/builder-team-admin/module.js +1 -1
  56. package/dist/editors/contributor-billing/components/DashboardHome.d.ts.map +1 -1
  57. package/dist/editors/contributor-billing/components/DashboardHome.js +2 -8
  58. package/dist/editors/contributor-billing/components/DocumentDropZone.d.ts.map +1 -1
  59. package/dist/editors/contributor-billing/components/DocumentDropZone.js +37 -8
  60. package/dist/editors/contributor-billing/components/DriveContents.d.ts.map +1 -1
  61. package/dist/editors/contributor-billing/components/DriveContents.js +4 -1
  62. package/dist/editors/contributor-billing/components/DriveExplorer.d.ts.map +1 -1
  63. package/dist/editors/contributor-billing/components/DriveExplorer.js +54 -3
  64. package/dist/editors/contributor-billing/components/FolderTree.d.ts.map +1 -1
  65. package/dist/editors/contributor-billing/components/FolderTree.js +6 -15
  66. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts +2 -1
  67. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts.map +1 -1
  68. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.js +41 -6
  69. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts +1 -1
  70. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts.map +1 -1
  71. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.js +16 -1
  72. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.d.ts +3 -1
  73. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.d.ts.map +1 -1
  74. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.js +13 -11
  75. package/dist/editors/contributor-billing/components/MonthReportCard.d.ts +11 -4
  76. package/dist/editors/contributor-billing/components/MonthReportCard.d.ts.map +1 -1
  77. package/dist/editors/contributor-billing/components/MonthReportCard.js +55 -6
  78. package/dist/editors/contributor-billing/components/MonthlyReportsOverview.d.ts +1 -1
  79. package/dist/editors/contributor-billing/components/MonthlyReportsOverview.d.ts.map +1 -1
  80. package/dist/editors/contributor-billing/components/MonthlyReportsOverview.js +104 -7
  81. package/dist/editors/contributor-billing/components/ReportingView.d.ts +0 -3
  82. package/dist/editors/contributor-billing/components/ReportingView.d.ts.map +1 -1
  83. package/dist/editors/contributor-billing/components/ReportingView.js +65 -8
  84. package/dist/editors/contributor-billing/components/ToastRenderer.d.ts +2 -0
  85. package/dist/editors/contributor-billing/components/ToastRenderer.d.ts.map +1 -0
  86. package/dist/editors/contributor-billing/components/ToastRenderer.js +14 -0
  87. package/dist/editors/contributor-billing/components/cbToast.d.ts +16 -0
  88. package/dist/editors/contributor-billing/components/cbToast.d.ts.map +1 -0
  89. package/dist/editors/contributor-billing/components/cbToast.js +29 -0
  90. package/dist/editors/contributor-billing/hooks/useDocumentAutoPlacement.d.ts.map +1 -1
  91. package/dist/editors/contributor-billing/hooks/useDocumentAutoPlacement.js +42 -2
  92. package/dist/editors/contributor-billing/hooks/useMonthlyReports.d.ts +4 -0
  93. package/dist/editors/contributor-billing/hooks/useMonthlyReports.d.ts.map +1 -1
  94. package/dist/editors/contributor-billing/hooks/useMonthlyReports.js +4 -0
  95. package/dist/editors/contributor-billing/module.js +1 -1
  96. package/dist/editors/invoice/InvoicePDF.d.ts.map +1 -1
  97. package/dist/editors/invoice/InvoicePDF.js +12 -9
  98. package/dist/editors/invoice/editor.d.ts.map +1 -1
  99. package/dist/editors/invoice/editor.js +6 -10
  100. package/dist/editors/invoice/exportUBL.d.ts.map +1 -1
  101. package/dist/editors/invoice/exportUBL.js +1 -2
  102. package/dist/editors/invoice/ingestPDF.js +1 -1
  103. package/dist/editors/invoice/invoiceToGnosis.d.ts.map +1 -1
  104. package/dist/editors/invoice/invoiceToGnosis.js +25 -22
  105. package/dist/editors/invoice/invoiceToast.d.ts +4 -0
  106. package/dist/editors/invoice/invoiceToast.d.ts.map +1 -0
  107. package/dist/editors/invoice/invoiceToast.js +6 -0
  108. package/dist/editors/invoice/legalEntity/legalEntity.d.ts +2 -1
  109. package/dist/editors/invoice/legalEntity/legalEntity.d.ts.map +1 -1
  110. package/dist/editors/invoice/legalEntity/legalEntity.js +3 -14
  111. package/dist/editors/invoice/legalEntity/walletSection.d.ts +1 -0
  112. package/dist/editors/invoice/legalEntity/walletSection.d.ts.map +1 -1
  113. package/dist/editors/invoice/legalEntity/walletSection.js +2 -2
  114. package/dist/editors/invoice/lineItems.js +1 -1
  115. package/dist/editors/invoice/requestFinance.d.ts +3 -2
  116. package/dist/editors/invoice/requestFinance.d.ts.map +1 -1
  117. package/dist/editors/invoice/requestFinance.js +38 -42
  118. package/dist/editors/invoice/validation/validationHandler.d.ts +1 -1
  119. package/dist/editors/invoice/validation/validationHandler.d.ts.map +1 -1
  120. package/dist/editors/invoice/validation/validationHandler.js +15 -2
  121. package/dist/editors/invoice/validation/validationManager.d.ts +1 -1
  122. package/dist/editors/invoice/validation/validationManager.d.ts.map +1 -1
  123. package/dist/editors/invoice/validation/validationManager.js +2 -1
  124. package/dist/editors/invoice/validation/validationRules.d.ts +1 -0
  125. package/dist/editors/invoice/validation/validationRules.d.ts.map +1 -1
  126. package/dist/editors/invoice/validation/validationRules.js +26 -1
  127. package/dist/editors/snapshot-report-editor/components/DateRangePicker.d.ts +19 -0
  128. package/dist/editors/snapshot-report-editor/components/DateRangePicker.d.ts.map +1 -0
  129. package/dist/editors/snapshot-report-editor/components/DateRangePicker.js +66 -0
  130. package/dist/editors/snapshot-report-editor/editor.d.ts.map +1 -1
  131. package/dist/editors/snapshot-report-editor/editor.js +72 -48
  132. package/dist/scripts/download-all-drive-documents/download-drive-documents.d.ts +33 -0
  133. package/dist/scripts/download-all-drive-documents/download-drive-documents.d.ts.map +1 -0
  134. package/dist/scripts/download-all-drive-documents/download-drive-documents.js +583 -0
  135. package/dist/scripts/invoice/requestFinance.d.ts +18 -1
  136. package/dist/scripts/invoice/requestFinance.d.ts.map +1 -1
  137. package/dist/scripts/invoice/requestFinance.js +17 -5
  138. package/dist/scripts/upload-phd-documents/upload-phd-documents.d.ts +20 -0
  139. package/dist/scripts/upload-phd-documents/upload-phd-documents.d.ts.map +1 -0
  140. package/dist/scripts/upload-phd-documents/upload-phd-documents.js +313 -0
  141. package/dist/style.css +201 -106
  142. package/dist/subgraphs/budget-statements/resolvers.d.ts +38 -0
  143. package/dist/subgraphs/budget-statements/resolvers.d.ts.map +1 -1
  144. package/dist/subgraphs/budget-statements/resolvers.js +192 -62
  145. package/dist/subgraphs/budget-statements/resolvers.test.d.ts +2 -0
  146. package/dist/subgraphs/budget-statements/resolvers.test.d.ts.map +1 -0
  147. package/dist/subgraphs/budget-statements/resolvers.test.js +339 -0
  148. package/dist/subgraphs/budget-statements/schema.d.ts.map +1 -1
  149. package/dist/subgraphs/budget-statements/schema.js +8 -0
  150. package/dist/subgraphs/index.d.ts +0 -1
  151. package/dist/subgraphs/index.d.ts.map +1 -1
  152. package/dist/subgraphs/index.js +0 -1
  153. package/dist/subgraphs/invoice-addon/customResolvers.d.ts +70 -11
  154. package/dist/subgraphs/invoice-addon/customResolvers.d.ts.map +1 -1
  155. package/dist/subgraphs/invoice-addon/customResolvers.js +12 -27
  156. package/package.json +35 -28
  157. package/dist/document-models/invoice/src/tests/document-model.test.d.ts +0 -10
  158. package/dist/document-models/invoice/src/tests/document-model.test.d.ts.map +0 -1
  159. package/dist/document-models/invoice/src/tests/document-model.test.js +0 -104
  160. package/dist/document-models/invoice/src/tests/general.test.d.ts +0 -6
  161. package/dist/document-models/invoice/src/tests/general.test.d.ts.map +0 -1
  162. package/dist/document-models/invoice/src/tests/general.test.js +0 -49
  163. package/dist/document-models/invoice/src/tests/items.test.d.ts +0 -6
  164. package/dist/document-models/invoice/src/tests/items.test.d.ts.map +0 -1
  165. package/dist/document-models/invoice/src/tests/items.test.js +0 -59
  166. package/dist/document-models/invoice/src/tests/parties.test.d.ts +0 -6
  167. package/dist/document-models/invoice/src/tests/parties.test.d.ts.map +0 -1
  168. package/dist/document-models/invoice/src/tests/parties.test.js +0 -69
  169. package/dist/document-models/invoice/src/tests/transitions.test.d.ts +0 -6
  170. package/dist/document-models/invoice/src/tests/transitions.test.d.ts.map +0 -1
  171. package/dist/document-models/invoice/src/tests/transitions.test.js +0 -59
  172. package/dist/document-models/invoice/utils/statusTransitions.d.ts +0 -13
  173. package/dist/document-models/invoice/utils/statusTransitions.d.ts.map +0 -1
  174. package/dist/document-models/invoice/utils/statusTransitions.js +0 -13
  175. package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.d.ts +0 -15
  176. package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.d.ts.map +0 -1
  177. package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.js +0 -61
  178. package/dist/editors/contributor-billing/components/CreateHubProfileModal.d.ts +0 -12
  179. package/dist/editors/contributor-billing/components/CreateHubProfileModal.d.ts.map +0 -1
  180. package/dist/editors/contributor-billing/components/CreateHubProfileModal.js +0 -74
  181. package/dist/subgraphs/resources-services/index.d.ts +0 -11
  182. package/dist/subgraphs/resources-services/index.d.ts.map +0 -1
  183. package/dist/subgraphs/resources-services/index.js +0 -11
  184. package/dist/subgraphs/resources-services/resolvers.d.ts +0 -3
  185. package/dist/subgraphs/resources-services/resolvers.d.ts.map +0 -1
  186. package/dist/subgraphs/resources-services/resolvers.js +0 -462
  187. package/dist/subgraphs/resources-services/schema.d.ts +0 -3
  188. package/dist/subgraphs/resources-services/schema.d.ts.map +0 -1
  189. 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
- // Normalize dates to YYYY-MM-DD format for consistent matching
7
- const startDate = new Date(periodStart);
8
- const endDate = new Date(periodEnd);
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
- const formatDate = (d) => d.toISOString().split("T")[0];
12
- return `${formatDate(startDate)}_${formatDate(endDate)}`;
16
+ return `${start}_${end}`;
13
17
  };
14
- // Helper to extract month key from date (format: "JAN2026")
15
- const getMonthKey = (dateStr) => {
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 date = new Date(dateStr);
19
- if (isNaN(date.getTime()))
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
- const months = [
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) => reactor.getDocument(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
- // Apply filters: teamId takes precedence, then networkSlug (via allowedBuilderPhids)
136
- if (teamId && ownerId !== teamId)
137
- continue;
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: Group reports by ownerId AND period
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 3: Build the budget statements
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
- // Get the builder profile for this owner
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, accountTransactionsDocs)
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
- budgetStatements.sort(sortByMonth);
272
- return budgetStatements;
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, accountTransactionsDocs) {
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.counterPartyAccountId, accountTransactionsDocs),
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 from account-transactions document
492
+ * Get counter party name by matching the counter party address
493
+ * against snapshot account addresses.
394
494
  */
395
- function getCounterPartyName(counterPartyAccountId, accountTransactionsDocs) {
396
- if (!counterPartyAccountId)
495
+ function getCounterPartyName(counterPartyAddress, snapshotAccounts) {
496
+ if (!counterPartyAddress)
397
497
  return "";
398
- // Search through all account-transactions docs to find the account name
399
- for (const txDoc of accountTransactionsDocs.values()) {
400
- const account = txDoc.state.global.account;
401
- if (account && account.id === counterPartyAccountId) {
402
- return account.name || "";
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=resolvers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolvers.test.d.ts","sourceRoot":"","sources":["../../../subgraphs/budget-statements/resolvers.test.ts"],"names":[],"mappings":""}