| Source | What It Contains | How It Gets In |
|---|---|---|
| Golf Genius Roster | Member number, first & last name, GHIN number — the authoritative link between ClubCorp members and GHIN | Manual upload on dashboard |
| GHIN Active Roster | GHIN number, golfer name, H.I., status, email, gender | Automated — GHIN emails report, processed daily at 8am ET (scores) and Monday 8am ET (roster) |
| Scores Posted Report | GHIN number, date played, date posted, AGS, holes, course, differential | Automated — same GHIN email pipeline |
| ClubCorp Tee Sheets | Per-player: ClubCorp ID, name, member code, holes, cart type, member type, player category | Manual upload — save .htm from ClubCorp Tee Times, upload per course per day |
The tool connects tee sheet players to roster members, then checks whether their scores were posted. This happens in three steps.
Step 1 — Identify the Player
Every tee sheet entry includes a member number (e.g., S0262). The system looks up that number in the Golf Genius Master Roster:
| Scenario | What Happens |
|---|---|
| Only one member on that code | That's the member. Done — no name matching needed. |
| Multiple members on that code | Check if the player's ClubCorp ID (a unique per-person identifier from the tee sheet) has already been stored from a previous match. If found, match confirmed. |
| No stored ClubCorp ID yet | Fall back to name matching: filter by last name, then score by first name using exact match, a 100+ nickname map (Bob↔Robert, Tom↔Thomas, Mike↔Michael, etc.), and first-3-character comparison. Clear winner = matched. |
| After a successful match | The player's ClubCorp ID is saved to their roster record. Next time they play, the match is instant — no name matching required. |
Step 2 — Check Score Posting
Once the player is identified, the system uses their GHIN number from the roster to look up posted scores for the same date. Scores are matched by date_played (not posted date), so a score posted the day after still counts.
| Priority | Match Criteria |
|---|---|
| 1 | Same date + same course + same holes |
| 2 | Same date + same course (holes differ) |
| 3 | Same date + same holes (course differs) |
| 4 | Same date only (fallback) |
Each score can only be consumed once. If a member played 2 rounds but posted 1 score, the best-matching round shows Posted and the other shows Missing.
Step 3 — Audit Summary
The Audit Tool groups tee sheet data by member across a date range. It reads directly from the tee sheet matching results — no separate matching logic. Each member shows all their rounds and whether each was posted.
| Tee Sheet Color | Meaning |
|---|---|
| Green | Matched member — score posted for this date |
| Red | Matched member — score missing for this date |
| Grey | Not matched — guest, family member without GHIN, social member, or unresolved |
The tee sheet shows ALL players. Each gets a badge. Only entry_type=member + player_category=Golf are audited for compliance.
| Badge | Type | Audited? |
|---|---|---|
| M | Member (Golf) | Yes — tracked for compliance |
| G | Guest of Member | No |
| U | Unaccompanied Guest | No |
| A | Associate Member | No |
| AA | Access Advantage | No |
| P | Play Away Premier | No |
| E | Employee | No |
| Schedule | What | How |
|---|---|---|
| Daily 8am ET | Scores Posted Report | GHIN emails .xlsx → Gmail → Edge Function. Only inserts scores with posted_date = yesterday or day before. Quick edit check on last 7 days. |
| Monday 8am ET | GHIN Active Roster | GHIN emails .xlsx → Gmail → Edge Function. Full upsert by GHIN number — updates status, H.I., email. |
| After tee sheet upload | ClubCorp ID capture | captureClubcorpIds() links tee sheet ClubCorp IDs to Golf Genius members for Tier 1 matching. |
| After GG upload | Display name sync | Syncs display_name and display_email from Golf Genius to the GHIN roster for canonical name/email display. |
Select a date range (up to 1 month). The audit loads tee sheet entries, matches them via the 5-tier system, cross-references GHIN scores, and groups results by member.
| Member Status | Meaning |
|---|---|
| Compliant | All rounds posted |
| Emailed | All missing rounds have been emailed |
| Partial | Some missing rounds emailed, some not |
| Missing | Has unposted rounds, no emails sent |
Each round in the expand dropdown shows: Posted (with score details), Emailed (reminder sent for this date), or Missing (not posted, not emailed).
| Issue | How It's Handled |
|---|---|
| Apostrophes in names (O'Connor, L'Herbier) | nlk() strips apostrophes for all lookups |
| Titles (Dr., Mr., Mrs.) in GHIN names | nlk() strips all titles before matching |
| Suffixes (Jr., Sr., III, IV) in names | nlk() strips suffixes |
| Professional designations (CPA, MD, DA) | nlk() strips them |
| Family members sharing a member number | Tier 3 disambiguates by first name + 100+ nickname map |
| GG members with NULL member_number (156) | Tier 4 matches by name → GHIN roster as fallback |
| Multiple rounds on same date | Priority matching by course + holes. Each score consumed only once. |
| Score posted the day after playing | Matched by date_played not posted_date |
| CC ID ≠ Member# (membership transfers) | Flagged as "Needs Review" — excluded from compliance until manually confirmed |
| Guest placeholder ClubCorp IDs (1-4) | Skipped — never matched |
| Play-away codes (XXXXX-XXXXX) | Skipped — not Treesdale members |