Skip to content

Manusha Job Posting Page Analytics: Create a donut chart showing applicants by experience - #1457

Open
manushajyasta30 wants to merge 2489 commits into
Manusha_donut_chart_show_applicants_by_experiencefrom
development
Open

manushajyasta30 wants to merge 2489 commits into
Manusha_donut_chart_show_applicants_by_experiencefrom
development

Conversation

@manushajyasta30

Copy link
Copy Markdown
Contributor

Description

image

Related PRS (if any):

T
To test this backend PR you need to checkout the ##3654 frontend PR.
…

Main changes explained:

added routes:
Route: GET /api/applicants/experience-breakdown
GET http://localhost:4500/api/experience-breakdown?roles=Frontend Developer
GET http://localhost:4500/api/experience-breakdown?startDate=2023-01-01&endDate=2024-12-31
…

How to test:

  1. check into current branch
  2. do npm install and ... to run this PR locally
  3. Clear site data/cache
  4. log as admin user
  5. verify endpoints

Screenshots or videos of changes:

image

@manushajyasta30 manushajyasta30 changed the title Job Posting Page Analytics: Create a donut chart showing applicants by experience Manusha Job Posting Page Analytics: Create a donut chart showing applicants by experience Jun 14, 2025
@one-community one-community added the High Priority - Please Review First This is an important PR we'd like to get merged as soon as possible label Jun 18, 2025
@Venk-rgb Venk-rgb self-assigned this Jun 19, 2025
smartha-del and others added 30 commits August 22, 2026 19:23
…not hours

Doc item #23. "Weekly Requirements" and "Remaining Weeks" still used the
old halved-hours threshold, so since PRs Needed moved to the committed
hours bands the two columns disagreed about what the requirement was.

The spec counts weeks where the reviewer "met or exceeded PR requirement",
so a week is now successful when the reviewer reviewed at least prsNeeded
PRs in it, honouring an Owner override where one is set. Actual PR review
records exist but store GitHub's numeric account id, which cannot be
joined to an HGN profile yet, so the count stays on the same review-task
proxy the rest of the page uses: distinct review tasks worked on in a
week, via $addToSet so several time entries against one task stay one
review.

- Add summariseWeeks and weekMeetsRequirement to the helper, pure and
  testable without a database, next to the bands they depend on.
- Exclude the current, still running week from successfulWeeks. The spec
  counts "previous weeks where they have satisfied the minimum
  requirement", and a week in progress has not finished failing yet.
- weeklyRequirementsMet now means the requirement is met for the current
  week, which is the spec's "satisfied for the current period". It used
  to be a synonym for successfulWeeks >= 2, which is promotion
  eligibility and is still available as remainingWeeks === 0. This
  changes what the column shows, so it needs flagging to the frontend.
- Expose successfulWeeks so the page can show progress, not only what
  is left.
- Fix isNewMember, which used six months against a spec that says "New
  Members (joined <= 1 week ago)" and "Existing Members (older than a
  week)".
- Group the per-week aggregation by year as well as week. $week alone
  repeats annually, so the same week number from different years was
  being folded into one group.
- Take one timestamp for the whole read, so two reviewers cannot land on
  different sides of a week boundary partway through the loop.

A requirement of zero is treated as not assessable rather than trivially
met, so reviewers on zero or negative committed hours accumulate no
successful weeks. Dev has 46 accounts below 10 hr/wk and one at -3, and
counting their empty weeks would have walked them to zero remaining weeks
and offered them for promotion without a single review. This moves with
open question 3 to Jae.

mongoWeekOf reproduces MongoDB's $year and $week in JavaScript so the
aggregation and the "which week is now" check agree. Verified against the
database itself over 128 dates across 8 years, including every Jan 1-8
and Dec 25-31 boundary, with no mismatches.
Doc item #23, Process Promotions. The spec assigns a promoted reviewer to
a 10-hour or 20+ hour team matched to that team's weekly standup, and
none of that information existed anywhere.

The premise this was blocked on was wrong. It was recorded as "the hours
band and standup time only live inside the team name", from the example
team-binary-brigade-tues-at-11am-pacific. That is a Slack channel name,
not a team record, and no such team exists. Checked properly: of 1046
active teams on dev, one has a weekday in its name, none has a clock time
and none has an hours band, and among the 161 teams with three or more
members it is zero on every count. teamCode is free text (S-PRc on 1302
profiles, TESTVEN on 626) and models/meeting.js is one-off meetings, not
recurring standups. The data does not exist, so something had to create
it.

- Add optional hoursBand, standupDay, standupTime and standupTimezone to
  the team model. A team missing any of them is not a placement
  candidate, which is what avoids backfilling 1046 mostly-disposable
  teams: only the real PR review teams need configuring, and an
  unconfigured team is invisible rather than wrongly eligible.
- postTeam and putTeam accept them. putTeam only writes the fields
  actually present in the body, because it assigns everything else
  unconditionally and reading these the same way would let the existing
  Teams page wipe a standup on an ordinary rename. Explicit null clears.
- Add teamPlacementHelper with the spec's rules, kept pure: band is
  required, then exact availability match, then smallest of several
  matches, then a standup within two hours, then smallest in band. Ties
  break on team name so preview and commit cannot disagree.
- Add POST /promote-members/preview, which writes nothing. A separate
  route rather than a flag, so nobody can promote by accident while
  asking what would happen. Rows carry a reason and needsReview so the
  confirmation modal can lead with the guesses.
- promoteMembers takes an optional placements array. Omitting it behaves
  exactly as before, role change only, no team touched. When present it
  is trusted over recalculating, since the modal exists so a human can
  override, and membership is written to both the team and the profile
  the way assignTeamToUsers does it.
- Promoted reviewers come back under All Members per the spec, but only
  for an explicit groupKey "all". Omitting the key, which is what the
  current page sends, is unchanged.

Two things the spec does not cover are flagged rather than hidden. Under
10 hr/wk is not placed at all, and someone with no availability on file
gets the smallest team in band marked needsReview. The second is the
common case, not the exception: only 94 of 2639 active profiles have ever
answered the questionnaire, against 1644 rows on the table. Both move
with the open questions to Jae.

Verified live against dev on every branch of the algorithm using real
questionnaire data, via one throwaway team that was deleted afterwards.
An 8AM-9AM person against an 11AM standup resolved as withinTwoHours at
exactly the two hour boundary, a 6AM-7AM person as smallestInBand, an
account whose availability is the string "N/A" as noAvailabilityOnFile,
and moving the standup to 8:30AM flipped the first to an exact match and
the second to withinTwoHours. Renaming the team without sending the
placement fields left it fully placeable, which is the wipe regression.

Full suite: 145 suites, 2164 tests, no failures.
…ratings

Doc item #23, spec items 2 and 5. With this the backend covers every item
in the spec.

History comes back on the existing dashboard read as one entry per prior
week, oldest first so it renders left to right the way the spec's example
does, with unlimited weeks and the current week excluded. belowRequirement
is precomputed rather than left to the frontend: the spec colours a week
red when it is under PRs Needed, and PRs Needed can be an Owner override
rather than the band value, so re-deriving it client side would go wrong
for exactly the reviewers somebody has intervened on. It is always false
when the requirement is zero.

"+ Add New" gets its own collection rather than an array on the
promotionEligibility doc, because the spec asks for unlimited weeks and
that document is rewritten on every dashboard read. A unique index on
reviewer, year, week and PR number is what makes the import safe to
re-run and turns a duplicate into a 409 instead of a 500.

- Add prEntryHelper with the five rating options verbatim from the spec,
  PR number normalisation, and the weekly summary parser, all pure.
- Add POST pr-ratings, which serves the options so the dropdown and the
  validation cannot drift apart. These are deliberately NOT the four
  buckets in services/analytics/fetchGithubReviews.js, which grades
  GitHub review states rather than review quality; two of the names are
  close enough to be mixed up, so that vocabulary is rejected outright.
- Add read, add, import and rate endpoints, all gated on getReports. The
  spec singles out the Owner for PRs Needed and the reviewer groups but
  says only "the person with access" for rating, so rating is open to
  anyone who can see the page.
- Normalise PR numbers on the way in, so 1234, #1234, PR 1234, FE-1234,
  fe 1234 and a full GitHub pull URL all work, keeping a repo prefix
  where one is given.

The weekly summary import is built because the spec asks for it, and I
do not trust it. It has never run against a real summary: zero profiles
on dev have any weekly summary text at all, so there is no sample of how
people write PR numbers and the patterns are assumptions. It is
deliberately conservative, wanting an explicit marker rather than a bare
number in prose, entries land with source "weeklySummary" so they can be
told from typed ones, and the response always warns that the results are
suggestions. The synced pullRequestReview data remains the better source
and that is open question 2 to Jae.

Verified live against dev: normalisation of every accepted format, the
409 on a duplicate, rejection of the analytics vocabulary, backfill into
a past week, half a week rejected, grouping newest week first, rating set
and cleared, and the import correctly reporting that it found nothing.
History checked on the real table, including one reviewer whose weeks run
2025 week 38, 2025 week 52, 2026 week 1, which exercises the year-aware
grouping across a boundary. Test entries removed afterwards.

Suite: 145 of 146 suites pass, 2195 tests. The one failure is
reasonSchedulingController, a database integration suite unrelated to
this work that times out under contention and passes standalone in 19s.
…_insights_visual_indicators_be

Sireesha taking over for Linh - Material Usage Insights Backend APIs and Calculations
The job listing page at /collaboration is reachable without signing in, and
its FAQ section reads from GET /faqs. Opens that one route in the global
auth allowlist and drops its verifyToken guard. Matched on the exact path so
the search, history, unanswered and write routes stay authenticated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…vent-Button-clean

Bosu taking over for Manvitha- Event Reschedule Button
…-most-expensive-endpoint

Amaresh - Phase 2 Summary Dashboard: Fix issue chart endpoints (BE) for PR #4608
…us-donut-backend

Shreevaths taking over for Saicharan - Project status summary API for donut chart (backend)
The "+ Add New" column had only a per reviewer read, so a table showing it
for a page of reviewers made one request, and one query, per row. This adds
the bulk read promised to the frontend on 09-01:

  POST /api/promotion-eligibility/pr-entries  { requestor, reviewerIds: [...] }
  -> { reviewers: { "<id>": { weeks: [...] } } }

Every id sent comes back as a key, including reviewers with nothing listed,
so the client never has to tell "no entries" apart from "id missing from the
response". The per reviewer value is the identical shape the single reviewer
route returns, so only the read location changes on the client.

One query for the whole batch, ids deduplicated first. The single reviewer
route stays, since it is still the better one to hit right after an add or a
rating change when only one row needs refreshing.

13 tests covering the keying, the empty reviewer, week ordering, the single
query, deduplication, the validation cases and the 403 and 500 paths.
…ummary_stats

Ansh - fix Total Org Summary badge stats aggregation
…jury-Trend-Chart

Purav taking over: create injury trend chart
…s-Zero

Gayatri -Fix taskHours always returning 0 in getTaskAndProjectStats
…e-styling-for-ApplicantVolunteerRatio-chart-backend

HANDIKA: update wrong import for applicant volunteer ratio router
…otion-eligibility-dashboard-backend

Sitaram - PRs Needed bands, reviewer groups, weekly requirements, History, PR ratings and Process Promotions
…q_endpoint

Aditya - Job Application Listing Page: allow public read access to the FAQ list
…_BSTimeOff

Revert "Diya 🔥 fix(timeOff): Fixed BS emails for timeoff"
…bility-bug-fix

Ruthwik fix the share availability bug for events
…Create-permission-to-see-and-interact-with-the-deadline-tracking-details

Roshini Seelamsetty: Create permission to see and interact with the deadline tracking details
…nnaire-Profile-ID

Bosu - fix: expose user profile id in HGN questionnaire responses
…leted_date_filter

Akshay Fix Task Completed chart date filtering

This branch was successfully deployed

1 active deployment
Production — 23d3a4f0 Deployed Oct 7, 2026 by one-community via deploy #1253
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Do Not Review Do not review or look at code without full context Needs New Developer This is a PR that is partially developed but needs someone new to take it over and finish it.

Projects

None yet

Development

Successfully merging this pull request may close these issues.