Skip to main content

Complex Areas

A short, honest list of areas where the code is genuinely complex and worth reading carefully before changing. Not a list of bugs or warnings — these are load-bearing, well-functioning systems whose shape matters.


PayrollContext.tsx

File: ../../src/routes/PayrollNew/PayrollContext.tsx (3,037 lines)

The aggregator for the PayrollNew feature. Subscribes to multiple RTDB trees, exposes hours / tips / cuts calculations, and feeds the eight export-format generators in ../../src/routes/PayrollNew/export-formats/.

It is heavily memoized (~37 useMemo/useCallback sites), so the risk isn't render perf — the risk is just size. A lot of consumers depend on the values it exposes, so changes ripple. When extending, prefer adding a focused hook in ../../src/routes/PayrollNew/ and plugging it into the context, rather than growing the context body.


requests module — multi-type state machine

Folder: ../../functions/modules/requests/

Handles several request types (availability changes, time-off, shift swaps, exchange offers, emergency coverage) on a shared state machine. Transitions are interlinked — for example, an exchange offer creates an inverse request on the counterparty; expirations cascade.

Before changing transitions or permission checks on one request type, read the state-transition logic under ../../functions/modules/requests/logic/ and check the other types don't depend on the path you're modifying.


integration-engine/ provider abstraction

Folder: ../../functions/integration-engine/ (100+ files)

The standard way to add a POS or reservation provider. Deep inheritance: BaseProvider → domain (sales, reservation) → concrete provider (opentable, lightspeed, …). A sync-job planner orchestrates pipeline runs; an observability layer reports health and writes state to Firestore (see decisions.md → data-stores).

Plan a few hours to read core/, domains/<your-domain>/, and one existing provider end-to-end before adding a new one. The older per-provider folders under ../../functions/integrations/ are legacy and predate this engine — new providers go through the engine.


Schedule → Postgres replication is asynchronous

Listener: ../../functions/db/pg-sync/on-schedule-write.listener.ts (and siblings for company / employee / user / schedule-settings)

A schedule edit is committed to RTDB first (the source of truth that web + mobile observe). A separate RTDB → Postgres listener then mirrors that change into Cloud SQL for analytics/reporting use.

If the Postgres write fails, the two stores can diverge silently — reports run against Postgres lag or contradict the live UI. When investigating "the dashboard doesn't match what I see in the app," check Rollbar for pg-sync errors. Keep the dataflow one-way: don't add ad-hoc Postgres writes outside of pg-sync.