Skip to content

feat: add realistic interview data and scheduling logic to seed script#107

Merged
JoachimLK merged 1 commit intomainfrom
feat/v2-new-demo-data
Mar 15, 2026
Merged

feat: add realistic interview data and scheduling logic to seed script#107
JoachimLK merged 1 commit intomainfrom
feat/v2-new-demo-data

Conversation

@JoachimLK
Copy link
Copy Markdown
Contributor

@JoachimLK JoachimLK commented Mar 12, 2026

Summary

  • What does this PR change?
  • Why is this needed?

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Chore

Validation

  • I tested locally
  • I added/updated relevant documentation
  • I verified multi-tenant scoping and auth behavior for affected API paths

DCO

  • All commits in this PR are signed off (Signed-off-by) via git commit -s

Summary by CodeRabbit

  • New Features

    • Interview data seeding: The application now automatically creates sample interview records during initialization with full metadata including scheduling, status, location, and interviewer assignments.
  • Chores

    • Enhanced database initialization to populate interview datasets and improved logging for seeding pipeline progress.

@railway-app railway-app Bot temporarily deployed to applirank / reqcore-pr-107 March 12, 2026 19:58 Destroyed
@railway-app
Copy link
Copy Markdown

railway-app Bot commented Mar 12, 2026

🚅 Deployed to the reqcore-pr-107 environment in applirank

Service Status Web Updated (UTC)
applirank ✅ Success (View Logs) Mar 12, 2026 at 8:11 pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 12, 2026

📝 Walkthrough

Walkthrough

A seeding script enhancement that introduces comprehensive interview data generation. The update adds a date utility function, interview metadata type, and extensive interview dataset, then integrates a new interview creation phase into the existing seed pipeline that resolves applications and populates interview records with scheduling details.

Changes

Cohort / File(s) Summary
Interview Seeding Enhancement
server/scripts/seed.ts
Added dateWithOffset() utility for scheduling, InterviewSeed type definition, and comprehensive INTERVIEWS_DATA dataset. Implemented interview creation phase in seed flow with application mapping, date calculations, and full metadata (type, status, duration, location, notes, interviewers, timezone) insertion with audit field population and logging.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Hop, hop, the interviews now bloom,
Scheduled dates fill each room,
Candidates and roles align with care,
Seeded interviews everywhere!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description only contains the template with unchecked boxes and no actual content. The required 'Summary' section is completely empty, missing what the PR changes and why it's needed. Fill in the Summary section to explain what changes were made and why they are needed. Mark the appropriate 'Type of change' checkbox, confirm validation steps, and sign off commits with DCO.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding realistic interview data and scheduling logic to the seed script, which aligns with the primary modifications shown in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/v2-new-demo-data
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/scripts/seed.ts`:
- Around line 1132-1153: The interview fixtures use iv.daysOffset values (e.g.,
-16, -18, -20) that can make interviews older than their parent application or
even the candidate; fix by clamping parent createdAt timestamps against the
earliest interview per seed key: when building interviews (look at
iv.daysOffset, scheduledAt, candidateRespondedAt, invitationSentAt, createdAt,
updatedAt in the db.insert(schema.interview) block) compute the minimum
iv.daysOffset for that applicationId/seed group and ensure the application's
createdAt (and candidate/application history createdAt) equals at least
daysAgo(Math.abs(minOffset) + X) (X = safety gap like 1–4 days) or reduce the
negative iv.daysOffset values so interviews never precede their parent;
implement this clamp where the application is inserted (use applicationId and
its createdAt computation and the daysAgo helper) so the seeded timeline remains
monotonic.
- Around line 1126-1130: The missing applicationId indicates broken fixture
mapping; instead of warning and continuing, fail fast so the seed run stops and
the dataset issue is obvious: in the block using
applicationMap.get(`${iv.jobIndex}-${iv.candidateIndex}`) (where applicationId
and iv are defined) replace the console.warn + continue behavior with an
explicit failure (throw a descriptive Error or call process.exit(1) with an
error message) that includes the jobIndex and candidateIndex to make the bad
mapping easy to find.
- Around line 103-109: The current dateWithOffset function builds timestamps
using local system timezone (new Date() + setHours), causing inconsistent
scheduledAt values; update dateWithOffset to accept an IANA timezone string
(e.g., timezone param used by interviews) and construct the datetime in that
zone using a timezone-aware API (either Luxon: DateTime.fromObject({ year,
month, day, hour, minute }, { zone }) then toJSDate(), or Temporal: build a
Temporal.PlainDate from today in the target zone, combine with time into a
Temporal.PlainDateTime and convert to Temporal.ZonedDateTime and
toInstant().toString()/toDate()); replace the local setDate/setHours approach in
dateWithOffset to produce a timezone-correct Date for scheduledAt. Ensure
callers of dateWithOffset (where scheduledAt is set) provide the interview IANA
timezone.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f583ea21-2dfd-4b2f-a32f-472fd82728a4

📥 Commits

Reviewing files that changed from the base of the PR and between 5525cf6 and 467cc56.

📒 Files selected for processing (1)
  • server/scripts/seed.ts

Comment thread server/scripts/seed.ts
Comment on lines +103 to +109
/** Create a date offset from today with a specific time. Positive = future, negative = past. */
function dateWithOffset(daysOffset: number, hour: number, minute: number = 0): Date {
const d = new Date()
d.setDate(d.getDate() + daysOffset)
d.setHours(hour, minute, 0, 0)
return d
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In JavaScript/TypeScript, does Date#setHours use the host machine's local timezone, and what is the recommended way to construct a wall-clock time for a specific IANA timezone such as Europe/Berlin?

💡 Result:

Yes. Date#setHours is a local-time setter: it interprets/updates the hour using the host environment’s current local time zone (and DST rules), not an arbitrary IANA zone like Europe/Berlin. This is why it can yield different results on machines in different time zones. [1], [2]

Recommended: use Temporal for “wall-clock time in an IANA zone”

If you want “2026-03-12 09:00 in Europe/Berlin” as a real zoned date-time (handling DST gaps/ambiguity), construct a Temporal.PlainDateTime and convert it to a Temporal.ZonedDateTime:

const pdt = new Temporal.PlainDateTime(2026, 3, 12, 9, 0);
const zdt = pdt.toZonedDateTime({ timeZone: "Europe/Berlin", disambiguation: "compatible" });

Temporal.ZonedDateTime is designed for IANA time zones and provides explicit control for DST ambiguity/gaps via disambiguation. [3], [4]

If you must return a legacy Date

A JS Date can only represent an instant (UTC timestamp), not “9am Berlin time” by itself. If you need a Date that corresponds to that Berlin wall-clock time, use a time-zone-aware library (e.g., Luxon) to compute the correct instant:

import { DateTime } from "luxon";

const dt = DateTime.fromObject(
  { year: 2026, month: 3, day: 12, hour: 9, minute: 0 },
  { zone: "Europe/Berlin" }
);
const date: Date = dt.toJSDate();

(Luxon’s fromObject is the flexible “from components” constructor; the zone determines the correct offset/DST.) [5]

Sources: MDN Date/local vs UTC methods [1], ECMA-262 LocalTime usage in setHours algorithm [2], MDN Temporal toZonedDateTime and ZonedDateTime behavior/options [3], [4], Luxon API docs [5].


Make dateWithOffset timezone-aware.

new Date() + setHours() uses the host machine's local timezone, so this seed will produce different wall-clock scheduledAt values on a UTC box than on a developer laptop. Because each interview already carries an IANA timezone, build the timestamp in that zone instead of relying on local-time setters. For legacy Date objects, use a timezone-aware library like Luxon; for modern code, use Temporal.ZonedDateTime.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/scripts/seed.ts` around lines 103 - 109, The current dateWithOffset
function builds timestamps using local system timezone (new Date() + setHours),
causing inconsistent scheduledAt values; update dateWithOffset to accept an IANA
timezone string (e.g., timezone param used by interviews) and construct the
datetime in that zone using a timezone-aware API (either Luxon:
DateTime.fromObject({ year, month, day, hour, minute }, { zone }) then
toJSDate(), or Temporal: build a Temporal.PlainDate from today in the target
zone, combine with time into a Temporal.PlainDateTime and convert to
Temporal.ZonedDateTime and toInstant().toString()/toDate()); replace the local
setDate/setHours approach in dateWithOffset to produce a timezone-correct Date
for scheduledAt. Ensure callers of dateWithOffset (where scheduledAt is set)
provide the interview IANA timezone.

Comment thread server/scripts/seed.ts
Comment on lines +1126 to +1130
const applicationId = applicationMap.get(`${iv.jobIndex}-${iv.candidateIndex}`)
if (!applicationId) {
console.warn(`⚠️ Skipping interview "${iv.title}" — no application found for job ${iv.jobIndex}, candidate ${iv.candidateIndex}`)
continue
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fail fast on broken interview mappings.

A missing applicationId here means the fixture data is out of sync. Warning and continuing leaves the demo org partially populated, and rerunning will still skip the org later, so the broken dataset persists.

Suggested fix
     const applicationId = applicationMap.get(`${iv.jobIndex}-${iv.candidateIndex}`)
     if (!applicationId) {
-      console.warn(`⚠️  Skipping interview "${iv.title}" — no application found for job ${iv.jobIndex}, candidate ${iv.candidateIndex}`)
-      continue
+      throw new Error(`Missing application for interview "${iv.title}" (job ${iv.jobIndex}, candidate ${iv.candidateIndex})`)
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const applicationId = applicationMap.get(`${iv.jobIndex}-${iv.candidateIndex}`)
if (!applicationId) {
console.warn(`⚠️ Skipping interview "${iv.title}" — no application found for job ${iv.jobIndex}, candidate ${iv.candidateIndex}`)
continue
}
const applicationId = applicationMap.get(`${iv.jobIndex}-${iv.candidateIndex}`)
if (!applicationId) {
throw new Error(`Missing application for interview "${iv.title}" (job ${iv.jobIndex}, candidate ${iv.candidateIndex})`)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/scripts/seed.ts` around lines 1126 - 1130, The missing applicationId
indicates broken fixture mapping; instead of warning and continuing, fail fast
so the seed run stops and the dataset issue is obvious: in the block using
applicationMap.get(`${iv.jobIndex}-${iv.candidateIndex}`) (where applicationId
and iv are defined) replace the console.warn + continue behavior with an
explicit failure (throw a descriptive Error or call process.exit(1) with an
error message) that includes the jobIndex and candidateIndex to make the bad
mapping easy to find.

Comment thread server/scripts/seed.ts
Comment on lines +1132 to +1153
const scheduledAt = dateWithOffset(iv.daysOffset, iv.hour, iv.minute ?? 0)
const responded = iv.candidateResponse !== 'pending'

await db.insert(schema.interview).values({
id: id(),
organizationId: orgId,
applicationId,
title: iv.title,
type: iv.type,
status: iv.status,
scheduledAt,
duration: iv.duration,
location: iv.location,
notes: iv.notes,
interviewers: iv.interviewers,
createdById: userId,
candidateResponse: iv.candidateResponse,
candidateRespondedAt: responded ? daysAgo(Math.abs(iv.daysOffset) + 2) : null,
invitationSentAt: responded ? daysAgo(Math.abs(iv.daysOffset) + 3) : null,
timezone: iv.timezone,
createdAt: daysAgo(Math.abs(iv.daysOffset) + 4),
updatedAt: daysAgo(Math.abs(iv.daysOffset) + 1),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

These backdated interviews can precede their application history.

The application phase above only backdates rows 1-15 days, but this fixture includes interviews at -16, -18, and -20 days. Those records will always sort earlier than their owning application, and some can even predate candidate creation, which makes the seeded timeline impossible. Please clamp parent createdAt values against the earliest interview for each seed key, or reduce the interview backdating so the timeline stays monotonic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/scripts/seed.ts` around lines 1132 - 1153, The interview fixtures use
iv.daysOffset values (e.g., -16, -18, -20) that can make interviews older than
their parent application or even the candidate; fix by clamping parent createdAt
timestamps against the earliest interview per seed key: when building interviews
(look at iv.daysOffset, scheduledAt, candidateRespondedAt, invitationSentAt,
createdAt, updatedAt in the db.insert(schema.interview) block) compute the
minimum iv.daysOffset for that applicationId/seed group and ensure the
application's createdAt (and candidate/application history createdAt) equals at
least daysAgo(Math.abs(minOffset) + X) (X = safety gap like 1–4 days) or reduce
the negative iv.daysOffset values so interviews never precede their parent;
implement this clamp where the application is inserted (use applicationId and
its createdAt computation and the daysAgo helper) so the seeded timeline remains
monotonic.

@JoachimLK JoachimLK merged commit e3b1881 into main Mar 15, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant