Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
99b39f5
PM-4305 Remove photo url check for completed profiles
himaniraghav3 Mar 25, 2026
61cbae0
Merge pull request #66 from topcoder-platform/PM-4305
kkartunov Mar 26, 2026
a1544f2
PM-4491 Add names in registered users
himaniraghav3 Mar 30, 2026
a91e218
Deploy branch
himaniraghav3 Mar 30, 2026
135dafa
add names to registrants history report
himaniraghav3 Mar 30, 2026
d41987d
Add names to submitters query
himaniraghav3 Mar 30, 2026
13c367b
fix dto
himaniraghav3 Mar 30, 2026
de46c8e
Add names to valid submitters query
himaniraghav3 Mar 30, 2026
bb86f51
Add names to winners query
himaniraghav3 Mar 30, 2026
ed158af
Merge pull request #67 from topcoder-platform/PM-4491-fix
himaniraghav3 Mar 31, 2026
9d04237
PM-4151: add MM final scores to challenge exports
jmgasper Apr 2, 2026
2e6aa4a
PM-4151: add MM final scores to challenge exports
jmgasper Apr 3, 2026
ccce5ef
Merge pull request #69 from topcoder-platform/PM-4151
jmgasper Apr 5, 2026
c75969f
PM-4151: align challenge export regression spec with names
jmgasper Apr 6, 2026
5a07b01
Merge pull request #71 from topcoder-platform/PM-4151-2
jmgasper Apr 6, 2026
07141f1
Merge branch 'develop' into PM-4151-1
jmgasper Apr 6, 2026
f108c3a
PM-4151: fallback MM export final scores to submission data
jmgasper Apr 8, 2026
b51a69a
Engagements data report
jmgasper Apr 8, 2026
1bdccab
Merge pull request #70 from topcoder-platform/PM-4151-1
jmgasper Apr 8, 2026
114fa73
Merge pull request #73 from topcoder-platform/PM-4151-3
jmgasper Apr 8, 2026
8ca58fa
Updates for engagements data report
jmgasper Apr 9, 2026
7adb2af
Merge branch 'develop' of github.com:topcoder-platform/reports-api-v6…
jmgasper Apr 9, 2026
1576ce0
Reports schema fix
jmgasper Apr 9, 2026
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
3 changes: 2 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ workflows:
only:
- develop
- pm-1127_1
- pm-4203_1
- PM-4305
- PM-4491-fix

# Production builds are exectuted only on tagged commits to the
# master branch.
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ Create a `.env` file in the root of the project. You can copy the example struct
# This is used by Prisma to connect to your local PostgreSQL instance.
DATABASE_URL="postgresql://user:password@localhost:5432/lookups?schema=public"

# Engagements database used by the Engagement Data member report.
ENGAGEMENTS_DB_URL="postgresql://user:password@localhost:5432/engagements"

# The same report also reads member/profile/project data from the main
# DATABASE_URL connection, including members.member, members.memberAddress,
# members.memberPhone, identity.country, and projects.projects.

# Old tc-payments database URL (used by member-tax CSV export script)
OLD_PAYMENTS_DATABASE_URL="postgresql://user:password@localhost:5432/tc_payments?schema=public"

Expand Down
8 changes: 8 additions & 0 deletions sql/reports/challenges/registered-users.sql
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ SELECT
NULLIF(TRIM(mem.handle), ''),
rm."memberHandle"
) AS "handle",
COALESCE(
NULLIF(TRIM(u.first_name), ''),
NULLIF(TRIM(mem."firstName"), '')
) AS "firstName",
COALESCE(
NULLIF(TRIM(u.last_name), ''),
NULLIF(TRIM(mem."lastName"), '')
) AS "lastName",
COALESCE(e.address, NULLIF(TRIM(mem.email), '')) AS "email",
COALESCE(
comp_code.name,
Expand Down
16 changes: 16 additions & 0 deletions sql/reports/challenges/registrants-history.sql
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,25 @@ SELECT
ELSE null
END AS "challengeCompletedDate",
r."registrantHandle",
COALESCE(
NULLIF(TRIM(u.first_name), ''),
NULLIF(TRIM(mem."firstName"), '')
) AS "firstName",

COALESCE(
NULLIF(TRIM(u.last_name), ''),
NULLIF(TRIM(mem."lastName"), '')
) AS "lastName",
COALESCE(sub."registrantFinalScore", sum."registrantFinalScore")
AS "registrantFinalScore"
FROM registrants r
LEFT JOIN identity."user" u
ON r."memberId" ~ '^[0-9]+$'
AND u.user_id = r."memberId"::numeric

LEFT JOIN members."member" mem
ON r."memberId" ~ '^[0-9]+$'
AND mem."userId" = r."memberId"::bigint
LEFT JOIN LATERAL (
SELECT
MAX(cw.handle) AS "winnerHandle",
Expand Down
21 changes: 20 additions & 1 deletion sql/reports/challenges/submitters.sql
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ submission_metrics AS (
s."initialScore"::double precision
) AS standard_score,
provisional_review.provisional_score,
final_review."aggregateScore" AS final_score_raw
COALESCE(
final_review."aggregateScore",
s."finalScore"::double precision
) AS final_score_raw
FROM challenge_context AS cc
JOIN reviews."submission" AS s
ON s."challengeId" = cc.id
Expand Down Expand Up @@ -85,6 +88,10 @@ mm_ranked_scores AS (
WHEN mlss.provisional_score_raw IS NULL THEN NULL
ELSE ROUND(mlss.provisional_score_raw::numeric, 2)
END AS "provisionalScore",
CASE
WHEN mlss.final_score_raw IS NULL THEN NULL
ELSE ROUND(mlss.final_score_raw::numeric, 2)
END AS "finalScore",
CASE
WHEN mlss.effective_score_raw IS NULL THEN NULL
ELSE ROW_NUMBER() OVER (
Expand All @@ -110,6 +117,14 @@ SELECT
sm."memberHandle"
) AS "handle",
COALESCE(e.address, NULLIF(TRIM(mem.email), '')) AS "email",
COALESCE(
NULLIF(TRIM(u.first_name), ''),
NULLIF(TRIM(mem."firstName"), '')
) AS "firstName",
COALESCE(
NULLIF(TRIM(u.last_name), ''),
NULLIF(TRIM(mem."lastName"), '')
) AS "lastName",
COALESCE(
comp_code.name,
comp_id.name,
Expand All @@ -127,6 +142,10 @@ SELECT
WHEN sm.is_marathon_match THEN mrs."provisionalScore"
ELSE NULL
END AS "provisionalScore",
CASE
WHEN sm.is_marathon_match THEN mrs."finalScore"
ELSE NULL
END AS "finalScore",
CASE
WHEN sm.is_marathon_match THEN mrs."finalRank"
ELSE NULL
Expand Down
21 changes: 20 additions & 1 deletion sql/reports/challenges/valid-submitters.sql
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ submission_metrics AS (
s."initialScore"::double precision
) AS standard_score,
provisional_review.provisional_score,
final_review."aggregateScore" AS final_score_raw,
COALESCE(
final_review."aggregateScore",
s."finalScore"::double precision
) AS final_score_raw,
(
passing_review.is_passing IS TRUE
OR COALESCE(s."finalScore"::double precision, 0) > 98
Expand Down Expand Up @@ -102,6 +105,10 @@ mm_ranked_scores AS (
WHEN mlss.provisional_score_raw IS NULL THEN NULL
ELSE ROUND(mlss.provisional_score_raw::numeric, 2)
END AS "provisionalScore",
CASE
WHEN mlss.final_score_raw IS NULL THEN NULL
ELSE ROUND(mlss.final_score_raw::numeric, 2)
END AS "finalScore",
CASE
WHEN mlss.effective_score_raw IS NULL THEN NULL
ELSE ROW_NUMBER() OVER (
Expand All @@ -126,6 +133,14 @@ SELECT
NULLIF(TRIM(mem.handle), ''),
vsm."memberHandle"
) AS "handle",
COALESCE(
NULLIF(TRIM(u.first_name), ''),
NULLIF(TRIM(mem."firstName"), '')
) AS "firstName",
COALESCE(
NULLIF(TRIM(u.last_name), ''),
NULLIF(TRIM(mem."lastName"), '')
) AS "lastName",
COALESCE(e.address, NULLIF(TRIM(mem.email), '')) AS "email",
COALESCE(
comp_code.name,
Expand All @@ -144,6 +159,10 @@ SELECT
WHEN vsm.is_marathon_match THEN mrs."provisionalScore"
ELSE NULL
END AS "provisionalScore",
CASE
WHEN vsm.is_marathon_match THEN mrs."finalScore"
ELSE NULL
END AS "finalScore",
CASE
WHEN vsm.is_marathon_match THEN mrs."finalRank"
ELSE NULL
Expand Down
23 changes: 21 additions & 2 deletions sql/reports/challenges/winners.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ submission_metrics AS (
s."initialScore"::double precision
) AS standard_score,
provisional_review.provisional_score,
final_review."aggregateScore" AS final_score_raw
COALESCE(
final_review."aggregateScore",
s."finalScore"::double precision
) AS final_score_raw
FROM challenge_context AS cc
JOIN reviews."submission" AS s
ON s."challengeId" = cc.id
Expand Down Expand Up @@ -72,7 +75,11 @@ mm_winner_scores AS (
CASE
WHEN mms.provisional_score_raw IS NULL THEN NULL
ELSE ROUND(mms.provisional_score_raw::numeric, 2)
END AS "provisionalScore"
END AS "provisionalScore",
CASE
WHEN mms.final_score_raw IS NULL THEN NULL
ELSE ROUND(mms.final_score_raw::numeric, 2)
END AS "finalScore"
FROM mm_member_scores AS mms
)
SELECT
Expand All @@ -88,6 +95,14 @@ SELECT
NULLIF(TRIM(mem.handle), ''),
wm."winnerHandle"
) AS "handle",
COALESCE(
NULLIF(TRIM(u.first_name), ''),
NULLIF(TRIM(mem."firstName"), '')
) AS "firstName",
COALESCE(
NULLIF(TRIM(u.last_name), ''),
NULLIF(TRIM(mem."lastName"), '')
) AS "lastName",
COALESCE(e.address, NULLIF(TRIM(mem.email), '')) AS "email",
COALESCE(
comp_code.name,
Expand All @@ -106,6 +121,10 @@ SELECT
WHEN wm.is_marathon_match THEN mrs."provisionalScore"
ELSE NULL
END AS "provisionalScore",
CASE
WHEN wm.is_marathon_match THEN mrs."finalScore"
ELSE NULL
END AS "finalScore",
CASE
WHEN wm.is_marathon_match THEN wm.placement
ELSE NULL
Expand Down
2 changes: 0 additions & 2 deletions sql/reports/topcoder/completed-profiles-count.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ FROM members.member m
INNER JOIN member_skills ms ON ms.user_id = m."userId"
WHERE m.description IS NOT NULL
AND m.description <> ''
AND m."photoURL" IS NOT NULL
AND m."photoURL" <> ''
AND m."homeCountryCode" IS NOT NULL
AND ($1::text IS NULL OR COALESCE(m."homeCountryCode", m."competitionCountryCode") = $1)
AND ($3::uuid[] IS NULL OR ms.skill_ids @> $3::uuid[])
Expand Down
2 changes: 0 additions & 2 deletions sql/reports/topcoder/completed-profiles.sql
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ LEFT JOIN LATERAL (
) ma ON TRUE
WHERE m.description IS NOT NULL
AND m.description <> ''
AND m."photoURL" IS NOT NULL
AND m."photoURL" <> ''
AND m."homeCountryCode" IS NOT NULL
AND ($1::text IS NULL OR COALESCE(m."homeCountryCode", m."competitionCountryCode") = $1)
AND ($5::uuid[] IS NULL OR ms.skill_ids @> $5::uuid[])
Expand Down
56 changes: 56 additions & 0 deletions sql/reports/topcoder/engagement-data-members.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
SELECT
m."userId"::text AS user_id,
NULLIF(BTRIM(m.handle), '') AS handle,
NULLIF(BTRIM(m."firstName"), '') AS first_name,
NULLIF(BTRIM(m."lastName"), '') AS last_name,
NULLIF(BTRIM(m.email), '') AS email,
COALESCE(NULLIF(BTRIM(c.country_name), ''), NULLIF(BTRIM(m.country), ''))
AS country,
preferred_address.street_addr_1,
preferred_address.street_addr_2,
preferred_address.city,
preferred_address.state_code,
preferred_address.zip,
preferred_phone.phone_number
FROM members.member m
LEFT JOIN identity.country c
ON c.country_code = m."homeCountryCode"
LEFT JOIN LATERAL (
SELECT
NULLIF(BTRIM(a."streetAddr1"), '') AS street_addr_1,
NULLIF(BTRIM(a."streetAddr2"), '') AS street_addr_2,
NULLIF(BTRIM(a.city), '') AS city,
NULLIF(BTRIM(a."stateCode"), '') AS state_code,
NULLIF(BTRIM(a.zip), '') AS zip
FROM members."memberAddress" a
WHERE a."userId" = m."userId"
ORDER BY
CASE
WHEN UPPER(a.type) = 'HOME' THEN 0
WHEN UPPER(a.type) = 'BILLING' THEN 1
ELSE 2
END,
a."updatedAt" DESC NULLS LAST,
a."createdAt" DESC NULLS LAST,
a.id DESC
LIMIT 1
) preferred_address
ON TRUE
LEFT JOIN LATERAL (
SELECT NULLIF(BTRIM(p.number), '') AS phone_number
FROM members."memberPhone" p
WHERE p."userId" = m."userId"
AND NULLIF(BTRIM(p.number), '') IS NOT NULL
ORDER BY
CASE
WHEN POSITION('mobile' IN LOWER(p.type)) > 0 THEN 0
ELSE 1
END,
p."updatedAt" DESC NULLS LAST,
p."createdAt" DESC NULLS LAST,
p.id ASC
LIMIT 1
) preferred_phone
ON TRUE
WHERE m."userId"::text = ANY($1::text[])
ORDER BY LOWER(m.handle), m."userId";
7 changes: 7 additions & 0 deletions sql/reports/topcoder/engagement-data-projects.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
SELECT
p.id::text AS project_id,
NULLIF(BTRIM(p.name), '') AS project_name
FROM projects.projects p
WHERE p.id::text = ANY($1::text[])
AND p."deletedAt" IS NULL
ORDER BY LOWER(p.name), p.id;
74 changes: 74 additions & 0 deletions sql/reports/topcoder/engagement-data.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
WITH assignment_members AS (
SELECT
NULLIF(BTRIM(a."memberId"), '') AS member_id,
NULLIF(BTRIM(a."memberHandle"), '') AS fallback_handle,
NULLIF(BTRIM(e."projectId"), '') AS project_id
FROM engagements."EngagementAssignment" a
JOIN engagements."Engagement" e
ON e.id = a."engagementId"
WHERE NULLIF(BTRIM(a."memberId"), '') IS NOT NULL
),
assigned_summary AS (
SELECT
member_id,
MAX(fallback_handle) AS fallback_handle,
ARRAY_REMOVE(ARRAY_AGG(DISTINCT project_id), NULL) AS assigned_project_ids
FROM assignment_members
GROUP BY member_id
),
ranked_public_applications AS (
SELECT
NULLIF(BTRIM(app."userId"), '') AS member_id,
NULLIF(BTRIM(app.handle), '') AS application_handle,
NULLIF(BTRIM(app.email), '') AS application_email,
NULLIF(BTRIM(app.address), '') AS application_address,
NULLIF(BTRIM(app."mobileNumber"), '') AS application_phone,
NULLIF(BTRIM(app.name), '') AS application_name,
ROW_NUMBER() OVER (
PARTITION BY app."userId"
ORDER BY app."updatedAt" DESC, app."createdAt" DESC, app.id DESC
) AS rn
FROM engagements."EngagementApplication" app
JOIN engagements."Engagement" e
ON e.id = app."engagementId"
WHERE COALESCE(e."isPrivate", false) = false
AND NULLIF(BTRIM(app."userId"), '') IS NOT NULL
),
latest_public_application AS (
SELECT
member_id,
application_handle,
application_email,
application_address,
application_phone,
application_name
FROM ranked_public_applications
WHERE rn = 1
),
eligible_members AS (
SELECT member_id
FROM assigned_summary
UNION
SELECT member_id
FROM latest_public_application
)
SELECT
em.member_id,
COALESCE(assigned_summary.fallback_handle, latest_public_application.application_handle)
AS fallback_handle,
latest_public_application.application_email,
latest_public_application.application_address,
latest_public_application.application_phone,
latest_public_application.application_name,
(assigned_summary.member_id IS NOT NULL) AS has_assignment,
COALESCE(assigned_summary.assigned_project_ids, ARRAY[]::text[]) AS assigned_project_ids
FROM eligible_members em
LEFT JOIN assigned_summary
ON assigned_summary.member_id = em.member_id
LEFT JOIN latest_public_application
ON latest_public_application.member_id = em.member_id
ORDER BY COALESCE(
assigned_summary.fallback_handle,
latest_public_application.application_handle,
em.member_id
);
2 changes: 2 additions & 0 deletions src/app-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const Scopes = {
AllReports: "reports:all",
TopcoderReports: "reports:topcoder",
Member: {
EngagementData: "reports:member-engagement-data",
RecentMemberData: "reports:member-recent-member-data",
},
TopgearChallengeTechnology: "reports:topgear-challenge-technology",
Expand Down Expand Up @@ -61,6 +62,7 @@ export const ScopeRoleAccess: Record<string, readonly string[]> = {
[Scopes.Challenge.Submitters]: challengeReportAccessRoles,
[Scopes.Challenge.ValidSubmitters]: challengeReportAccessRoles,
[Scopes.Challenge.Winners]: challengeReportAccessRoles,
[Scopes.Member.EngagementData]: [UserRoles.TalentManager],
[Scopes.Member.RecentMemberData]: [UserRoles.TalentManager],
[Scopes.Identity.UsersByHandles]: [
UserRoles.TalentManager,
Expand Down
Loading
Loading