Enhance schedule stop progress; add scheduled_passed_date column and update unique constraints
This commit is contained in:
@@ -11,6 +11,7 @@ ADMIN_DEPLOYMENT_SUMMARY.md
|
|||||||
CI_CD_PORTAINER_GUIDE.md
|
CI_CD_PORTAINER_GUIDE.md
|
||||||
DEPLOYMENT.md
|
DEPLOYMENT.md
|
||||||
GETTING_STARTED.md
|
GETTING_STARTED.md
|
||||||
|
handoff.md
|
||||||
INTERNAL_*.md
|
INTERNAL_*.md
|
||||||
SETUP_*.md
|
SETUP_*.md
|
||||||
DEPLOY_*.md
|
DEPLOY_*.md
|
||||||
|
|||||||
+24
-14
@@ -1,30 +1,40 @@
|
|||||||
# Session Handoff
|
# Session Handoff
|
||||||
|
|
||||||
**Goal:** [What I'm trying to achieve]
|
**Goal:** Make schedules work correctly across recurring and one-time events, with accurate per-day status/progress in the API and calendar views in the admin UI.
|
||||||
|
|
||||||
**Current Status:**
|
**Current Status:**
|
||||||
- [What is already done]
|
- `transit_api/index.js` now materializes recurring schedules into concrete occurrences for `/schedules/overview`.
|
||||||
- [What is in progress]
|
- `transit.schedule_stop_progress` is now occurrence-aware via `scheduled_passed_date`; the API backfills old rows and writes/reads stop progress per date.
|
||||||
- [What still needs to happen]
|
- The API check passed with `node --check transit_api/index.js`.
|
||||||
|
- The admin UI still needs to be wired to use the range-aware overview endpoint in its calendar data source.
|
||||||
|
|
||||||
**Important Context:**
|
**Important Context:**
|
||||||
- [Audience, tone, constraints, preferences]
|
- The schedule template lives in the database as a row with `weekdays`; recurring events are not stored as separate rows.
|
||||||
- [Key files, links, notes, or source material]
|
- The backend should be the source of truth for date-specific materialization and live progress/status.
|
||||||
- [Deadline or success criteria]
|
- Key files: `transit_api/index.js`, `admin_ui/src/components/ScheduleMaker.jsx`, `transit_api/README.md`.
|
||||||
|
- The admin UI build already succeeded earlier with `npm --prefix admin_ui run build`.
|
||||||
|
|
||||||
**Decisions Already Made:**
|
**Decisions Already Made:**
|
||||||
- [Decision + short reason]
|
- Recurring schedules are materialized on read instead of creating one DB row per occurrence. This keeps the DB simple and makes the calendar/date-range API deterministic.
|
||||||
|
- Progress must be keyed by occurrence date, not only by schedule id and stop order, otherwise a recurring schedule reuses yesterday’s stop state.
|
||||||
|
- `/schedules/overview` should support both single-date and date-range requests so month/week views can render all relevant occurrences with one call.
|
||||||
|
|
||||||
**What to Avoid:**
|
**What to Avoid:**
|
||||||
- [Failed attempts, wrong direction, out-of-scope items]
|
- Do not treat recurring schedules as a single mutable live schedule row for progress/status.
|
||||||
|
- Do not reuse the old `schedule_id + stop_order` uniqueness for stop progress.
|
||||||
|
- Avoid reworking unrelated API routes or admin screens unless they block the calendar flow.
|
||||||
|
|
||||||
**Open Questions or Blockers:**
|
**Open Questions or Blockers:**
|
||||||
- [What is unresolved]
|
- The admin UI calendar source still needs to be confirmed and wired to call `/schedules/overview?fromDate=...&toDate=...`.
|
||||||
|
- If the admin calendar view expects a different event shape, map the overview response there rather than changing the backend again.
|
||||||
|
|
||||||
**Next Best Step:**
|
**Next Best Step:**
|
||||||
- [What you should do first]
|
1. Inspect the calendar/timetable code path in `admin_ui/src/components/ScheduleMaker.jsx` and any adjacent component that renders the calendar range.
|
||||||
|
2. Wire that view to request `/schedules/overview` with `fromDate` and `toDate`.
|
||||||
|
3. Map returned schedules into calendar events and surface the current status/progress fields.
|
||||||
|
4. Run a focused admin UI build to confirm the change compiles.
|
||||||
|
|
||||||
**How to Respond:**
|
**How to Respond:**
|
||||||
- Start with a short summary of your understanding.
|
- Start by summarizing the current state in one short paragraph.
|
||||||
- Continue from here instead of restarting from scratch.
|
- Continue from the existing implementation instead of re-discovering the schedule model.
|
||||||
- If anything critical is missing, ask only the minimum questions needed.
|
- If anything critical is missing, ask only the minimum question needed to proceed.
|
||||||
@@ -582,6 +582,52 @@ async function ensureScheduleStopProgressTable() {
|
|||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await db.query(`
|
||||||
|
ALTER TABLE transit.schedule_stop_progress
|
||||||
|
ADD COLUMN IF NOT EXISTS scheduled_passed_date DATE
|
||||||
|
`);
|
||||||
|
|
||||||
|
await db.query(`
|
||||||
|
UPDATE transit.schedule_stop_progress
|
||||||
|
SET scheduled_passed_date = scheduled_passed_at::date
|
||||||
|
WHERE scheduled_passed_date IS NULL
|
||||||
|
`);
|
||||||
|
|
||||||
|
await db.query(`
|
||||||
|
ALTER TABLE transit.schedule_stop_progress
|
||||||
|
ALTER COLUMN scheduled_passed_date SET NOT NULL
|
||||||
|
`);
|
||||||
|
|
||||||
|
await db.query(`
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
constraint_name text;
|
||||||
|
BEGIN
|
||||||
|
SELECT tc.constraint_name
|
||||||
|
INTO constraint_name
|
||||||
|
FROM information_schema.table_constraints tc
|
||||||
|
JOIN information_schema.key_column_usage kcu
|
||||||
|
ON tc.constraint_name = kcu.constraint_name
|
||||||
|
AND tc.table_schema = kcu.table_schema
|
||||||
|
AND tc.table_name = kcu.table_name
|
||||||
|
WHERE tc.table_schema = 'transit'
|
||||||
|
AND tc.table_name = 'schedule_stop_progress'
|
||||||
|
AND tc.constraint_type = 'UNIQUE'
|
||||||
|
GROUP BY tc.constraint_name
|
||||||
|
HAVING array_agg(kcu.column_name ORDER BY kcu.ordinal_position) = ARRAY['schedule_id', 'stop_order']
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
IF constraint_name IS NOT NULL THEN
|
||||||
|
EXECUTE format('ALTER TABLE transit.schedule_stop_progress DROP CONSTRAINT %I', constraint_name);
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
`);
|
||||||
|
|
||||||
|
await db.query(`
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_schedule_stop_progress_schedule_order_date
|
||||||
|
ON transit.schedule_stop_progress (schedule_id, stop_order, scheduled_passed_date)
|
||||||
|
`);
|
||||||
|
|
||||||
await db.query(`
|
await db.query(`
|
||||||
CREATE INDEX IF NOT EXISTS idx_schedule_stop_progress_schedule_order
|
CREATE INDEX IF NOT EXISTS idx_schedule_stop_progress_schedule_order
|
||||||
ON transit.schedule_stop_progress (schedule_id, stop_order, scheduled_passed_date)
|
ON transit.schedule_stop_progress (schedule_id, stop_order, scheduled_passed_date)
|
||||||
|
|||||||
Reference in New Issue
Block a user