Skip to content

Ascendly Scorecard — System Documentation

Status: Eight operational scorecard entry surfaces + configurations (MongoDB). Bulk Excel upload on ATW, SBS, Non-SBS, Additional Points, and Incidents. Weekly locking for SBS / Non-SBS / ATW (optional; off by default). L5 timely excuse on SBS / Non-SBS (late/excused badges + filter). BSC cycle + month list filters on SBS / Non-SBS (compact float UI shared across tabs). Similar entry warning on form Save and upload preview (five main types). Additional Points for discretionary BSC boosts; Incidents for conduct records that feed bonus qualification. BSC dashboard and cycle versioning documented separately.
See also: Fiscal cycles & locks (fiscal cycles, task delivery, finalized-month locks), Weekly locking, List filters, User-month calculation § Bonus qualification, BigQuery dashboard.

Last updated: July 20, 2026


Table of contents

  1. Overview
  2. Architecture
  3. Use cases by page
  4. MongoDB collections
  5. API reference
  6. Document schemas
  7. Calculations and derived fields
  8. List, filter, and export pipeline
  9. Audit logging
  10. Frontend structure
  11. Feature parity matrix
  12. Known limitations and Phase 2 notes
  13. Source file index

User guides: Similar entry warning (duplicate check) — advisory prompt on form Save and on bulk upload preview when a matching entry may already exist. Weekly locking — mid-month locks for SBS / Non-SBS / ATW and effect on bonus qualification. Missing/Excess Evals — month gaps plus W1–W4 presence and on-time.


1. Overview

The scorecard module is Ascendly’s operational layer for recording and reviewing employee performance data. It consists of eight entry pages (seven submission surfaces plus task delivery), each backed by MongoDB collections and FastAPI routes under /v1/scorecard.

PageRoute segmentCollectionPrimary purpose
SBS (Side-by-Side)sbstbl_sbs_entriesLive observation: manager scores task execution with a weighted Yes/No/N/A rubric
Non-SBSnon-sbstbl_non_sbs_entriesOutput review; BSC 2025: auditor score. BSC 2026+: same checklist as SBS
Attitude Towards Workattitude-towards-worktbl_atw_entriesPositive conduct signals (impact, attitude, rating × multiplier)
Attendance Issuesattendance-issuestbl_attendance_issuesAbsenteeism, tardiness, over-breaks, etc.
Productivity Issuesproductivity-issuestbl_productivity_issuesCall-outs, performance issues, etc.
Additional Pointsadditional-pointstbl_additional_points_entriesDiscretionary percentage boosts to a KPM or KPI for a month
Incidentsincidentstbl_incidentsNTE, Incident Reports, CAR, Coaching logs — feeds bonus qualification
Task Deliverytask-deliverytbl_task_delivery_entriesDaily finished tasks / task count on scheduled workdays (BSC KPI)

Supporting data (same MongoDB database, not scorecard pages):

CollectionRole in scorecard
tbl_employeesEmployee identity, hire date (tenure), org links, auth; bsc_status gates scorecard pickers and new entries
tbl_departments, tbl_clustersOrg hierarchy for filters and table enrichment
tbl_tasksPer-task goal targets by tenure band (SBS / Non-SBS quantity score)
tbl_logsAudit trail for create/update/delete

BigQuery today: Optional GET /v1/scorecard/me reads pre-aggregated KPI rows from scorecard_kpis (or stub data). Entry CRUD does not use BigQuery yet.


2. Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│  Web (React) — web/src/pages/scorecard/                                 │
│  Eight entry pages + shared filters, tables, modals, export             │
└───────────────────────────────┬─────────────────────────────────────────┘
                                │ REST /v1/scorecard/*
┌───────────────────────────────▼─────────────────────────────────────────┐
│  API (FastAPI) — api/app/routers/v1/scorecard.py                        │
│  CRUD → audit_log │ List → facet + table_rows + in-memory filter/sort   │
└───────────────────────────────┬─────────────────────────────────────────┘

        ┌───────────────────────┼───────────────────────┐
        ▼                       ▼                       ▼
   MongoDB                 tbl_tasks              BigQuery (optional)
   (5 entry collections)   (goals)                scorecard_kpis → /me only

Design choices:

  • Single MongoDB database (MONGO_DB, default channel_precision) — all collections in one DB.
  • Pydantic schemas validate API input; Mongo stores flexible BSON documents.
  • Server-derived fields — tenure, duration, SBS scores, goals, etc. are computed on the API and persisted (clients cannot set tenure directly).
  • Table lists — date filter in Mongo; search, org facets, and sort often applied in Python after loading up to 5,000 documents per request.

3. Use cases by page

3.1 SBS (Side-by-Side)

Who: Managers evaluating employees while observing task execution.

Workflow:

  1. Select employee, task evaluated date, brand, task name, duration (h/m/s), auditor’s score, item count.
  2. Complete 17 checklist criteria (Preparedness ×4, Creation ×4, Submission ×4, Red flags ×5) as Yes / No / N/A, with optional section comments.
  3. Submit → API stores entry and computes tenure, SBS %, integrity, timeliness, quantity metrics.
  4. Browse table with BSC cycle + month, org, search, and timely status filters; sort by employee or task date.
  5. View full submission in read-only modal; edit or delete via context menu (delete is soft — see §3.11 Recently deleted).
  6. Bulk select rows → export Excel, resync calculated fields, or multi-delete (soft).
  7. Page actions — floating hub (bottom-right) expands on hover to Activity log and Recently deleted (when permitted).

Business rules:

  • Duration cannot be all zero (h, m, s all 0).
  • Any red-flag answer No zeros SBS percentage and timeliness.
  • submitted_by_id tracks who filed the evaluation.

3.2 Non-SBS

Who: Reviewers scoring output (no live side-by-side observation for BSC 2025; checklist added for BSC 2026+).

Workflow by fiscal cycle:

Eval date fiscal cycleForm fields
BSC 2025 (through Jun 2026)Duration, auditor’s score, items, comment — no checklist (existing rows only — see below)
BSC 2026+ (Jul 2026 onward)Duration, items, comment, same Yes/No checklist as SBS (per-cycle rubric) — no auditor score

Create / upload closed for BSC 2025: New SBS and Non-SBS entries (form create and bulk upload) must use a task-evaluated date in BSC 2026 or later (July 2026 onward). Historical BSC 2025 rows remain viewable and editable. Upload templates are checklist-only (BSC 2026).

Derived fields: tenure, duration, output, goal, quantity_score; BSC 2026+ also stores checklist scores (score, sbs_percentage_score, etc.).

Resync: POST /non-sbs-entries/resync-tenure recalculates tenure + calculated fields (quantity and checklist when applicable).

3.3 Attitude Towards Work (ATW)

Who: Managers recording positive attitude / conduct signals.

Workflow:

  1. Record employee(s), date of occurrence, impact (Team / Other Departments / Company).
  2. Impact drives level and base rating (5.0 / 7.0 / 10.0).
  3. Choose attitude (12 fixed categories), multiplier, remarks; final_score = rating × multiplier (stored as submitted).
  4. Table supports by entry vs by employee aggregated views with impact drilldown.
  5. Bulk create on form — multiple employees in one submit.
  6. Export all rows matching current filters (no row selection export).

On Save, you may be prompted if a similar entry already exists for the same employee, date, attitude, impact, remarks, and multiplier.

ATW entry requests (employee submit → manager approve):

Employees (desktop My ATW or web when enabled) submit requests for the current month with the same fields as a manager ATW entry plus optional proof image (stored in S3 when configured). Managers review on the web ATW page via the Entry requests action (badge shows pending count).

StepActorResult
SubmitEmployeepending request; managers notified
ApproveManager (scorecard submit permission)Creates tbl_atw_entries row; employee notified
RejectManagerRequest closed with review note; employee notified
CancelEmployee (own pending request)Request withdrawn

API: /v1/atw-entry-requests (not under /v1/scorecard). See § 5.4a.

3.4 Attendance Issues

Who: HR / managers logging attendance violations.

Fields: employee, date of occurrence, type (Absenteeism | Tardiness), violation (Absent, Late, Missed Bio Log, Over-break, Undertime, Not Working), comment.

Workflow: Filtered table, create/edit modal, filter-based export, context menu (copy timestamp, edit, delete). On Save, you may be prompted if a similar entry already exists for the same employee, date, and violation.

3.5 Productivity Issues

Who: Managers logging productivity / performance call-outs.

Fields: employee, date of occurrence, brand, task evaluated, reason for occurrence (free text).

Workflow: Same pattern as attendance issues. On Save, you may be prompted if a similar entry already exists for the same employee, date, task, brand, and reason.

3.6 Additional Points

Who: Managers awarding discretionary BSC percentage boosts when an employee exceeds expectations (e.g. treat Productivity as 100% for a month despite lower eval averages).

Route: /scorecard/additional-points — first item in the secondary sidebar nav (after the divider, before Incidents).

Fields: employee, date of occurrence, target level (KPM or KPI), target (from that month’s Balance Scorecard Metrics config), points (integer 1–100; 1 point = 1%), reason.

BSC effect (live compute, dashboard, and BigQuery sync after re-sync):

TargetEffect
KPIAdd points directly to that KPI score (min(100, base + points)).
KPMAdd points directly to the KPM total (min(100, weighted KPI sum + points)). Individual KPI scores are unchanged; Total BSC uses the boosted KPM total.

Workflow: Filtered table (Employee, Date, KPM/KPI, Points, Reason), create/edit modal, filter-based export, soft delete + recycle bin, bulk Excel upload (template → preview → commit).

Month lock: Same as other entry types — finalized months block create/edit/delete for access levels 1–4 (level 5 may override).

See User-month calculation § Additional points and BigQuery dashboard.

3.7 Incidents

Who: HR / managers logging formal conduct incidents (NTE, Incident Report, CAR, Coaching log).

Route: /scorecard/incidents — secondary sidebar nav, after Additional Points.

Fields: employee, incident date (incident_date), incident type (NTE | IR | CAR | Coaching log), reason (free text).

BSC effect: Incidents do not change KPI or total BSC scores. Active incidents in a calendar month block bonus qualification for that month (see User-month calculation § Bonus qualification). Re-sync the affected user-month after incident create/update/delete/restore.

Workflow: Filtered table (org, date, incident type, search), create/edit modal, filter-based export, soft delete + recycle bin, bulk Excel upload. Same month-lock and page-actions pattern as attendance/productivity.

3.8 Task Delivery

Who: Managers entering daily output counts for BSC-enabled employees on scheduled task-delivery days only.

Workflow:

  1. Open Task Delivery — month grid (employees × calendar days).
  2. Filter by org/month like other scorecard pages.
  3. Click a workday cell or open employee detail → edit finished tasks and task count.
  4. Off days / non-TD day codes (OFF, H, VL, etc.) show the schedule abbreviation and are not editable.
  5. Missing (past TD day, no entry) — red highlight; counts as 0% in the month average.
  6. Pending (today, no entry yet) — amber highlight; excluded from average until saved.
  7. Future TD days may be entered early (excluded from average until that day).

Month average: Uses scheduled task-delivery days through today (Eastern). Hover Avg (to date) header or cell for scored / missing / pending / N/A breakdown.

BSC: Contributes task_delivery KPI when the active metrics bundle includes it (BSC 2026 metrics from July 2026 onward — see Fiscal cycles & locks).

Locks: If the dashboard month is finalized, edits are blocked for most users (disabled UI + API 409); level 5 may override or reopen the month on the BSC dashboard.

3.9 Configurations

Route: /scorecard/configurations

Per BSC fiscal cycle (dropdown): eval quotas, balance scorecard metrics, total score goals, SBS checklist rubric, schedule day codes. Upcoming cycles are editable; active/ended cycles are read-only for cycle-specific bundles.

Global (not per cycle):

  • Schedule day codes — catalog for employee schedules
  • Brands list — suggested brand names for SBS, Non-SBS, and Productivity entry forms (GET /v1/scorecard/brands). Users can type custom values; the API auto-appends unseen brands on create/update (case-insensitive dedup). Managed under Brands List tab with export, bulk merge, and replace.
  • Weekly Locking — master enable, week day ranges, lock clock time/timezone, effective_from, allow_update_locked_entries, and per-total weekly quota distribution (see §3.13)

3.10 Bulk file upload (ATW, SBS, Non-SBS, Additional Points, Incidents)

Pages: Attitude Towards Work, SBS, Non-SBS, Additional Points, IncidentsUpload button (or split-button Upload on Additional Points / Incidents) opens a modal (same permission as create entry).

Flow:

  1. Download template — personalized .xlsx for the logged-in user (employee dropdown scoped to scorecard jurisdiction).
  2. Fill rows on the Entries sheet (Excel dropdowns for employees, tasks, brands, checklist values where applicable).
  3. Preview — per-row validation with errors before commit. On SBS, Non-SBS, ATW, Attendance, and Productivity uploads, valid rows may show Similar existing? when they match an active entry (see §3.12).
  4. Commit — inserts valid rows only; shows created / skipped / failed receipt. Duplicate check is not re-run on commit (preview only, for speed).

Rules:

  • .xlsx only, max 5 MB.
  • Submitted-by and timestamps come from the authenticated user (not template columns).
  • Month-finalization locks apply per row date (same as manual create).
  • When weekly locking is enabled, preview flags / rejects SBS, Non-SBS, and ATW rows whose entry dates fall in a locked week (same rule as manual create; level 5 may bypass).
  • SBS/Non-SBS derived fields (tenure, scores, quantity metrics) match form create.
  • SBS / Non-SBS: rows with task dates in BSC 2025 are rejected on preview/commit (create/upload closed for that cycle).

API: see §5.10 Bulk upload endpoints.

UI modules: shared/ScorecardUploadFileStep.tsx, per-page *UploadModal.tsx, *UploadPreviewTable.tsx.

SBS-only: row context menu Duplicate as new entry opens the create form pre-filled from an existing row with today's evaluation date (intentional copy — not the same as the similar entry warning).

Pre-submit / pre-upload: Form Save and upload preview may warn if a similar entry already exists (see §3.12). You can still submit or upload after confirming.

3.11 Recently deleted (recycle bin)

Pages: SBS, Non-SBS, ATW, Attendance Issues, Productivity Issues, Additional Points, Incidentsnot Task Delivery.

Purpose: Recover accidental deletes while the entry month is still open, or permanently remove bin items before the cron backstop runs.

UI:

  1. Hover (or tap) the page actions hub at bottom-right → Recently deleted satellite button (badge shows recoverable count).
  2. Drawer lists soft-deleted entries in org scope while the entry’s occurrence month is still open (not finalized) — shows employee, date, summary, who deleted, when.
  3. Click rows to select; use toolbar Restore selected or Delete permanently (permission-gated).
  4. Task Delivery keeps a standalone Activity log button only (no recycle bin).

Permissions:

ActionScorecard permission
Open bin (list)edit or delete
Restoreedit + month not finalized
Permanent delete (UI)delete + same retention window

Retention:

  • Entry date of occurrence must fall in a calendar month that is not finalized (same gate as scorecard edits).
  • After the month is finalized, the worker job purge_soft_deleted hard-deletes expired soft-deleted rows (replaces the legacy cron script).
  • Entries without a parseable occurrence date stay in the recycle bin until manually purged — they are not auto-deleted.

Notifications: When an entry is soft-deleted, the evaluated employee receives an in-app notification (scorecard.{kind}.deleted_for_you). Desktop Home refetches scorecard queries when such notifications arrive.

Soft-delete fields (on entry documents while in bin): deleted_at, deleted_by_employee_id, deleted_by_full_name. Active lists, facets, BSC compute, exports, and dashboard self view exclude soft-deleted documents.

API (per submission kind — replace {resource} with sbs-entries, non-sbs-entries, atw-entries, attendance-issues, productivity-issues, additional-points, or incidents):

MethodPathPurpose
GET/{resource}/deletedList recoverable deletions in actor scope
POST/{resource}/restoreBatch restore { entry_ids: string[] }
POST/{resource}/purgeBatch permanent delete (soft-deleted rows only)

Restore recalculates SBS/Non-SBS derived fields. Audit actions: delete on soft delete, restore on recovery, delete on permanent purge (with before snapshot).

3.12 Similar entry warning (duplicate check)

Pages: SBS, Non-SBS, Attitude Towards Work, Attendance Issues, Productivity Issues — on form Save and bulk upload preview. Not Task Delivery, Additional Points, or Incidents.

Purpose: Reduce accidental double-entry when a manager submits the same scorecard record twice.

When it runs:

SurfaceTrigger
Entry formClick Save on create or edit (not while typing)
Bulk uploadFile preview only — preview table column Similar existing?; confirm on Upload. Commit/import skips the check for speed.

Behavior:

  1. Ascendly compares your form against active entries (not recycle-bin rows).
  2. If one or more similar entries exist, a confirmation dialog appears, for example: “A similar entry may already exist…” with a short summary of the match (task, violation, etc.) and submission timestamp.
  3. Cancel returns you to the form unchanged. OK / Submit anyway saves the entry — the warning is advisory only; the system never hard-blocks a submit for this reason.
  4. When editing an entry, the row you are editing is excluded from the match list.

What counts as “similar” (same)?

Two entries are treated as similar when all fields in the row below match (after trimming spaces). This is not a full document comparison — scores, comments, rubric answers, and submission timestamps are ignored.

PageTreated as similar when all of these matchCan differ and still trigger a warning
SBS / Non-SBSEmployee, task evaluated date, task evaluated, brandChecklist scores, duration, item count, comment, auditor score, submitter
Attitude Towards WorkEmployee, date of occurrence, attitude, impact, remarks, multiplierLevel, rating, final score, submitter
Attendance IssuesEmployee, date of occurrence, type of violation, violationComment, submitter
Productivity IssuesEmployee, date of occurrence, task evaluated, brand, reason for occurrenceSubmitter

Examples:

  • SBS: Same employee, date, task, and brand as an existing eval → warning, even if the new checklist scores differ.
  • SBS: Same employee and date but a different task nameno warning (multiple evals per day are normal).
  • ATW: Same employee, date, attitude, and impact but different remarksno warning (same-day entries with different reasons are normal).
  • ATW: Same employee, date, attitude, impact, remarks, and multiplier → warning.
  • Attendance: Same employee, date, Tardiness, and Late → warning.
  • Productivity: Same employee, date, task, and brand but a different reasonno warning.

Not the same as:

FeatureDifference
SBS “Duplicate as new entry” (context menu)You choose to copy an existing row into a new form with today’s date — intentional re-entry.
SBS / Non-SBS eval quota warningWarns when monthly eval count would exceed the configured quota — not whether the same task was already evaluated.
Task DeliveryOne row per employee per work day is enforced separately (overwrite on save, not a “similar entry” prompt).
Bulk Excel uploadDuplicate check runs on preview only (one batched query); commit/import skips it for speed. Preview table column Similar existing?

API: GET /v1/scorecard/duplicate-entry-check — query params depend on entry_type; returns up to five matching entries. See §5.11.

Implementation: api/app/domains/scorecard/shared/duplicate_entry_check.py, api/app/domains/scorecard/shared/duplicate_entry_upload.py, web/src/pages/scorecard/shared/useDuplicateEntryCheck.ts. Design logs: design-log/2026-07-14-scorecard-duplicate-entry-check-form.md, design-log/2026-07-14-scorecard-duplicate-entry-check-upload.md.

3.13 Weekly locking (SBS / Non-SBS / ATW)

Status: Live (feature off by default — enable under Configurations → Weekly Locking).
Design log: design-log/2026-07-14-scorecard-weekly-locking.md.
See also: Month finalize locks in Fiscal cycles & locks; bonus gate in User-month calculation § Bonus qualification.

Weekly locking sits on top of month finalize. While a calendar month is still open (not final), SBS / Non-SBS / ATW can lock by week of entry date so managers submit evenly through the month. Attendance, Productivity, Additional Points, Incidents, and Task Delivery are not under weekly locks.

How weeks are defined

Each calendar month is split into admin-editable day-of-month ranges on the entry date (task_evaluated_date for SBS/Non-SBS, date_of_occurrence for ATW) — not on when the form was saved.

Week (default)Entry-date daysAuto-lock dayLock clock (default)
W11–788:00 PM Asia/Manila
W28–14158:00 PM Asia/Manila
W315–21228:00 PM Asia/Manila
W422–end of month29 (clamped to EOM)8:00 PM Asia/Manila

ATW vs SBS / Non-SBS (W4 tail): When W4 locks on the 29th, SBS / Non-SBS block the whole range (22–EOM). ATW only blocks occurrence dates before the lock day (22–28); days 29–31 stay creatable until month finalize — same idea as W1–W3, where the lock calendar day itself stays open.

Ranges, lock days, clock time, and timezone are editable in Configurations → Weekly Locking. Changing the schedule is live: the next resolution / sync uses the new schedule (no freeze of the old deadline unless you rely on a manual override).

What a locked week blocks

Effective lock = manual override if set, else now ≥ scheduled lock datetime.

ActionLocked weekOpen week
Create with entry date in that weekBlocked (levels 1–4)Allowed
Edit non-date fieldsAllowed if allow_update_locked_entries (default on); else blockedAllowed
Change entry dateAlways blocked while the week is lockedAllowed (target week must also be editable)
DeleteSame as edit non-date fieldsAllowed
  • Later weeks stay creatable after earlier weeks lock.
  • Level 5 bypasses weekly hard locks the same way as month finalize.
  • Month finalize still locks the whole month; manual weekly lock/unlock is 409 while the month is final (reopen first).
  • Enforced on forms, bulk upload, and ATW request submit/approve paths.

UI: On SBS / Non-SBS / ATW, open the page 3-dot actions menu → weekly locks modal (status + Lock / Unlock for level 5). Forms show a locked-week banner and disable Submit when the chosen date’s week is locked.

Manual lock / unlock (level 5)

Admins unlock a week so managers can still submit late operational entries (backfills). Unlock does not change the scheduled deadline used for bonus — see below.

How weekly locking affects bonus qualification

A sixth bonus gate, timely weekly submission, runs for SBS + Non-SBS when cadence applies to that month:

ConfigWhen cadence applies
effective_from set (e.g. 2026-07)Months on/after that month — even if hard locking is temporarily disabled
effective_from blankOnly while Enable weekly locking is on

For each employee-month:

  1. Tenure quotas determine required SBS / Non-SBS totals (same as eval quotas).
  2. Those totals are split into per-week increments (configurable distribution; defaults e.g. Non-SBS 5 → 2/1/1/1, SBS 3 → 1/1/1/0).
  3. Entries are bucketed by entry-date week.
  4. An entry counts as on-time for that week only if createdAt is before the week’s scheduled lock datetime.

Hard lock vs bonus (important):

Hard weekly lockBonus timely gate
PurposeBlock/allow create & date editsScore whether submissions met the schedule
Unlock weekLets managers still createDoes not grant on-time credit
What time is usedLive effective lock (schedule + override)Scheduled lock only
ATWLocked like SBS/Non-SBSNot in the bonus cadence

Moving a lock day in Configurations (e.g. W1 lock day 8 → 9) does change the scheduled deadline on the next BSC sync, so a create that was late under the old schedule may become on-time under the new one (if createdAt is still before the new instant). Re-sync to refresh qualification.

Timely excuse (level 5): On SBS / Non-SBS, level 5 can mark an entry Excused with a required reason (POST …/excuse) or clear it (DELETE …/excuse) from the table / view modal. Badges show Late / Excused. List filters include a Timely status dropdown (late, excused). Excused entries count as on-time for bonus cadence and Missing/Excess even when submitted after the scheduled lock. Unlock alone never excuses. No auto-excuse.

Full check list and examples: User-month calculation § Bonus qualification.

Go-live tip: Set effective_from to the first month that should use the cadence before turning on Enable for production months.

API / code: GET|POST /v1/scorecard/weekly-locks (+ /lock, /unlock); settings on scorecard config; api/app/domains/scorecard/shared/week_lock.py, api/app/domains/bsc/timely_weekly_submission.py. Approaching-lock reminders: notification type scorecard.weekly_lock.approaching (see Notifications).

3.14 Missing/Excess Evals (monthly + weekly)

Route: /scorecard/missing-excess-evals (read-only).

Compares SBS / Non-SBS counts vs tenure quotas for selected calendar months (department → employee drill).

When exactly one month is selected and weekly submission cadence applies (same rules as §3.13 / bonus gate):

  • Each SBS / Non-SBS cell shows the month actual / required, plus W1–W4 chips:
    • Presence = entries whose entry date falls in that week.
    • Status: On time (enough presence created before the scheduled lock), Late (presence met but created after schedule), Short (not enough presence), or (no weekly requirement).
  • Unlocking a week can fill presence late; late chips still show Late (aligned with bonus).
  • Level 5 may excuse a late SBS / Non-SBS entry (required reason). Excused entries count as on-time for bonus and show e.g. 1 excused on week chips; they do not invent presence if the week is still short.
  • Rows with any short/late week are treated as incomplete even if the month total is met.

Multi-month selection (or cadence not active) keeps the classic month-only columns.

API: GET /v1/scorecard/missing-excess-evals — rows include weeks_enabled, sbs_weeks, non_sbs_weeks.


4. MongoDB collections

CollectionConstant (collections.py)Written by
tbl_sbs_entriesTBL_SBS_ENTRIESSBS CRUD
tbl_non_sbs_entriesTBL_NON_SBS_ENTRIESNon-SBS CRUD
tbl_atw_entriesTBL_ATW_ENTRIESATW CRUD
tbl_atw_entry_requestsTBL_ATW_ENTRY_REQUESTSEmployee ATW submit; manager approve/reject
tbl_attendance_issuesTBL_ATTENDANCE_ISSUESAttendance CRUD
tbl_productivity_issuesTBL_PRODUCTIVITY_ISSUESProductivity CRUD
tbl_additional_points_entriesTBL_ADDITIONAL_POINTS_ENTRIESAdditional points CRUD
tbl_incidentsTBL_INCIDENTSIncidents CRUD
tbl_task_delivery_entriesTBL_TASK_DELIVERY_ENTRIESTask delivery day upsert
tbl_scorecard_configTBL_SCORECARD_CONFIGPer-cycle BSC config + bsc-cycle-settings

Connection: MongoDB connection settings are configured on the server (MONGO_URI, MONGO_DB).

Indexes at startup (api/app/main.py): employees, clusters, departments, enrollments, productivity issues, logs. Scorecard entry collections do not yet have dedicated startup indexes.


5. API reference

Base path: /v1/scorecard

5.1 Shared query parameters (list & facet endpoints)

ParameterDescription
date_modenone, month, year, exact, range
month_values, year_values, exact_dates, range_datesDate filter values (format depends on mode)
occurrence_year, occurrence_month, exact_date, year_value, range_start, range_endAlternate date param names (legacy compatibility)
searchFree-text search on enriched table rows
cluster_ids, department_ids, employee_idsComma-separated org filters
timely_flagsSBS / Non-SBS only — comma-separated late and/or excused (empty = all)
sort_byColumn key (varies by entity)
sort_dirasc or desc
page, page_sizePagination (list endpoints only)

UI note (SBS / Non-SBS): The filter float picks a BSC cycle and one or more months in that July–June window. The client still sends date_mode=month + month_values (empty month selection expands to all twelve months in the cycle). cycle_id is persisted in the URL / session for the float only — not a Mongo query param.

Date field per entity:

EntityMongo date field
SBS, Non-SBStask_evaluated_date
ATW, Attendance, Productivity, Additional Pointsdate_of_occurrence
Incidentsincident_date

5.2 SBS entries

MethodPathPurpose
GET/sbs-entriesPaginated table list
GET/sbs-entries/facet-sourceCascading filter options
GET/sbs-entries/matching-selectionAll entry IDs matching filters (bulk select)
GET/sbs-entries/{entry_id}Single entry (form/view)
POST/sbs-entriesCreate
PATCH/sbs-entries/{entry_id}Update
DELETE/sbs-entries/{entry_id}Soft delete (sets deleted_at; excluded from active lists)
GET/sbs-entries/deletedList recoverable soft-deleted entries
POST/sbs-entries/restoreBatch restore
POST/sbs-entries/purgeBatch permanent delete (bin items only)
POST/sbs-entries/export-rowsExport table rows by ID list (1–500)
POST/sbs-entries/resyncRecalculate server-derived fields for ID list (1–200)
POST/sbs-entries/resync-tenureHidden legacy alias of /resync
GET/sbs-entries/upload/templateDownload personalized SBS upload workbook
POST/sbs-entries/upload/previewValidate uploaded workbook (multipart file)
POST/sbs-entries/uploadCommit valid rows from workbook
POST/sbs-entries/{entry_id}/excuseLevel 5 — mark entry excused (body: { reason })
DELETE/sbs-entries/{entry_id}/excuseLevel 5 — clear timely excuse

5.3 Non-SBS entries

Same as SBS except:

  • Resync: POST /non-sbs-entries/resync-tenure (tenure + quantity fields)
  • Export: POST /non-sbs-entries/export-rows
  • Upload: GET/POST …/non-sbs-entries/upload/template|preview|upload
  • Recycle bin: GET/POST …/non-sbs-entries/deleted|restore|purge
  • Excuse: POST|DELETE /non-sbs-entries/{entry_id}/excuse (same level-5 rules as SBS)

5.4 ATW entries

MethodPathPurpose
GET/atw-entriesPaginated list
GET/atw-entries/facet-sourceFacets
GET/atw-entries/exportAll filtered rows
GET/POST/PATCH/DELETE/atw-entries/{entry_id}CRUD (DELETE is soft)
GET/atw-entries/deletedRecycle bin list
POST/atw-entries/restore, /atw-entries/purgeRestore / permanent delete
GET/atw-entries/upload/templateDownload personalized ATW upload workbook
POST/atw-entries/upload/previewValidate uploaded workbook
POST/atw-entries/uploadCommit valid rows

5.4a ATW entry requests

Base path: /v1/atw-entry-requests (top-level router, not under /v1/scorecard).

MethodPathPurpose
GET``List — scope=mine (employee) or scope=approval (manager pending queue)
GET/pending-countPending count for manager badge (requires scorecard submit)
POST``Submit (multipart: fields + optional proof image)
GET/{request_id}Single request
GET/{request_id}/proof-urlPresigned S3 URL for proof image
DELETE/{request_id}Employee cancel (pending only)
POST/{request_id}/approveManager approve → creates ATW entry
POST/{request_id}/rejectManager reject with review_note

5.5 Attendance issues

MethodPathPurpose
GET/attendance-issuesPaginated list
GET/attendance-issues/facet-sourceFacets
GET/attendance-issues/exportAll filtered rows
GET/POST/PATCH/DELETE/attendance-issues/{issue_id}CRUD (DELETE is soft)
GET/attendance-issues/deletedRecycle bin list
POST/attendance-issues/restore, /attendance-issues/purgeRestore / permanent delete

5.6 Productivity issues

MethodPathPurpose
GET/productivity-issuesPaginated list
GET/productivity-issues/facet-sourceFacets
GET/productivity-issues/exportAll filtered rows
GET/POST/PATCH/DELETE/productivity-issues/{issue_id}CRUD (DELETE is soft)
GET/productivity-issues/deletedRecycle bin list
POST/productivity-issues/restore, /productivity-issues/purgeRestore / permanent delete

5.7 Additional points

MethodPathPurpose
GET/additional-pointsPaginated list
GET/additional-points/facet-sourceFacets
GET/additional-points/exportAll filtered rows
GET/POST/PATCH/DELETE/additional-points/{entry_id}CRUD (DELETE is soft)
GET/additional-points/deletedRecycle bin list
POST/additional-points/restore, /additional-points/purgeRestore / permanent delete
GET/additional-points/upload/templateDownload personalized additional points upload workbook
POST/additional-points/upload/previewValidate uploaded workbook
POST/additional-points/uploadCommit valid rows

5.8 Incidents

MethodPathPurpose
GET/incidentsPaginated list
GET/incidents/facet-sourceFacets
GET/incidents/exportAll filtered rows
GET/POST/PATCH/DELETE/incidents/{incident_id}CRUD (DELETE is soft)
GET/incidents/deletedRecycle bin list
POST/incidents/restore, /incidents/purgeRestore / permanent delete
GET/incidents/upload/templateDownload personalized incidents upload workbook
POST/incidents/upload/previewValidate uploaded workbook
POST/incidents/uploadCommit valid rows

5.9 Personal KPIs (BigQuery)

MethodPathPurpose
GET/meCurrent user’s metrics from BigQuery scorecard_kpis (or stub)

Resolves employee_key from JWT user: employee_key field, else employment_data.employee_id, else Mongo _id.

5.10 Bulk upload endpoints

Shared behavior for ATW, SBS, Non-SBS, Additional Points, and Incidents upload routes:

ConcernBehavior
File type.xlsx only (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet or empty content-type with .xlsx name)
Max size5 MB
Template scopeActive BSC employees visible to uploader's scorecard jurisdiction
SubmitterAuthenticated user (submitted_by_id); impersonation header respected
Month lockRows with dates in finalized months rejected for access levels 1–4
Preview responsePer-row errors/warnings; possible_duplicate on five main upload types; derived field preview where applicable
Commit responsecreated_count, skipped_invalid_count, failed_count, per-row failures
MethodPathPurpose
GET/brandsGlobal brands suggestion list (for entry forms and upload templates)

5.11 Pre-submit form checks

Shared read-only endpoints used by entry forms before save.

MethodPathPurpose
GET/eval-quota-checkSBS / Non-SBS only — projected monthly eval count vs configured quota (employee_id, task_evaluated_date, entry_type, optional exclude_entry_id)
GET/duplicate-entry-checkSimilar-entry warning for the five main entry types (entry_type, employee_id, date + type-specific fields; ATW also requires remarks + multiplier; optional exclude_entry_id)

Both return JSON only; the web UI shows window.confirm dialogs on Save. Neither endpoint blocks create/update on the server.

Bulk upload: Duplicate detection for preview uses the same similarity keys via duplicate_entry_upload.py inside POST …/upload/preview (batched query; response fields possible_duplicate / possible_duplicate_count). It does not call GET /duplicate-entry-check. Commit and async import skip the check.


6. Document schemas

Dates are stored as M/D/YYYY strings for occurrence/evaluation dates. Timestamps use M/D/YYYY H:M:S.mmm.

6.1 SBS entry (tbl_sbs_entries)

User-provided (create/update):

FieldTypeNotes
timestampstringSubmission time
employee_idstringSubject employee
task_evaluated_datestringM/D/YYYY
task_evaluatedstringTask name (links to tbl_tasks)
brandstring
submitted_by_idstringSubmitter employee id
hours, minutes, secondsintDuration components (not all zero)
auditors_scoreint0–100
number_of_itemsint1–999999
commentstringGeneral comment
preparedness_14, creation_14, submission_14Yes/No/N/AChecklist
redflag_15Yes/No/N/ARed flags
*_commentstringSection comments (4 fields)

Server-calculated (persisted, not accepted from client on write):

FieldDescription
tenureNewbie / Advance / Intermediate / Tenured
durationDecimal minutes
outputMinutes per item
goalTarget from tbl_tasks for task + tenure
quantity_scoregoal ÷ output, capped 0–1
sbs_actual_score, sbs_total_score, sbs_percentage_scoreWeighted checklist
integrity_score, timeliness, scoreDerived penalties
createdAtUTC datetime (on insert)
lateComputed for list/view — submitted after scheduled week lock
excused, excuse_reason, excused_at, excused_by_employee_idLevel-5 timely excuse (optional)

6.2 Non-SBS entry (tbl_non_sbs_entries)

Same operational and quantity fields as SBS without checklist fields for BSC 2025; BSC 2026+ adds checklist scores. Server fields: tenure, duration, output, goal, quantity_score, plus the same late / excused* timely fields as SBS.

6.3 ATW entry (tbl_atw_entries)

FieldTypeNotes
timestampstringUnique per entry (1ms bump if collision)
employee_idstring
date_of_occurrencestringM/D/YYYY
submitted_by_idstring
impactTeam | Other Departments | Company
attitude12 literalsSee atw_entry.py
levelAverage | Excellent | ExemplaryDerived from impact
ratingfloat5.0 / 7.0 / 10.0 from impact
multiplierfloat≥ 0
final_scorefloatTypically rating × multiplier
remarksstring

Impact → level & rating:

ImpactLevelRating
TeamAverage5.0
Other DepartmentsExcellent7.0
CompanyExemplary10.0

6.4 Attendance issue (tbl_attendance_issues)

FieldValues
type_of_violationAbsenteeism, Tardiness
violationAbsent, Late, Missed Bio Log, Over-break, Undertime, Not Working
+timestamp, employee_id, date_of_occurrence, submitted_by_id, comment

6.5 Productivity issue (tbl_productivity_issues)

FieldNotes
timestamp, employee_id, date_of_occurrence, submitted_by_idStandard
brand, task_evaluated
reason_for_occurrenceFree text

6.6 Additional points (tbl_additional_points_entries)

FieldNotes
timestamp, employee_id, date_of_occurrence, submitted_by_idStandard
target_levelkpm or kpi
target_keyKPM/KPI key from metrics config at save time
target_labelSnapshot label at save time
pointsInteger 1–100 (percentage points to add)
reasonFree text

6.7 Incidents (tbl_incidents)

FieldNotes
timestamp, employee_id, incident_date, submitted_by_idStandard
incident_typeNTE, IR, CAR, or Coaching log
reasonFree text

6.8 Table row API shape (all entry types)

List/facet/export responses enrich each row with:

  • employee_name — from tbl_employees
  • clusters[]{ id, name }
  • departments[]{ id, name, cluster_id }

SBS/Non-SBS rows additionally expose calculated columns for the grid (duration, output, scores, etc.).


7. Calculations and derived fields

Implementation is shared between API (api/app/services/) and SBS UI preview (web/.../sbsScorecardFields.ts). Server values are authoritative on save.

7.1 Tenure

Module: api/app/services/scorecard_tenure.py

  1. Load employment_data.hire_date from tbl_employees by employee_id.
  2. Compute whole months from hire date to evaluation/occurrence date (day-aware).
  3. Map to band:
Months employedTenure label
0–4Newbie
5–8Advance
9–11Intermediate
12+Tenured
  • Missing employee or hire date → Newbie
  • Evaluation before hire date → ValueError (surfaces in resync errors array)

Goal lookup keys: Newbie → newbie, Advance → advance, Intermediate → intermediate, Tenured → tenured in tbl_tasks.goals.

7.2 Duration and output

Module: api/app/services/sbs_entry_calculated.py

duration = hours×60 + minutes + seconds÷60   (decimal minutes, 2 dp)
output   = duration ÷ number_of_items        (0 if items ≤ 0)

7.3 Goal and quantity score

Module: api/app/services/sbs_entry_goal.py

  1. Find tbl_tasks where task_name = task_evaluated.
  2. Read goals[tenure_band].target (float).
  3. If missing → goal = 0.
quantity_score = min(1, max(0, goal ÷ output))   when goal > 0 and output > 0, else 0

Interpretation: ratio of target time-per-item to actual; 1.0 = at or better than goal.

7.4 SBS checklist scoring

Criterion weights (SBS_CRITERION_SCORES):

FieldPoints
preparedness_110
preparedness_2, 3, 45 each
creation_1, creation_35
creation_2, creation_410
submission_1, 3, 410
submission_215

Algorithm:

  1. If any redflag_* = Nosbs_actual_score = 0, sbs_total_score = 0, sbs_percentage_score = 0.
  2. Else for each preparedness/creation/submission criterion:
    • N/A → excluded from total weight
    • Yes → add weight to actual and total
    • No → add weight to total only
  3. sbs_percentage_score = actual ÷ total (0 if total is 0)

7.5 Integrity, timeliness, final SBS score

integrity_score = (sum of weights for criteria marked "No" ÷ 2) ÷ 100
timeliness      = 0 if any red flag is "No", else 1
score           = max(0, timeliness − integrity_score)

All three are stored as ratios (0–1), not percentages.

7.6 Non-SBS calculated fields

Module: api/app/services/non_sbs_entry_calculated.py

Reuses duration, output, goal, quantity_score only — no checklist or integrity/timeliness.

7.7 ATW

No server calculation service. level and rating are set from impact on create/update. final_score is stored as provided (UI computes rating × multiplier).

7.8 Resync behavior

EndpointUpdates
POST /sbs-entries/resynctenure, duration, all SBS scores, output, integrity, timeliness, score, goal, quantity_score
POST /non-sbs-entries/resync-tenuretenure, duration, output, goal, quantity_score

Response: { updated, not_found, errors }. Each successful update writes an audit log entry.


8. List, filter, and export pipeline

Mongo find (date filter only, up to 5000 docs)
    → *_docs_to_table_rows (join employee, dept, cluster names)
    → apply_*_filters (search + org [+ timely_flags for SBS/Non-SBS] in Python)
    → sort_scorecard_table_rows
    → paginate (router) OR return all (export)

8.1 Filter float UI

Each entry page uses a right-rail filter float (same chrome as dashboard scope filters). When expanded (embedded), controls use inline dropdown triggers (label + value on one row):

ControlSBS / Non-SBSOther entry tabs
SearchInline search rowInline search row
PeriodBSC cycle (single-select) + Month (multi-select in that July–June window)Flexible date modes (ScorecardDateFilterFields: none / exact / month / year / range)
Timely statusMulti-select dropdown (late, excused; empty = all)
OrganizationCluster → department → employee cascadeSame

SBS / Non-SBS defaults: active Eastern calendar month’s fiscal cycle and that month (e.g. BSC 2026 + July 2026). Empty current month stays empty — no auto-walk-back to older months with data. Empty month selection = all months in the selected cycle (client expands to twelve YYYY-MM values on the API). Org cascade prune still runs against month-scoped facet rows.

Design note: design-log/2026-07-20-scorecard-bsc-cycle-month-filters.md.

8.2 Facet source pattern

Most entry types (fetch_contextual_*_facets):

  • Org facets (facet_items) — rows after date filter + search only (no org filters).
  • Date facets (date_facet_items) — rows after search + org filters, no date filter (builds year/month/day option lists from entries).

SBS / Non-SBS (optimized):

  • Org facets — same as above (date-scoped).
  • Date facets — always empty. Month options come from the BSC cycle calendar on the client (GET /v1/scorecard/bsc-cycles + cycle_months_all), which removes the previous all-time Mongo hydrate on every filter load.

8.3 Export modes

PagesExport mechanism
SBS, Non-SBSPOST .../export-rows with selected entry_ids
ATW, Attendance, Productivity, Additional Points, IncidentsGET .../export? same filters as list (all matching rows)

Frontend Excel: web/src/pages/scorecard/shared/scorecardExcelExport.ts + per-page *Export.ts.


9. Audit logging

Module: api/app/audit_log.py

On create, update, delete, restore, and resync updates, CRUD calls log_change()tbl_logs.

Resource keyCollection
sbs_entrytbl_sbs_entries
non_sbs_entrytbl_non_sbs_entries
atw_entrytbl_atw_entries
attendance_issuetbl_attendance_issues
productivity_issuetbl_productivity_issues
additional_points_entrytbl_additional_points_entries
incidenttbl_incidents

Log fields include: action, page path, resource, resource_id, actor employee id/key/name, redacted before/after snapshots, changed_fields, API path, HTTP method.

UI: On the seven submission pages (excluding Task Delivery), Activity log and Recently deleted share a page actions floating hub (bottom-right; hover to expand). Task Delivery shows Activity log only. Access level 1 for scorecard activity-log routes.


10. Frontend structure

Routes (web/src/App.tsx):

/scorecard              → index redirect (last segment or SBS)
/scorecard/sbs
/scorecard/non-sbs
/scorecard/attitude-towards-work
/scorecard/attendance-issues
/scorecard/productivity-issues
/scorecard/additional-points
/scorecard/incidents
/scorecard/task-delivery

Layout: layout/ScorecardLayout.tsx — outlet + floating nav rail (sidebar/ScorecardFloatingRail.tsx).

Navigation: sidebar/scorecardNav.ts — primary segments (SBS, Non-SBS, ATW, etc.) plus secondary nav (Additional Points, Incidents, Missing/Excess Evals, Configurations).

10.1 Shared modules (shared/)

ModuleRole
scorecardDateFilterTypes.ts, scorecardDateFilterQuery.ts, scorecardDateFilterLogic.tsDate filter state and API serialization
scorecardCycleMonthFilter.ts, ScorecardBscCycleMonthFields.tsx, bscCycle.tsSBS / Non-SBS BSC cycle + month filter (calendar months, no data walk-back)
scorecardFilterPersistence.tsURL / session persistence for date + org (+ cycle_id, timely_flags)
ScorecardDateFilterFields.tsx, CheckboxDateDropdown.tsxFlexible date filter UI (non–SBS/Non-SBS tabs)
ScorecardInlineSearchField.tsxCompact search row in filter floats
CheckboxOrgDropdown.tsx, filterOptionSearch.tsOrg / cycle / timely facet dropdowns (layout="inline" in floats)
ScorecardTimelyBadges.tsx, ScorecardExcuseModal.tsxLate / excused badges and level-5 excuse dialog
scorecardTableSort.ts, SortableScorecardTh.tsxColumn sorting
scorecardTableRow.tsRow styling
scorecardExcelExport.tsExcel download
durationInputUtils.tsDuration clamp; client duration/output preview
TaskEvaluatedSelect.tsxTask picker (GET /v1/tasks)
ScorecardQuantityCalculatedPanel.tsxRead-only quantity metrics (Non-SBS view)
ScorecardResyncProgressBanner.tsxChunked resync progress
useScorecardActiveEmployeeIds.tsBSC-included employees for forms (bsc_status + active)
useScorecardMonthEditAccess.tsMonth-finalization edit/upload gates
ScorecardUploadFileStep.tsx, scorecardUploadApi.tsBulk upload download + file step
ScorecardPageActionsFloat.tsxFloating hub: activity log + recently deleted satellites
ScorecardDeletedDrawer.tsx, scorecardDeletedTypes.tsRecycle bin drawer (list, restore, purge)
*UploadModal.tsx, *UploadPreviewTable.tsx, *UploadApi.tsPer-page upload flow (ATW, SBS, Non-SBS, Additional Points, Incidents)

10.2 Per-page folders

FolderKey components
sbs_components/SbsTable, SbsFilters, SbsEntryFormModal, SbsEntryViewModal, SbsCalculatedFieldsPanel, sbsScorecardFields.ts
non_sbs_components/Parallel to SBS; NonSbsEntryViewModal
atw_components/AtwTablePanel, employee aggregation, AtwEntryFormModal, AtwEntryRequestsModal, AtwProofImagePicker
attendance_issues_components/Table, filters, form
productivity_issues_components/Table, filters, form
additional_points_components/Table, filters, form, upload (KPM/KPI target picker from month config)
incidents_components/Table, filters, form, upload

React Query keys: ['scorecard', 'resource', ...] and ['scorecard', 'resource-facet', ...] (replace resource with the page key, e.g. additional-points).

10.3 SBS checklist UI

Defined in sbsScorecardFields.ts:

  • Preparedness (4 criteria) — verification, validation, escalations, analysis
  • Creation (4) — source files, data input, naming, review
  • Submission (4) — upload, trackers, notifications, timeliness
  • Red flags (5) — failure indicators; any No fails the submission

Client mirrors server math via computeSbsScores and computeSbsDerivedMetrics for live form preview.


11. Feature parity matrix

FeatureSBSNon-SBSATWAttendanceProductivityAdd. PtsIncidents
Floating filters (org + search)
BSC cycle + month filter
Flexible date modes (exact/month/year/range)
Timely status filter (late / excused)
L5 timely excuse
Compact inline filter float
Paginated sortable table
Create / edit modal
View submission modal
Row bulk selection
Select all matching (API)
Export selected rows
Export all filtered
Resync calculated fields
Yes/No/N/A scorecard form
Multi-delete (selection)
Employee aggregation view
Bulk create (multi employee)
Activity log
Recently deleted (soft delete + restore)
Bulk Excel upload
Similar entry warning on form Save
Similar entry warning on upload preview
Affects BSC user-month scores
Affects bonus qualification

Reference implementation: SBS — other entry-style pages (Non-SBS) should match its selection/export/resync pattern where applicable. Incidents follow the attendance/productivity pattern (export-all, recycle bin, upload); they gate bonus qualification only, not KPI math.


12. Known limitations and Phase 2 notes

Current limitations

  1. In-memory filtering — Up to 5,000 documents loaded per list/facet request; search and org filters run in Python, not Mongo aggregation.
  2. No scorecard collection indexes — Only date filter hits Mongo; consider indexes on task_evaluated_date, date_of_occurrence, employee_id.
  3. Facet cost — Most tabs still run an all-time date-facet hydrate to build month/day options. SBS / Non-SBS skip that scan (cycle calendar on the client). Further wins: org options from /v1/organization/tree or Mongo $distinct, and push org filters into Mongo.
  4. BigQuery scope — Only /me KPI stub/table; entry data is Mongo-only.
  5. Cross-page analytics — BSC dashboard reads user-month aggregates (Mongo and/or BigQuery); operational pages remain separate UIs.
  6. Finalized months — After Generate Final Report on the dashboard, entry edits for that calendar month are locked unless the month is reopened (see Fiscal cycles & locks).
  7. Weekly locking — Optional mid-month locks for SBS / Non-SBS / ATW; off until enabled. See §3.13.

Dashboard + BigQuery (partially implemented)

User-month BSC materialization, rolling sync, finalize/reopen, and dashboard UI are live — see BigQuery dashboard. Raw entry tables are still Mongo-only; BQ holds summarized KPI rows per employee-month.


13. Source file index

API — router & config

PathDescription
api/app/routers/v1/scorecard.pyAll HTTP endpoints
api/app/collections.pyCollection name constants
api/app/config.pyMongo + BigQuery env settings
api/app/bigquery_client.pyfetch_scorecard_rows for /me

API — schemas

PathEntity
api/app/schemas/sbs_entry.pySBS
api/app/schemas/non_sbs_entry.pyNon-SBS
api/app/schemas/atw_entry.pyATW
api/app/schemas/attendance_issue.pyAttendance
api/app/schemas/productivity_issue.pyProductivity (+ shared date parsers)

API — domain layout

Scorecard entry logic lives under api/app/domains/scorecard/<type>/ (crud, facet_source, table_rows, table_query, upload/). HTTP routes: api/app/routers/v1/scorecard/. ATW entry requests: api/app/services/atw_entry_requests.py, api/app/routers/v1/atw_entry_requests.py.

PathEntity
api/app/domains/scorecard/atw/ATW entries
api/app/domains/scorecard/sbs/SBS
api/app/domains/scorecard/non_sbs/Non-SBS
api/app/domains/scorecard/attendance/Attendance
api/app/domains/scorecard/productivity/Productivity
api/app/domains/scorecard/additional_points/Additional points
api/app/domains/scorecard/incidents/Incidents
api/app/domains/scorecard/shared/soft_delete.pySoft delete, restore, purge
api/app/domains/scorecard/shared/duplicate_entry_check.pyPre-submit similar-entry check (forms)
api/app/domains/scorecard/shared/duplicate_entry_upload.pyBatched similar-entry check (upload preview only)
api/app/domains/scorecard/shared/eval_quota_check.pyPre-submit SBS / Non-SBS eval quota check
api/app/domains/scorecard/shared/week_lock.pyWeekly lock resolution + create/edit guards
api/app/domains/scorecard/shared/entry_excuse.pyLevel-5 timely excuse set/clear
api/app/domains/scorecard/shared/timely_flag_filter.pyList timely_flags parse (late / excused)
api/app/domains/scorecard/config/weekly_lock_store.pyGlobal weekly-lock settings document
api/app/domains/bsc/timely_weekly_submission.pyBonus timely weekly submission cadence
api/app/schemas/scorecard_excuse.pyExcuse request body
api/app/routers/v1/scorecard/weekly_locks.pyWeekly lock status + manual lock/unlock API

API — calculations

PathPurpose
api/app/services/scorecard_tenure.pyTenure bands
api/app/services/sbs_entry_calculated.pyDuration, output, SBS scores, integrity, timeliness
api/app/services/sbs_entry_goal.pyGoal + quantity_score
api/app/services/non_sbs_entry_calculated.pyNon-SBS quantity bundle
api/app/services/scorecard_upload_common.pyShared bulk-upload parsing and validation
api/app/services/scorecard_upload_employees.pyJurisdiction-scoped upload employee lists
api/app/services/{atw,sbs,non_sbs}_upload_*.pyPer-type template, preview, commit
api/app/services/scorecard_soft_delete.pySoft delete, restore, purge helpers
api/app/services/scorecard_deleted_entries.pyDeleted list, batch restore/purge
api/app/schemas/scorecard_deleted.pyRecycle bin API models
api/scripts/purge_soft_deleted_scorecard_entries.pyCron hard-delete for expired bin rows
api/app/services/brands_list.pyGlobal brands config + auto-append on entry save

API — list / query

PathEntity
api/app/sbs_entry_list.py, sbs_entry_facet_source.py, sbs_entry_table_rows.py, sbs_entries_table_query.pySBS
api/app/non_sbs_entry_list.py, non_sbs_entry_facet_source.py, non_sbs_entry_table_rows.py, non_sbs_entries_table_query.pyNon-SBS
api/app/atw_entry_facet_source.py, atw_entry_table_rows.py, atw_entries_table_query.pyATW
api/app/attendance_issue_facet_source.py, attendance_issue_table_rows.py, attendance_issues_table_query.pyAttendance
api/app/productivity_issue_facet_source.py, productivity_issue_table_rows.py, productivity_issues_table_query.pyProductivity
api/app/scorecard_date_query.py, scorecard_date_filter.pyShared date filtering
api/app/scorecard_table_sort.pyShared sorting

API — other

PathPurpose
api/app/audit_log.pyChange logging
api/scripts/seed_*_from_*CSV/XLSX seed scripts
api/scripts/bigquery_scorecard_example.sqlBQ KPI table DDL

Web — pages

PathPage
web/src/pages/scorecard/ScorecardSbsPage.tsxSBS
web/src/pages/scorecard/ScorecardNonSbsPage.tsxNon-SBS
web/src/pages/scorecard/ScorecardAttitudeTowardsWorkPage.tsxATW
web/src/pages/scorecard/ScorecardAttendanceIssuesPage.tsxAttendance
web/src/pages/scorecard/ScorecardProductivityIssuesPage.tsxProductivity

Web — SBS rubric

PathPurpose
web/src/pages/scorecard/sbs_components/sbsScorecardFields.tsCriteria labels, weights, client score math

For optional BigQuery dashboard architecture, see BigQuery dashboard.