Skip to content

Commit 7fb676c

Browse files
authored
Merge pull request #47 from topcoder-platform/develop
Start / end dates to weekly member participation report
2 parents feeabe6 + 24f965f commit 7fb676c

9 files changed

Lines changed: 60 additions & 23 deletions

sql/reports/topcoder/weekly-member-participation.sql

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
1-
WITH window_bounds AS (
1+
WITH provided_dates AS (
22
SELECT
3-
(DATE_TRUNC('week', CURRENT_DATE) - INTERVAL '4 weeks') AS window_start,
4-
(DATE_TRUNC('week', CURRENT_DATE) + INTERVAL '1 week') AS window_end
3+
NULLIF($1, '')::timestamptz AS start_date,
4+
NULLIF($2, '')::timestamptz AS end_date
5+
),
6+
window_bounds AS (
7+
SELECT
8+
COALESCE(
9+
pd.start_date,
10+
CASE
11+
WHEN pd.end_date IS NOT NULL THEN pd.end_date - INTERVAL '5 weeks'
12+
ELSE DATE_TRUNC('week', CURRENT_DATE) - INTERVAL '4 weeks'
13+
END
14+
) AS window_start,
15+
COALESCE(
16+
pd.end_date,
17+
DATE_TRUNC('week', CURRENT_DATE) + INTERVAL '1 week'
18+
) AS window_end
19+
FROM provided_dates pd
520
),
621
billing AS (
722
SELECT
@@ -18,7 +33,7 @@ billing AS (
1833
LEFT JOIN projects.projects proj
1934
ON proj.id::text = NULLIF(TRIM(c."projectId"::text), '')
2035
LEFT JOIN "billing-accounts"."BillingAccount" project_ba
21-
ON project_ba.id = proj."billingAccountId"
36+
ON project_ba.id::text = NULLIF(TRIM(proj."billingAccountId"::text), '')
2237
GROUP BY c.id
2338
),
2439
project_clients AS (

src/auth/auth.middleware.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ function decodeTokenPayload(token: string): Record<string, unknown> | null {
4444
return null;
4545
}
4646
const payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
47-
const padded =
48-
payload + "=".repeat((4 - (payload.length % 4)) % 4);
47+
const padded = payload + "=".repeat((4 - (payload.length % 4)) % 4);
4948
const decoded = Buffer.from(padded, "base64").toString("utf8");
5049
return JSON.parse(decoded);
5150
} catch {

src/common/validation.util.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,7 @@ export function transformArray({ value }: { value: unknown }) {
2525
return [v];
2626
};
2727

28-
return Array.isArray(value) ? value.flatMap(splitIfString) : splitIfString(value);
28+
return Array.isArray(value)
29+
? value.flatMap(splitIfString)
30+
: splitIfString(value);
2931
}

src/reports/report-directory.data.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,8 @@ export const REPORTS_DIRECTORY: ReportsDirectory = {
446446
report(
447447
"Weekly Member Participation",
448448
"/topcoder/weekly-member-participation",
449-
"Weekly distinct registrants and submitters for the last five weeks",
449+
"Weekly distinct registrants and submitters for the provided date range (defaults to last five weeks)",
450+
[paymentsStartDateParam, paymentsEndDateParam],
450451
),
451452
report(
452453
"Member Payment Accrual",

src/reports/sfdc/sfdc-reports.dto.spec.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -732,11 +732,7 @@ describe("TaasResourceBookingsReportQueryDto validation", () => {
732732
billingAccountIds: "80001012,80002012 , 80003012",
733733
});
734734
expect(errors).toHaveLength(0);
735-
expect(dto.billingAccountIds).toEqual([
736-
"80001012",
737-
"80002012",
738-
"80003012",
739-
]);
735+
expect(dto.billingAccountIds).toEqual(["80001012", "80002012", "80003012"]);
740736
});
741737

742738
it("accepts ISO date strings for startDate and endDate", async () => {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ApiPropertyOptional } from "@nestjs/swagger";
2+
import { IsDateString, IsOptional } from "class-validator";
3+
4+
export class WeeklyMemberParticipationQueryDto {
5+
@ApiPropertyOptional({
6+
description:
7+
"Start date (inclusive) for filtering challenge posting date in ISO 8601 format",
8+
example: "2024-01-01T00:00:00.000Z",
9+
})
10+
@IsOptional()
11+
@IsDateString()
12+
startDate?: string;
13+
14+
@ApiPropertyOptional({
15+
description:
16+
"End date (exclusive) for filtering challenge posting date in ISO 8601 format",
17+
example: "2024-02-01T00:00:00.000Z",
18+
})
19+
@IsOptional()
20+
@IsDateString()
21+
endDate?: string;
22+
}

src/reports/topcoder/topcoder-reports.controller.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { TopcoderReportsService } from "./topcoder-reports.service";
1111
import { RegistrantCountriesQueryDto } from "./dto/registrant-countries.dto";
1212
import { MemberPaymentAccrualQueryDto } from "./dto/member-payment-accrual.dto";
1313
import { RecentMemberDataQueryDto } from "./dto/recent-member-data.dto";
14+
import { WeeklyMemberParticipationQueryDto } from "./dto/weekly-member-participation.dto";
1415
import { TopcoderReportsGuard } from "../../auth/guards/topcoder-reports.guard";
1516
import { CsvResponseInterceptor } from "../../common/interceptors/csv-response.interceptor";
1617

@@ -63,10 +64,13 @@ export class TopcoderReportsController {
6364
@Get("/weekly-member-participation")
6465
@ApiOperation({
6566
summary:
66-
"Weekly distinct registrants and submitters for the last five weeks",
67+
"Weekly distinct registrants and submitters for the provided date range (defaults to last five weeks)",
6768
})
68-
getWeeklyMemberParticipation() {
69-
return this.reports.getWeeklyMemberParticipation();
69+
getWeeklyMemberParticipation(
70+
@Query() query: WeeklyMemberParticipationQueryDto,
71+
) {
72+
const { startDate, endDate } = query;
73+
return this.reports.getWeeklyMemberParticipation(startDate, endDate);
7074
}
7175

7276
@Get("/member-payment-accrual")

src/reports/topcoder/topcoder-reports.service.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -448,15 +448,15 @@ export class TopcoderReportsService {
448448
}));
449449
}
450450

451-
async getWeeklyMemberParticipation() {
451+
async getWeeklyMemberParticipation(startDate?: string, endDate?: string) {
452452
const query = this.sql.load(
453453
"reports/topcoder/weekly-member-participation.sql",
454454
);
455455
const rows = await this.db.query<{
456456
"challenge_stats.posting_date_week": string;
457457
"challenge_stats.count_distinct_registrant": string | number;
458458
"challenge_stats.count_distinct_submitter": string | number;
459-
}>(query);
459+
}>(query, [startDate ?? null, endDate ?? null]);
460460

461461
return rows.map((row) => ({
462462
"challenge_stats.posting_date_week":
@@ -470,10 +470,7 @@ export class TopcoderReportsService {
470470
}));
471471
}
472472

473-
async getMemberPaymentAccrual(
474-
startDate?: string,
475-
endDate?: string,
476-
) {
473+
async getMemberPaymentAccrual(startDate?: string, endDate?: string) {
477474
const query = this.sql.load("reports/topcoder/member-payment-accrual.sql");
478475
const rows = await this.db.query<MemberPaymentAccrualRow>(query, [
479476
startDate ?? null,

src/reports/topgear/topgear-reports.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export class TopgearReportsService {
2222
}
2323

2424
async getTopgearHandles(opts: { startDate?: string }) {
25-
const startDate = parseOptionalDate(opts.startDate) ?? subDays(new Date(), 90);
25+
const startDate =
26+
parseOptionalDate(opts.startDate) ?? subDays(new Date(), 90);
2627
const query = this.sql.load("reports/topgear/topgear-handles.sql");
2728
return this.db.query(query, [startDate.toISOString()]);
2829
}

0 commit comments

Comments
 (0)