Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions sql/reports/topgear/topgear-handles.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-- INPUTS:
-- $1 :: timestamptz -- startDate filter
SELECT
m.handle AS "Handle",
m."firstName" AS "First name",
m."lastName" AS "Last name",
m.email AS "Email address",
m."userId" AS "User ID",
u.create_date AS "User create date",
sso.sso_user_id AS "SSO user ID",
sso.sso_user_name AS "SSO user name",
sso.email AS "SSO email"
FROM members.member m
JOIN identity."user" u
ON u.user_id = m."userId"::numeric(10, 0)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Casting m."userId" to numeric(10, 0) may lead to unexpected behavior if m."userId" contains non-numeric characters or exceeds the precision. Consider ensuring that m."userId" is always a valid numeric value or adjust the data type accordingly.

AND u.create_date >= $1::timestamptz
LEFT JOIN LATERAL (
SELECT
usl.sso_user_id,
usl.sso_user_name,
usl.email
FROM identity.user_sso_login usl
WHERE usl.user_id = m."userId"::numeric(10, 0)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Similar to line 15, casting m."userId" to numeric(10, 0) in the WHERE clause may lead to unexpected behavior. Ensure that m."userId" is always a valid numeric value or adjust the data type accordingly.

ORDER BY
(usl.email ILIKE '%@wipro.com') DESC,
usl.provider_id
LIMIT 1
) sso ON TRUE
WHERE m.email ILIKE '%@wipro.com'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
The WHERE clause filters by m.email ILIKE '%@wipro.com', which may lead to performance issues if the dataset is large and there is no index supporting this pattern match. Consider evaluating the need for an index or alternative filtering strategies.

ORDER BY u.create_date DESC NULLS LAST, m.handle;
1 change: 1 addition & 0 deletions src/app-constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const Scopes = {
TopgearHourly: "reports:topgear-hourly",
TopgearHandles: "reports:topgear-handles",
TopgearPayments: "reports:topgear-payments",
TopgearChallenge: "reports:topgear-challenge",
TopgearCancelledChallenge: "reports:topgear-cancelled-challenge",
Expand Down
18 changes: 18 additions & 0 deletions src/reports/topgear/topgear-reports.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@ export class TopgearReportsController {
return this.reports.getTopgearHourly();
}

@Get("topgear-handles")
@UseGuards(PermissionsGuard)
@Scopes(AppScopes.AllReports, AppScopes.TopgearHandles)
@ApiBearerAuth()
@ApiOperation({
summary: "Return the Topgear handles report for Wipro email accounts",
})
@ApiQuery({
name: "startDate",
required: false,
type: Date,
description:
"Filter users created after this date (defaults to current date - 90 days)",
})
getTopgearHandles(@Query("startDate") startDate?: string) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
The startDate parameter is expected to be a Date, but it is being passed as a string. Consider parsing it to a Date object before using it to ensure correct date handling.

return this.reports.getTopgearHandles({ startDate });
}

@Get("challenge-stats-by-user")
@UseGuards(PermissionsGuard)
@Scopes(AppScopes.AllReports, AppScopes.TopgearChallengeStatsByUser)
Expand Down
6 changes: 6 additions & 0 deletions src/reports/topgear/topgear-reports.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export class TopgearReportsService {
return this.db.query(query);
}

async getTopgearHandles(opts: { startDate?: string }) {
const startDate = parseOptionalDate(opts.startDate) ?? subDays(new Date(), 90);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
Consider validating the opts.startDate before parsing it with parseOptionalDate. If opts.startDate is not a valid date string, parseOptionalDate might return null, leading to unexpected behavior. Adding validation can prevent potential issues with invalid input.

const query = this.sql.load("reports/topgear/topgear-handles.sql");
return this.db.query(query, [startDate.toISOString()]);
}

async getChallengeStatsByUser(opts: {
startDate?: string;
endDate?: string;
Expand Down
Loading