Skip to content

Commit aecfeb8

Browse files
authored
Merge pull request #81 from topcoder-platform/PM-2087_use-v6-apis
PM-2088 - use Topcoder v6 APIs
2 parents 686991d + eca223e commit aecfeb8

File tree

9 files changed

+32
-137
lines changed

9 files changed

+32
-137
lines changed

.env.sample

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
TOPCODER_API_BASE_URL="https://api.topcoder-dev.com/v5"
1+
TOPCODER_API_V5_BASE_URL="https://api.topcoder-dev.com/v5"
2+
TOPCODER_API_V6_BASE_URL="https://api.topcoder-dev.com/v6"
23
AUTH0_CERT="-----BEGIN RSA PUBLIC KEY-----
34
MIIBCgKCAQEArAV0dmDkedFdlaQ6KQiqUv+UGshfMXx/4jJCLZ9802ynJqAvIt+Z
45
V7EiPqjc2J1xVfJJEvQ9ZS5A2TFWAk16NUTU4LN+TkjEnqeg+LlUPWY3Y4RXa2OU
@@ -15,4 +16,4 @@ DB_PASSWORD=randompassword
1516
DB_HOST=127.0.0.1
1617
DB_PORT=5434
1718
DB_NAME=walletdb
18-
DATABASE_URL="postgresql://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=disable"
19+
DATABASE_URL="postgresql://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=disable"

src/api/admin/admin.service.ts

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ import { ResponseDto } from 'src/dto/api-response.dto';
1313
import { PaymentStatus } from 'src/dto/payment.dto';
1414
import { WinningAuditDto, AuditPayoutDto } from './dto/audit.dto';
1515
import { WinningUpdateRequestDto } from './dto/winnings.dto';
16-
import {
17-
AdminPaymentUpdateData,
18-
TopcoderChallengesService,
19-
} from 'src/shared/topcoder/challenges.service';
16+
import { TopcoderChallengesService } from 'src/shared/topcoder/challenges.service';
2017
import { Logger } from 'src/shared/global';
2118

2219
/**
@@ -307,30 +304,6 @@ export class AdminService {
307304
}
308305
});
309306

310-
transactions.push(async () => {
311-
const winning = await this.getWinningById(winningsId);
312-
if (!winning) {
313-
this.logger.error(
314-
`Error updating legacy system for winning ${winningsId}. Winning not found!`,
315-
);
316-
throw new Error(
317-
`Error updating legacy system for winning ${winningsId}. Winning not found!`,
318-
);
319-
}
320-
321-
const payoutData: AdminPaymentUpdateData = {
322-
userId: +winning.winner_id,
323-
status: body.paymentStatus,
324-
amount: body.paymentAmount,
325-
releaseDate: body.releaseDate,
326-
};
327-
328-
await this.tcChallengesService.updateLegacyPayments(
329-
winning.external_id as string,
330-
payoutData,
331-
);
332-
});
333-
334307
// Run all transaction tasks in a single prisma transaction
335308
await this.prisma.$transaction(async (tx) => {
336309
for (const transaction of transactions) {

src/api/challenges/challenges.service.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ import { BillingAccountsService } from 'src/shared/topcoder/billing-accounts.ser
1212
import { TopcoderM2MService } from 'src/shared/topcoder/topcoder-m2m.service';
1313
import { ChallengeStatuses } from 'src/dto/challenge.dto';
1414
import { WinningsService } from '../winnings/winnings.service';
15-
import { WinningsCategory, WinningsType } from 'src/dto/winning.dto';
15+
import {
16+
WinningRequestDto,
17+
WinningsCategory,
18+
WinningsType,
19+
} from 'src/dto/winning.dto';
1620
import { WinningsRepository } from '../repository/winnings.repo';
1721

1822
const placeToOrdinal = (place: number) => {
@@ -23,7 +27,7 @@ const placeToOrdinal = (place: number) => {
2327
return `${place}th`;
2428
};
2529

26-
const { TOPCODER_API_V6_BASE_URL, TGBillingAccounts } = ENV_CONFIG;
30+
const { TOPCODER_API_V6_BASE_URL: TC_API_BASE, TGBillingAccounts } = ENV_CONFIG;
2731

2832
@Injectable()
2933
export class ChallengesService {
@@ -37,7 +41,7 @@ export class ChallengesService {
3741
) {}
3842

3943
async getChallenge(challengeId: string) {
40-
const requestUrl = `${TOPCODER_API_V6_BASE_URL}/challenges/${challengeId}`;
44+
const requestUrl = `${TC_API_BASE}/challenges/${challengeId}`;
4145

4246
try {
4347
const challenge = await this.m2MService.m2mFetch<Challenge>(requestUrl);
@@ -51,7 +55,7 @@ export class ChallengesService {
5155
}
5256

5357
async getChallengeSubmissionsCount(challengeId: string) {
54-
const requestUrl = `${TOPCODER_API_V6_BASE_URL}/submissions?challengeId=${challengeId}&perPage=9999`;
58+
const requestUrl = `${TC_API_BASE}/submissions?challengeId=${challengeId}&perPage=9999`;
5559

5660
try {
5761
const submissions =
@@ -71,10 +75,10 @@ export class ChallengesService {
7175
async getChallengeResources(challengeId: string) {
7276
try {
7377
const resources = await this.m2MService.m2mFetch<ChallengeResource[]>(
74-
`${TOPCODER_API_V6_BASE_URL}/resources?challengeId=${challengeId}`,
78+
`${TC_API_BASE}/resources?challengeId=${challengeId}`,
7579
);
7680
const resourceRoles = await this.m2MService.m2mFetch<ResourceRole[]>(
77-
`${TOPCODER_API_V6_BASE_URL}/resource-roles`,
81+
`${TC_API_BASE}/resource-roles`,
7882
);
7983

8084
const rolesMap = resourceRoles.reduce(
@@ -217,7 +221,7 @@ export class ChallengesService {
217221
billingAccountId: challenge.billing.billingAccountId,
218222
payroll: includes(
219223
TGBillingAccounts,
220-
+challenge.billing.billingAccountId,
224+
parseInt(challenge.billing.billingAccountId),
221225
),
222226
},
223227
}));
@@ -240,7 +244,9 @@ export class ChallengesService {
240244
}
241245

242246
const existingPayments = (
243-
await this.winningsRepo.searchWinnings({ externalIds: [challengeId] })
247+
await this.winningsRepo.searchWinnings({
248+
externalIds: [challengeId],
249+
} as WinningRequestDto)
244250
)?.data?.winnings;
245251
if (existingPayments?.length > 0) {
246252
this.logger.log(

src/api/repository/winnings.repo.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ export class WinningsRepository {
5656
private getWinningsQueryFilters(
5757
type?: string,
5858
status?: string,
59-
winnerIds?: string[] | undefined,
60-
externalIds?: string[] | undefined,
59+
winnerIds?: string[],
60+
externalIds?: string[],
6161
date?: DateFilterType,
6262
): Prisma.winningsFindManyArgs['where'] {
6363
return {
@@ -176,7 +176,7 @@ export class WinningsRepository {
176176

177177
const orderBy = this.getOrderByWithWinnerId(
178178
searchProps.sortBy,
179-
searchProps.sortOrder!,
179+
searchProps.sortOrder,
180180
!winnerIds && !!externalIds?.length,
181181
);
182182

@@ -240,9 +240,9 @@ export class WinningsRepository {
240240
})),
241241
pagination: {
242242
totalItems: count,
243-
totalPages: Math.ceil(count / searchProps.limit!),
244-
pageSize: searchProps.limit!,
245-
currentPage: Math.ceil(searchProps.offset! / searchProps.limit!) + 1,
243+
totalPages: Math.ceil(count / searchProps.limit),
244+
pageSize: searchProps.limit,
245+
currentPage: Math.ceil(searchProps.offset / searchProps.limit) + 1,
246246
},
247247
};
248248
// response.data = winnings as any

src/api/withdrawal/withdrawal.service.ts

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ import {
1212
} from '@prisma/client';
1313
import { TrolleyService } from 'src/shared/global/trolley.service';
1414
import { PaymentsService } from 'src/shared/payments';
15-
import {
16-
TopcoderChallengesService,
17-
WithdrawUpdateData,
18-
} from 'src/shared/topcoder/challenges.service';
15+
import { TopcoderChallengesService } from 'src/shared/topcoder/challenges.service';
1916
import { TopcoderMembersService } from 'src/shared/topcoder/members.service';
2017
import { BasicMemberInfo, BASIC_MEMBER_FIELDS } from 'src/shared/topcoder';
2118
import { Logger } from 'src/shared/global';
@@ -35,16 +32,6 @@ interface ReleasableWinningRow {
3532
datePaid: Date;
3633
}
3734

38-
function formatDate(date = new Date()) {
39-
const pad = (n, z = 2) => String(n).padStart(z, '0');
40-
41-
return (
42-
`${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ` +
43-
`${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}.` +
44-
`${pad(date.getMilliseconds(), 3)}`
45-
);
46-
}
47-
4835
@Injectable()
4936
export class WithdrawalService {
5037
private readonly logger = new Logger(WithdrawalService.name);
@@ -367,26 +354,6 @@ export class WithdrawalService {
367354
this.logger.error(errorMsg, error);
368355
throw new Error(errorMsg);
369356
}
370-
371-
try {
372-
for (const winning of winnings) {
373-
const payoutData: WithdrawUpdateData = {
374-
userId: +userId,
375-
status: 'Paid',
376-
datePaid: formatDate(new Date()),
377-
};
378-
379-
await this.tcChallengesService.updateLegacyPayments(
380-
winning.externalId as string,
381-
payoutData,
382-
);
383-
}
384-
} catch (error) {
385-
this.logger.error(
386-
`Failed to update legacy payment while withdrawing for challenge ${error?.message ?? error}`,
387-
error,
388-
);
389-
}
390357
});
391358
} catch (error) {
392359
if (error.code === 'P2010' && error.meta?.code === '55P03') {

src/config/config.env.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class ConfigEnv {
2020
PORT = 3000;
2121

2222
@IsString()
23-
TOPCODER_API_BASE_URL!: string;
23+
TOPCODER_API_V5_BASE_URL!: string;
2424

2525
@IsString()
2626
TOPCODER_API_V6_BASE_URL!: string;
@@ -114,6 +114,6 @@ export class ConfigEnv {
114114
@IsString()
115115
SENDGRID_TEMPLATE_ID_OTP_CODE: string = 'd-2d0ab9f6c9cc4efba50080668a9c35c1';
116116

117-
@IsInt({each: true})
117+
@IsInt({ each: true })
118118
TGBillingAccounts = [80000062, 80002800];
119119
}

src/shared/topcoder/bus.service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ENV_CONFIG } from 'src/config';
33
import { TopcoderM2MService } from './topcoder-m2m.service';
44
import { Logger } from '../global';
55

6-
const { TOPCODER_API_BASE_URL } = ENV_CONFIG;
6+
const { TOPCODER_API_V5_BASE_URL: TC_API_BASE } = ENV_CONFIG;
77

88
@Injectable()
99
export class TopcoderBusService {
@@ -43,7 +43,7 @@ export class TopcoderBusService {
4343

4444
try {
4545
const headers = await this.getHeaders();
46-
const response = await fetch(`${TOPCODER_API_BASE_URL}/bus/events`, {
46+
const response = await fetch(`${TC_API_BASE}/bus/events`, {
4747
method: 'POST',
4848
headers,
4949
body: JSON.stringify({
Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import { Injectable } from '@nestjs/common';
22
import { TopcoderM2MService } from './topcoder-m2m.service';
3-
import { ENV_CONFIG } from 'src/config';
4-
import { payment_status } from '@prisma/client';
53
import { Logger } from 'src/shared/global';
64

7-
const { TOPCODER_API_BASE_URL } = ENV_CONFIG;
8-
95
export interface WithdrawUpdateData {
106
userId: number;
117
status: string;
@@ -18,57 +14,9 @@ export interface AdminPaymentUpdateData {
1814
amount: number;
1915
releaseDate: string;
2016
}
21-
22-
const mapStatus = (payoutData: WithdrawUpdateData | AdminPaymentUpdateData) => {
23-
return {
24-
...payoutData,
25-
status: {
26-
[payment_status.CANCELLED]: 'Cancelled',
27-
[payment_status.FAILED]: 'Failed',
28-
[payment_status.ON_HOLD]: 'OnHold',
29-
[payment_status.ON_HOLD_ADMIN]: 'OnHoldAdmin',
30-
[payment_status.OWED]: 'Owed',
31-
[payment_status.PAID]: 'Paid',
32-
[payment_status.PROCESSING]: 'Processing',
33-
[payment_status.RETURNED]: 'Returned',
34-
}[payoutData.status],
35-
};
36-
};
37-
3817
@Injectable()
3918
export class TopcoderChallengesService {
4019
private readonly logger = new Logger(TopcoderChallengesService.name);
4120

4221
constructor(private readonly m2MService: TopcoderM2MService) {}
43-
44-
async updateLegacyPayments(
45-
challengeId: string,
46-
payoutData: WithdrawUpdateData | AdminPaymentUpdateData,
47-
) {
48-
const requestData = mapStatus(payoutData);
49-
const requestUrl = `${TOPCODER_API_BASE_URL}/challenges/${challengeId}/legacy-payment`;
50-
51-
this.logger.debug(
52-
`Updating legacy payment for challenge ${challengeId} with data: ${JSON.stringify(requestData, null, 2)}`,
53-
);
54-
55-
try {
56-
const response = await this.m2MService.m2mFetch(requestUrl, {
57-
method: 'PATCH',
58-
body: JSON.stringify(requestData),
59-
});
60-
61-
this.logger.debug(
62-
`Response from updating legacy payment for challenge ${challengeId}: ${JSON.stringify(response, null, 2)}`,
63-
);
64-
65-
return response;
66-
} catch (e) {
67-
this.logger.error(
68-
`Failed to update legacy payment for challenge ${challengeId}! Error: ${e?.message ?? e}`,
69-
e,
70-
);
71-
throw e;
72-
}
73-
}
7422
}

src/shared/topcoder/members.service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { TopcoderM2MService } from './topcoder-m2m.service';
55
import { ENV_CONFIG } from 'src/config';
66
import { Logger } from 'src/shared/global';
77

8-
const { TOPCODER_API_BASE_URL } = ENV_CONFIG;
8+
const { TOPCODER_API_V6_BASE_URL: TC_API_BASE } = ENV_CONFIG;
99

1010
@Injectable()
1111
export class TopcoderMembersService {
@@ -27,7 +27,7 @@ export class TopcoderMembersService {
2727

2828
// Split the unique user IDs into chunks of 100 to comply with API request limits
2929
const requests = chunk(uniqUserIds, 30).map((chunk) => {
30-
const requestUrl = `${TOPCODER_API_BASE_URL}/members?${chunk.map((id) => `userIds[]=${id}`).join('&')}&fields=handle,userId`;
30+
const requestUrl = `${TC_API_BASE}/members?${chunk.map((id) => `userIds[]=${id}`).join('&')}&fields=handle,userId`;
3131
return fetch(requestUrl).then(
3232
async (response) =>
3333
(await response.json()) as { handle: string; userId: string },
@@ -77,7 +77,7 @@ export class TopcoderMembersService {
7777
e.message ?? e,
7878
);
7979
}
80-
const requestUrl = `${TOPCODER_API_BASE_URL}/members/${handle}${fields ? `?fields=${fields.join(',')}` : ''}`;
80+
const requestUrl = `${TC_API_BASE}/members/${handle}${fields ? `?fields=${fields.join(',')}` : ''}`;
8181

8282
try {
8383
const response = await fetch(requestUrl, {

0 commit comments

Comments
 (0)