Skip to content

Commit eeeb87f

Browse files
feat: resolve sponsors to org accounts
1 parent 1afc314 commit eeeb87f

5 files changed

Lines changed: 114 additions & 71 deletions

File tree

‎src/extensions/endpoints/admin-sponsors/src/queries.ts‎

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ type SponsorshipEventRow = {
2929
date_created: string | Date;
3030
github_id: string;
3131
github_login: string | null;
32-
dashboard_user_id: string | null;
33-
dashboard_username: string | null;
32+
dashboard_account_id: string | null;
33+
dashboard_account_name: string | null;
3434
reason: SponsorshipReason;
3535
meta: string | AdditionMeta;
3636
};
@@ -40,8 +40,8 @@ export type ManualAdditionRow = {
4040
date_created: string | Date;
4141
github_id: string;
4242
github_login: string | null;
43-
dashboard_user_id: string | null;
44-
dashboard_username: string | null;
43+
dashboard_account_id: string | null;
44+
dashboard_account_name: string | null;
4545
added_by: string | null;
4646
amount: string | number;
4747
reason: 'one_time_sponsorship' | 'other';
@@ -58,8 +58,8 @@ type SponsorsChartRow = {
5858
export type SponsorAccountRow = {
5959
github_id: string;
6060
github_login: string | null;
61-
dashboard_user_id: string | null;
62-
dashboard_username: string | null;
61+
dashboard_account_id: string | null;
62+
dashboard_account_name: string | null;
6363
is_active: string | number;
6464
has_recurring: string | number;
6565
current_monthly_amount: string | number | null;
@@ -87,6 +87,9 @@ const activeSponsorSql = '(current_sponsors.github_id IS NOT NULL OR legacy_spon
8787
const sponsorLoginSql = 'COALESCE(current_sponsors.github_login, legacy_sponsors.github_login)';
8888
const sponsorMonthlyAmountSql = 'COALESCE(current_sponsors.monthly_amount, legacy_sponsors.monthly_amount)';
8989

90+
const dashboardAccountIdSql = 'COALESCE(directus_users.id, gp_orgs.id)';
91+
const dashboardAccountNameSql = 'COALESCE(directus_users.github_username, gp_orgs.name)';
92+
9093
const joinSponsors = (database: Knex, query: Knex.QueryBuilder) => query
9194
.leftJoin('sponsors as current_sponsors', 'current_sponsors.github_id', 'additions.github_id')
9295
.leftJoin('sponsors as legacy_sponsors', database.raw(`legacy_sponsors.github_id = CASE additions.github_id ${redirectCases} END`, redirectEntries.flatMap(([ source, target ]) => [ target, source ])));
@@ -110,7 +113,7 @@ export const applySearch = (query: Knex.QueryBuilder, search: string | undefined
110113
}
111114

112115
builder.orWhereRaw(`${sponsorLoginSql} LIKE ?`, [ value ])
113-
.orWhere('directus_users.github_username', 'like', value)
116+
.orWhereRaw(`${dashboardAccountNameSql} LIKE ?`, [ value ])
114117
.orWhereRaw(`${metadataGithubLoginSql} LIKE ?`, [ value ]);
115118
});
116119
};
@@ -129,7 +132,7 @@ export const applyManualSearch = (query: Knex.QueryBuilder, search: string | und
129132
}
130133

131134
builder.orWhereRaw(`${sponsorLoginSql} LIKE ?`, [ value ])
132-
.orWhere('dashboard_users.github_username', 'like', value)
135+
.orWhereRaw(`${dashboardAccountNameSql} LIKE ?`, [ value ])
133136
.orWhereRaw(`${additionGithubLoginSql()} LIKE ?`, [ value ])
134137
.orWhereRaw(`JSON_UNQUOTE(JSON_EXTRACT(additions.meta, '$.comment')) LIKE ?`, [ value ])
135138
.orWhereRaw(`${addedBySql} LIKE ?`, [ value ]);
@@ -160,8 +163,8 @@ export const normalizeSponsorshipEvent = (row: SponsorshipEventRow): Sponsorship
160163
date: new Date(row.date_created).toISOString(),
161164
githubId: row.github_id,
162165
githubLogin: row.github_login,
163-
dashboardUserId: row.dashboard_user_id,
164-
dashboardUsername: row.dashboard_username,
166+
dashboardAccountId: row.dashboard_account_id,
167+
dashboardAccountName: row.dashboard_account_name,
165168
reason: row.reason,
166169
manual: meta.manual === true,
167170
amountInDollars,
@@ -178,8 +181,8 @@ export const normalizeManualAddition = (row: ManualAdditionRow): ManualAddition
178181
date: new Date(row.date_created).toISOString(),
179182
githubId: row.github_id,
180183
githubLogin: row.github_login,
181-
dashboardUserId: row.dashboard_user_id,
182-
dashboardUsername: row.dashboard_username,
184+
dashboardAccountId: row.dashboard_account_id,
185+
dashboardAccountName: row.dashboard_account_name,
183186
addedBy: row.added_by,
184187
type: row.reason === 'one_time_sponsorship' ? 'payment' : 'other',
185188
credits: toNumber(row.amount),
@@ -206,8 +209,8 @@ export const fillChartPoints = (monthKeys: string[], rows: SponsorsChartRow[]):
206209
export const normalizeSponsorAccount = (row: SponsorAccountRow): SponsorAccount => ({
207210
githubId: row.github_id,
208211
githubLogin: row.github_login,
209-
dashboardUserId: row.dashboard_user_id,
210-
dashboardUsername: row.dashboard_username,
212+
dashboardAccountId: row.dashboard_account_id,
213+
dashboardAccountName: row.dashboard_account_name,
211214
status: toNumber(row.is_active) ? 'active' : toNumber(row.has_recurring) ? 'former' : 'one-time',
212215
currentMonthlyAmount: row.current_monthly_amount === null ? null : toNumber(row.current_monthly_amount),
213216
periodSponsorshipValue: toNumber(row.period_sponsorship_value),
@@ -305,7 +308,8 @@ export const getManualAdditions = async (database: Knex, query: ManualAdditionsQ
305308
const base = database('gp_credits_additions as additions')
306309
.whereIn('additions.reason', [ 'one_time_sponsorship', 'other' ])
307310
.whereRaw(`JSON_UNQUOTE(JSON_EXTRACT(additions.meta, '$.manual')) = 'true'`)
308-
.leftJoin('directus_users as dashboard_users', 'dashboard_users.external_identifier', 'additions.github_id')
311+
.leftJoin('directus_users', 'directus_users.external_identifier', 'additions.github_id')
312+
.leftJoin('gp_orgs', 'gp_orgs.github_id', 'additions.github_id')
309313
.leftJoin('directus_users as added_by_users', 'added_by_users.id', 'additions.user_updated');
310314

311315
joinSponsors(database, base);
@@ -318,7 +322,7 @@ export const getManualAdditions = async (database: Knex, query: ManualAdditionsQ
318322

319323
const sortExpressions: Record<ManualAdditionsQuery['sort'], string> = {
320324
date: 'additions.date_created',
321-
sponsor: `COALESCE(${sponsorLoginSql}, dashboard_users.github_username, ${additionGithubLoginSql()}, additions.github_id)`,
325+
sponsor: `COALESCE(${sponsorLoginSql}, ${dashboardAccountNameSql}, ${additionGithubLoginSql()}, additions.github_id)`,
322326
type: 'additions.reason',
323327
credits: 'additions.amount',
324328
addedBy: addedBySql,
@@ -330,9 +334,9 @@ export const getManualAdditions = async (database: Knex, query: ManualAdditionsQ
330334
'additions.id',
331335
'additions.date_created',
332336
'additions.github_id',
333-
database.raw(`COALESCE(${sponsorLoginSql}, dashboard_users.github_username, ${additionGithubLoginSql()}) AS github_login`),
334-
database.raw('dashboard_users.id AS dashboard_user_id'),
335-
database.raw('dashboard_users.github_username AS dashboard_username'),
337+
database.raw(`COALESCE(${sponsorLoginSql}, ${dashboardAccountNameSql}, ${additionGithubLoginSql()}) AS github_login`),
338+
database.raw(`${dashboardAccountIdSql} AS dashboard_account_id`),
339+
database.raw(`${dashboardAccountNameSql} AS dashboard_account_name`),
336340
database.raw(`${addedBySql} AS added_by`),
337341
'additions.amount',
338342
'additions.reason',
@@ -350,7 +354,8 @@ export const getManualAdditions = async (database: Knex, query: ManualAdditionsQ
350354
export const getSponsorshipEvents = async (database: Knex, range: SponsorsPeriodRange, query: EventsQuery): Promise<PageResult<SponsorshipEvent>> => {
351355
const valueSql = sponsorshipValueSql();
352356
const base = periodEventsQuery(database, range)
353-
.leftJoin('directus_users', 'directus_users.external_identifier', 'additions.github_id');
357+
.leftJoin('directus_users', 'directus_users.external_identifier', 'additions.github_id')
358+
.leftJoin('gp_orgs', 'gp_orgs.github_id', 'additions.github_id');
354359

355360
joinSponsors(database, base);
356361

@@ -362,7 +367,7 @@ export const getSponsorshipEvents = async (database: Knex, range: SponsorsPeriod
362367

363368
const sortExpressions: Record<EventsQuery['sort'], string> = {
364369
date: 'additions.date_created',
365-
sponsor: `COALESCE(${sponsorLoginSql}, directus_users.github_username, ${additionGithubLoginSql()}, additions.github_id)`,
370+
sponsor: `COALESCE(${sponsorLoginSql}, ${dashboardAccountNameSql}, ${additionGithubLoginSql()}, additions.github_id)`,
366371
type: 'additions.reason',
367372
sponsorshipValue: `(${valueSql})`,
368373
};
@@ -373,9 +378,9 @@ export const getSponsorshipEvents = async (database: Knex, range: SponsorsPeriod
373378
'additions.id',
374379
'additions.date_created',
375380
'additions.github_id',
376-
database.raw(`COALESCE(${sponsorLoginSql}, directus_users.github_username, ${additionGithubLoginSql()}) AS github_login`),
377-
database.raw('directus_users.id AS dashboard_user_id'),
378-
database.raw('directus_users.github_username AS dashboard_username'),
381+
database.raw(`COALESCE(${sponsorLoginSql}, ${dashboardAccountNameSql}, ${additionGithubLoginSql()}) AS github_login`),
382+
database.raw(`${dashboardAccountIdSql} AS dashboard_account_id`),
383+
database.raw(`${dashboardAccountNameSql} AS dashboard_account_name`),
379384
'additions.reason',
380385
'additions.meta',
381386
).orderByRaw(`${sortExpressions[query.sort]} ${query.direction}`).orderBy('additions.id', 'desc')
@@ -406,7 +411,8 @@ export const getSponsorAccounts = async (database: Knex, range: SponsorsPeriodRa
406411

407412
const base = database.from(periodAccounts.as('additions'))
408413
.leftJoin(recurringHistory.as('history'), 'history.github_id', 'additions.github_id')
409-
.leftJoin('directus_users', 'directus_users.external_identifier', 'additions.github_id');
414+
.leftJoin('directus_users', 'directus_users.external_identifier', 'additions.github_id')
415+
.leftJoin('gp_orgs', 'gp_orgs.github_id', 'additions.github_id');
410416

411417
joinSponsors(database, base);
412418
applySearch(base, query.search, 'additions.github_login');
@@ -424,11 +430,11 @@ export const getSponsorAccounts = async (database: Knex, range: SponsorsPeriodRa
424430
}
425431

426432
if (query.linked !== undefined) {
427-
base.whereRaw(`directus_users.id IS ${query.linked ? 'NOT ' : ''}NULL`);
433+
base.whereRaw(`${dashboardAccountIdSql} IS ${query.linked ? 'NOT ' : ''}NULL`);
428434
}
429435

430436
const sortExpressions: Record<AccountsQuery['sort'], string> = {
431-
sponsor: `COALESCE(${sponsorLoginSql}, directus_users.github_username, additions.github_login, additions.github_id)`,
437+
sponsor: `COALESCE(${sponsorLoginSql}, ${dashboardAccountNameSql}, additions.github_login, additions.github_id)`,
432438
status: `CASE
433439
WHEN ${activeSponsorSql} THEN 0
434440
WHEN COALESCE(history.has_recurring, 0) = 1 THEN 1
@@ -444,9 +450,9 @@ export const getSponsorAccounts = async (database: Knex, range: SponsorsPeriodRa
444450
base.clone().clearSelect().clearOrder().count({ total: 'additions.github_id' }).first(),
445451
base.clone().select(
446452
'additions.github_id',
447-
database.raw(`COALESCE(${sponsorLoginSql}, directus_users.github_username, additions.github_login) AS github_login`),
448-
database.raw('directus_users.id AS dashboard_user_id'),
449-
database.raw('directus_users.github_username AS dashboard_username'),
453+
database.raw(`COALESCE(${sponsorLoginSql}, ${dashboardAccountNameSql}, additions.github_login) AS github_login`),
454+
database.raw(`${dashboardAccountIdSql} AS dashboard_account_id`),
455+
database.raw(`${dashboardAccountNameSql} AS dashboard_account_name`),
450456
database.raw(`IF(${activeSponsorSql}, 1, 0) AS is_active`),
451457
database.raw('COALESCE(history.has_recurring, 0) AS has_recurring'),
452458
database.raw(`${sponsorMonthlyAmountSql} AS current_monthly_amount`),

‎src/extensions/endpoints/admin-sponsors/src/types.ts‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ export type SponsorshipEvent = {
5454
date: string;
5555
githubId: string;
5656
githubLogin: string | null;
57-
dashboardUserId: string | null;
58-
dashboardUsername: string | null;
57+
dashboardAccountId: string | null;
58+
dashboardAccountName: string | null;
5959
reason: SponsorshipReason;
6060
manual: boolean;
6161
amountInDollars: number;
@@ -68,8 +68,8 @@ export type ManualAddition = {
6868
date: string;
6969
githubId: string;
7070
githubLogin: string | null;
71-
dashboardUserId: string | null;
72-
dashboardUsername: string | null;
71+
dashboardAccountId: string | null;
72+
dashboardAccountName: string | null;
7373
addedBy: string | null;
7474
type: ManualAdditionType;
7575
credits: number;
@@ -80,8 +80,8 @@ export type ManualAddition = {
8080
export type SponsorAccount = {
8181
githubId: string;
8282
githubLogin: string | null;
83-
dashboardUserId: string | null;
84-
dashboardUsername: string | null;
83+
dashboardAccountId: string | null;
84+
dashboardAccountName: string | null;
8585
status: SponsorStatus;
8686
currentMonthlyAmount: number | null;
8787
periodSponsorshipValue: number;

‎src/extensions/endpoints/admin-sponsors/test/index.test.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ describe('/admin-sponsors endpoint', () => {
1212
where: sinon.stub(),
1313
whereIn: sinon.stub(),
1414
whereRaw: sinon.stub(),
15+
leftJoin: sinon.stub(),
1516
orderByRaw: sinon.stub(),
1617
offset: sinon.stub(),
1718
limit: sinon.stub(),
@@ -159,7 +160,8 @@ describe('/admin-sponsors endpoint', () => {
159160

160161
expect(response.status).to.equal(200);
161162
expect(stubs.whereRaw.calledWith('((current_sponsors.github_id IS NOT NULL OR legacy_sponsors.github_id IS NOT NULL) OR (NOT (current_sponsors.github_id IS NOT NULL OR legacy_sponsors.github_id IS NOT NULL) AND history.has_recurring = 1))')).to.equal(true);
162-
expect(stubs.whereRaw.calledWith('directus_users.id IS NOT NULL')).to.equal(true);
163+
expect(stubs.whereRaw.calledWith('COALESCE(directus_users.id, gp_orgs.id) IS NOT NULL')).to.equal(true);
164+
expect(stubs.leftJoin.calledWith('gp_orgs', 'gp_orgs.github_id', 'additions.github_id')).to.equal(true);
163165
expect(stubs.orderByRaw.firstCall.args[0]).to.include('CASE').and.to.match(/ desc$/);
164166
expect(stubs.offset.calledWith(10)).to.equal(true);
165167
expect(stubs.limit.calledWith(20)).to.equal(true);

‎src/extensions/endpoints/admin-sponsors/test/queries.test.ts‎

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe('sponsor query normalization', () => {
1717

1818
expect(builder.where.calledOnceWithExactly('additions.github_id', '6209808')).to.equal(true);
1919
expect(builder.orWhereRaw.calledWithExactly('COALESCE(current_sponsors.github_login, legacy_sponsors.github_login) LIKE ?', [ '%66716858%' ])).to.equal(true);
20-
expect(builder.orWhere.calledWithExactly('directus_users.github_username', 'like', '%66716858%')).to.equal(true);
20+
expect(builder.orWhereRaw.calledWithExactly('COALESCE(directus_users.github_username, gp_orgs.name) LIKE ?', [ '%66716858%' ])).to.equal(true);
2121
expect(builder.orWhereRaw.calledWithExactly(`NULLIF(JSON_UNQUOTE(JSON_EXTRACT(additions.meta, '$.githubLogin')), '') LIKE ?`, [ '%66716858%' ])).to.equal(true);
2222
});
2323

@@ -34,7 +34,7 @@ describe('sponsor query normalization', () => {
3434

3535
expect(builder.where.calledOnceWithExactly('additions.github_id', '6209808')).to.equal(true);
3636
expect(builder.orWhereRaw.calledWithExactly('COALESCE(current_sponsors.github_login, legacy_sponsors.github_login) LIKE ?', [ '%66716858%' ])).to.equal(true);
37-
expect(builder.orWhere.calledWithExactly('dashboard_users.github_username', 'like', '%66716858%')).to.equal(true);
37+
expect(builder.orWhereRaw.calledWithExactly('COALESCE(directus_users.github_username, gp_orgs.name) LIKE ?', [ '%66716858%' ])).to.equal(true);
3838
expect(builder.orWhereRaw.calledWithExactly(`NULLIF(JSON_UNQUOTE(JSON_EXTRACT(additions.meta, '$.githubLogin')), '') LIKE ?`, [ '%66716858%' ])).to.equal(true);
3939
});
4040

@@ -48,17 +48,17 @@ describe('sponsor query normalization', () => {
4848
date_created: '2026-07-15T10:00:00.000Z',
4949
github_id: '123',
5050
github_login: 'example',
51-
dashboard_user_id: 'user-id',
52-
dashboard_username: 'dashboard-example',
51+
dashboard_account_id: 'user-id',
52+
dashboard_account_name: 'dashboard-example',
5353
reason: 'recurring_sponsorship',
5454
meta: JSON.stringify({ amountInDollars: 150, monthsCovered: 6, bonus: 25, manual: true }),
5555
})).to.deep.equal({
5656
id: 10,
5757
date: '2026-07-15T10:00:00.000Z',
5858
githubId: '123',
5959
githubLogin: 'example',
60-
dashboardUserId: 'user-id',
61-
dashboardUsername: 'dashboard-example',
60+
dashboardAccountId: 'user-id',
61+
dashboardAccountName: 'dashboard-example',
6262
reason: 'recurring_sponsorship',
6363
manual: true,
6464
amountInDollars: 150,
@@ -73,17 +73,17 @@ describe('sponsor query normalization', () => {
7373
date_created: new Date('2026-07-16T10:00:00.000Z'),
7474
github_id: '456',
7575
github_login: null,
76-
dashboard_user_id: null,
77-
dashboard_username: null,
76+
dashboard_account_id: null,
77+
dashboard_account_name: null,
7878
reason: 'tier_changed',
7979
meta: { amountInDollars: 25, monthsCovered: 3 },
8080
})).to.deep.equal({
8181
id: 11,
8282
date: '2026-07-16T10:00:00.000Z',
8383
githubId: '456',
8484
githubLogin: null,
85-
dashboardUserId: null,
86-
dashboardUsername: null,
85+
dashboardAccountId: null,
86+
dashboardAccountName: null,
8787
reason: 'tier_changed',
8888
manual: false,
8989
amountInDollars: 25,
@@ -111,8 +111,8 @@ describe('sponsor query normalization', () => {
111111
date_created: '2026-08-14T08:30:00.000Z',
112112
github_id: '123',
113113
github_login: 'example',
114-
dashboard_user_id: 'recipient-id',
115-
dashboard_username: 'example',
114+
dashboard_account_id: 'recipient-id',
115+
dashboard_account_name: 'example',
116116
added_by: 'Admin User',
117117
amount: '25000',
118118
reason: 'one_time_sponsorship',
@@ -122,8 +122,8 @@ describe('sponsor query normalization', () => {
122122
date: '2026-08-14T08:30:00.000Z',
123123
githubId: '123',
124124
githubLogin: 'example',
125-
dashboardUserId: 'recipient-id',
126-
dashboardUsername: 'example',
125+
dashboardAccountId: 'recipient-id',
126+
dashboardAccountName: 'example',
127127
addedBy: 'Admin User',
128128
type: 'payment',
129129
credits: 25_000,
@@ -136,8 +136,8 @@ describe('sponsor query normalization', () => {
136136
date_created: new Date('2026-08-14T09:30:00.000Z'),
137137
github_id: '456',
138138
github_login: null,
139-
dashboard_user_id: null,
140-
dashboard_username: null,
139+
dashboard_account_id: null,
140+
dashboard_account_name: null,
141141
added_by: null,
142142
amount: 5000,
143143
reason: 'other',
@@ -147,8 +147,8 @@ describe('sponsor query normalization', () => {
147147
date: '2026-08-14T09:30:00.000Z',
148148
githubId: '456',
149149
githubLogin: null,
150-
dashboardUserId: null,
151-
dashboardUsername: null,
150+
dashboardAccountId: null,
151+
dashboardAccountName: null,
152152
addedBy: null,
153153
type: 'other',
154154
credits: 5000,
@@ -161,8 +161,8 @@ describe('sponsor query normalization', () => {
161161
expect(normalizeSponsorAccount({
162162
github_id: '123',
163163
github_login: 'example',
164-
dashboard_user_id: 'user-id',
165-
dashboard_username: 'dashboard-example',
164+
dashboard_account_id: 'user-id',
165+
dashboard_account_name: 'dashboard-example',
166166
is_active: 0,
167167
has_recurring: '1',
168168
current_monthly_amount: null,
@@ -172,8 +172,8 @@ describe('sponsor query normalization', () => {
172172
})).to.deep.equal({
173173
githubId: '123',
174174
githubLogin: 'example',
175-
dashboardUserId: 'user-id',
176-
dashboardUsername: 'dashboard-example',
175+
dashboardAccountId: 'user-id',
176+
dashboardAccountName: 'dashboard-example',
177177
status: 'former',
178178
currentMonthlyAmount: null,
179179
periodSponsorshipValue: 125.5,
@@ -186,8 +186,8 @@ describe('sponsor query normalization', () => {
186186
expect(normalizeSponsorAccount({
187187
github_id: '456',
188188
github_login: null,
189-
dashboard_user_id: null,
190-
dashboard_username: null,
189+
dashboard_account_id: null,
190+
dashboard_account_name: null,
191191
is_active: 1,
192192
has_recurring: 0,
193193
current_monthly_amount: '15.00',
@@ -199,8 +199,8 @@ describe('sponsor query normalization', () => {
199199
expect(normalizeSponsorAccount({
200200
github_id: '789',
201201
github_login: null,
202-
dashboard_user_id: null,
203-
dashboard_username: null,
202+
dashboard_account_id: null,
203+
dashboard_account_name: null,
204204
is_active: 0,
205205
has_recurring: 0,
206206
current_monthly_amount: null,

0 commit comments

Comments
 (0)