StormWater.INSPECTION INTELLIGENCE
Knowledge workspace / Technical reference
FEB 2026 EDITION
THE STORMWATER KNOWLEDGE BASE

Clarity in every inspection.

Your guide to the rules, workflows, and logic behind the StormWater module.

Updated February 2026
BUILT FOR THE BIG PICTURE. AND THE DETAILS.

Complex workflows.
Clear answers.

From the first rainfall to the final report, understand how every inspection moves through the system.

Explore the reference See real-world scenarios ↗
14Reference chapters
7Inspection frequencies
6Scenario walkthroughs
One connected system.
Every rule, explained.

Find your starting point

Explore the system, one topic at a time.

THE COMPLETE REFERENCE
Prefer a visual walkthrough?Follow the decisions, branches, and outcomes.Workflow diagrams
The rules make more sense in context.

Follow six real-world scenarios, from routine schedules to consecutive rainfall events.

Explore scenarios

StormWater Inspection Module — Complete Business Logic Reference

Overview: Comprehensive guide to StormWater inspection scheduling, workflows, status management, and dashboard functionality. This reference explains how inspections are triggered, tracked, and managed throughout their lifecycle.
Last Updated: February 2026

Table of Contents

  1. Key Terms & Definitions
  2. Inspection Types
  3. Project Types: Fluid vs Non-Fluid
  4. Inspection Frequencies
  5. Routine Inspection Scheduling — Non-Fluid Projects
  6. Routine Inspection Scheduling — Fluid Projects (Twice-a-Week)
  7. Post-Rainfall Inspection — Precipitation-Based (Non-Event)
  8. Rainfall Event Inspection — ENVR Event-Based
  9. Dashboard Card Logic: Inspections Due, Past Due, Missed, Draft
  10. Inspection Submission & Rescheduling Logic
  11. Deferral Logic
  12. Timezone-Based Scheduling
  13. Comparative Summary Tables
  14. Scenario Walkthroughs

1. Key Terms & Definitions

1.1 Inspection Item Statuses

StatusIDDescription
Draft1Inspector has saved but not submitted
Open2Has open corrective action items
Closed3All actions resolved
Submit5Successfully submitted/completed
NA6Not applicable
SubmitForReview7Submitted, awaiting review
ActionPending8Inspection is due and awaiting completion by inspector
Scheduled9Future-dated inspection, not yet actionable
Missed10Inspection was not completed within the allowed window
SubmittedByOther11Submitted by another inspector
NotScheduled12Placeholder for fluid twice-a-week 2nd term (not yet active)

1.2 Inspection Types

TypeIDDescription
Routine1Scheduled routine inspection (calendar-based)
PostRainfall2Triggered by rainfall exceeding threshold
Routine_PostRainfall3Combined — can satisfy both routine and post-rainfall requirements

1.3 Inspection Frequencies

FrequencyIDScheduling Rule
Daily1Every calendar day
Weekly2Once per week on a fixed InspectionDay (0=Sun … 6=Sat)
Monthly3Once per month on a fixed day of the month
Quarterly4Once every 3 months on a fixed day
TwiceAWeek5Two inspections per week — behavior differs for Fluid vs Non-Fluid
BiWeekly6Once every 14 days on a fixed day of the week
Custom7Every N days (FrequencyInDays) from the start date

1.4 Dashboard Cards

Card NameID
InspectionsDue1
PastDueInspections2
Draft3
OpenItems4

1.5 Rainfall Event Statuses

StatusIDDescription
Active0Rainfall event is ongoing
InActive1Rainfall event has ended (4 consecutive zero-precipitation hours)

1.6 Setup Statuses

StatusIDDescription
defaultSetup0Normal active setup created by admin
setupCreatedByInspection1Setup auto-created during ad-hoc "Add Report" submission

2. Inspection Types

2.1 Routine Inspections (Type = 1)

  • Calendar-driven inspections generated by the scheduler.
  • The scheduler (GetTodayRoutineInspection) runs once per timezone window (EST → CST → MST → PST) daily.
  • Only projects with InsTypeId = Routine (1) or Routine_PostRainfall (3) are included.
  • Scheduling is purely based on frequency and the configured inspection day(s).

2.2 Post-Rainfall Inspections (Type = 2)

  • Triggered when precipitation data from the previous day exceeds the project's RainfallThreshold.
  • Generated by the scheduler (GetTodayInspection) using daily precipitation records from SwProjectPrecip.
  • Only projects with InsTypeId = PostRainfall (2) or Routine_PostRainfall (3) are included.
  • Non-event states only — states where IsEventSwIns is NOT true use this path.

2.3 Routine + Post-Rainfall Combined (Type = 3)

  • Projects configured as Routine_PostRainfall participate in both the routine scheduler and the post-rainfall/event scheduler.
  • For Fluid projects, when a rainfall event triggers an inspection, the InsTypeId is forced to Routine_PostRainfall (3) regardless of the setup's original type. This satisfies both the routine and rainfall inspection requirement in a single report.

3. Project Types: Fluid vs Non-Fluid

The IsFluid flag on the SwProject entity fundamentally changes how twice-a-week inspections are scheduled and how submission/rescheduling behaves.

FeatureNon-FluidFluid
Twice-a-Week DaysFixed to InspectionDay and InspectionDay2 from setupDynamic — 1st always on Monday, 2nd flexible
InsTerm FieldEmpty string ("")"1" for first, "2" for second inspection of the week
Future SchedulingPre-scheduled on both configured days for 3 monthsOnly Monday inspections pre-scheduled for next 3 weeks
Submission BehaviorAll ActionPending inspections for same config are deletedOnly the first ActionPending inspection is deleted
Inspection Day Changes on SubmitYes — setup's InspectionDay updates to the day of submissionNo — for TwiceAWeek; Yes — for other frequencies
Sunday VisibilityVisibleHidden from dashboard on Sundays
PostRainfall Type OverrideNo — keeps original InsTypeIdYes — forced to Routine_PostRainfall (3)

4. Inspection Frequencies

4.1 Daily (FrequencyId = 1)

Scheduling: An inspection is generated every calendar day.

Special "Daily Report" Mode: If the setup has no Question Set selected (QuestionSetId == null || 0) and is not external, it operates as a "Daily Report" with different handling:

  • One inspection per month (not per day) is created in the SwIns table.
  • Individual daily data points are tracked via SwInsDailyReport entries.
  • The single monthly inspection's ScheduleDate is updated to today each day.
  • Prior month inspections are marked Missed if still ActionPending.

Standard Daily: If a Question Set is selected, a new SwIn record is created each day with Status = ActionPending.

4.2 Weekly (FrequencyId = 2)

Scheduling: Fires on the configured InspectionDay (day of week: 0=Sunday … 6=Saturday).

Trigger condition: currentDayOfWeek == setup.InspectionDay

Future scheduling: 3 future inspections are pre-scheduled with Status = Scheduled.

Missed logic: Previous ActionPending inspections with ScheduleDate < today are marked Missed when the next inspection is generated.

4.3 Twice-a-Week (FrequencyId = 5)

This frequency has two completely different behaviors depending on whether the project is Fluid or Non-Fluid. See Sections 5 and 6 for detailed breakdowns.

4.4 Bi-Weekly (FrequencyId = 6)

Scheduling: Fires on the configured InspectionDay (day of week), but only if at least 14 days have passed since the last inspection.

Trigger condition: currentDayOfWeek == setup.InspectionDay AND the most recent previous inspection's ScheduleDate + 14 days > today check fails (i.e., 14+ days have elapsed).

Future scheduling: 3 future inspections are pre-scheduled with Status = Scheduled.

4.5 Monthly (FrequencyId = 3)

Scheduling: Fires when currentDay == setup.InspectionDay (day of month, e.g., the 15th).

Future scheduling: 3 future inspections are pre-scheduled.

4.6 Quarterly (FrequencyId = 4)

Scheduling: Fires when currentDay == setup.InspectionDay AND the current month aligns with the quarterly cycle based on InspectionMonth.

Quarter calculation: Starting from InspectionMonth, the system checks if the current month is InspectionMonth, InspectionMonth + 3, InspectionMonth + 6, or InspectionMonth + 9 (wrapping around at 12).

Future scheduling: 3 future inspections are pre-scheduled.

4.7 Custom (FrequencyId = 7)

Scheduling: Fires every N days (FrequencyInDays) calculated from the InspectionStartDate.

Trigger condition: (today - InspectionStartDate).TotalDays % FrequencyInDays == 0

Future scheduling: 3 future inspections are pre-scheduled.


5. Routine Inspection Scheduling — Non-Fluid Projects

5.1 Entry Point

The scheduler calls GetTodayRoutineInspection() which:

1. Queries all active setups with InsTypeId = Routine (1) or Routine_PostRainfall (3).

2. Filters setups whose frequency matches today (see frequency rules above).

3. For each matching setup, processes the inspection.

5.2 Processing Flow for Each Setup (Non-Fluid, Non-TwiceAWeek)


1. Update today's existing Scheduled inspection → ActionPending
2. Update rainfall amount from yesterday's precipitation data
3. Mark old ActionPending inspections (ScheduleDate < today) → Missed
4. If no inspection exists for today → Create new SwIn with Status = ActionPending
5. Pre-schedule next 3 future inspections with Status = Scheduled

5.3 Processing Flow for Non-Fluid Twice-a-Week

Since isFluid == false, the standard processing path is followed:

  • Both InspectionDay and InspectionDay2 are used to determine if today is an inspection day.
  • Inspections are created/scheduled on both fixed days.
  • The GetNextInspectionDate recursive method generates future dates for both days each week.
  • InsTerm is set to empty string.
  • Old ActionPending inspections are marked Missed.
  • 3 future inspections (covering both days) are pre-scheduled.

5.4 Missed Marking (Non-Fluid Routine)

When: Every time the scheduler runs for a setup.

Condition: ScheduleDate &lt; today AND Status == ActionPending AND same SetupId

Action: Status is changed to Missed (10).

This means: If an inspector does not complete a weekly inspection by the day the next one generates, it automatically becomes Missed.


6. Routine Inspection Scheduling — Fluid Projects (Twice-a-Week)

Fluid twice-a-week inspections have a completely unique scheduling model.

6.1 Key Concepts

  • Weekly cycle: Sunday through Saturday.
  • Two terms per week: Term 1 and Term 2, tracked via the InsTerm field.
  • Dynamic scheduling: The second inspection's activation day depends on when conditions are met.
  • Scheduler runs daily for fluid TwiceAWeek setups (the filter m.isFluid == true bypasses the day-of-week check).

6.2 Monday or First Run of the Week

When DayOfWeek == Monday OR no inspections exist for the current week:


1. Mark all ActionPending inspections from PRIOR weeks → Missed
2. If an existing Scheduled inspection for this week exists:
     → Update its Status from Scheduled → ActionPending (Term 1)
   Else:
     → Create new inspection: InsTerm = "1", Status = ActionPending
3. If today is NOT Friday AND no Term 2 exists for this week:
     → Create new inspection: InsTerm = "2", Status = NotScheduled
4. Pre-schedule next 3 weeks (Monday dates) with Status = Scheduled

Term 1: Created as ActionPending — immediately visible on dashboard.

Term 2: Created as NotScheduled (12) — NOT visible on dashboard yet.

6.3 Term 2 Activation (Tuesday through Friday)

The second inspection becomes ActionPending (visible) when specific conditions are met:

On Tuesday, Wednesday, or Friday:

  • Condition: The week has exactly 2 inspections where both are either Submit or NotScheduled.
  • This means: Term 1 was submitted, and Term 2 is still NotScheduled → activate Term 2.

On Thursday:

  • Condition: The week has exactly 1 inspection that is either ActionPending or Submit.
  • This means: If only one inspection exists or Term 1 is still pending, activate Term 2 on Thursday regardless.

Activation action: The NotScheduled Term 2 inspection is updated to ActionPending.

6.4 Missed Marking (Fluid Twice-a-Week)

When: At the start of each new week (Monday processing).

Condition: ScheduleDate &lt; thisWeekStart AND Status == ActionPending AND same SetupId

Action: Status changed to Missed (10).

Key difference from Non-Fluid: Missed marking only happens for inspections from prior weeks, not just prior days. This gives the inspector the entire week to complete both terms.

6.5 Sunday Handling

Fluid TwiceAWeek inspections are completely hidden from the dashboard on Sundays:


!(currentDate.DayOfWeek == DayOfWeek.Sunday 
  && frequency.InsFrequencyId == InspectionFrequencyId.TwiceAWeek 
  && project.IsFluid == true)

6.6 Friday Handling

On Fridays, Term 1 inspections that are still ActionPending are included in the Past Due count. This creates urgency to complete them before the weekend.


7. Post-Rainfall Inspection — Precipitation-Based (Non-Event)

This applies to states where IsEventSwIns is NOT true (i.e., rainfall inspections are based on daily precipitation data, not real-time ENVR events).

7.1 Trigger Mechanism

The scheduler (GetTodayInspection with IsEventSwIns = null/false) runs daily and:

1. Queries all active setups with InsTypeId = PostRainfall (2) or Routine_PostRainfall (3).

2. Retrieves precipitation data from SwProjectPrecip for the period from Friday (if Monday) or yesterday to today.

3. For each setup: if any precipitation record exceeds the project's RainfallThreshold → generate inspection.

7.2 Deduplication

Before generating, the system checks:

  • If an ActionPending inspection already exists for today with the same SetupId → skip (no duplicate).

7.3 Missed Marking

Previous ActionPending inspections with ScheduleDate &lt; today for the same setup are marked Missed.

This is a key difference from event-based inspections — non-event rainfall inspections DO get marked as Missed automatically.

7.4 Inspection Creation


Status = ActionPending
ScheduleDate = today
InsTypeId = setup's original InsTypeId (no override)
RainEventId = 0 (no event association)
Rainfall = the actual precipitation amount that exceeded threshold

7.5 After Post-Rainfall Processing

The system then calls GetTodayRoutineInspection() to also process routine inspections for the same timezone. This ensures both rainfall-triggered and routine inspections are handled in a single scheduler run.


8. Rainfall Event Inspection — ENVR Event-Based

This applies to states where IsEventSwIns = true. These inspections are driven by real-time rainfall data from the ENVR/EvenTrack weather API.

8.1 Trigger Mechanism

A separate Lambda function (GenerateRainafallSwInspection in RainfallBusinessLogic) runs on a scheduled basis (typically hourly) and:

1. Queries all active setups with InsTypeId = PostRainfall (2) or Routine_PostRainfall (3) in states where IsEventSwIns = true.

2. Calls the ENVR API (GetPrecipLastHourData) to get the last hour's precipitation for each project's weather account.

3. Manages rainfall events and potentially generates inspections.

8.2 Rainfall Event Lifecycle


┌─────────────────────────────────────────────────────────────┐
│                    RAINFALL EVENT LIFECYCLE                   │
├─────────────────────────────────────────────────────────────┤
│                                                               │
│  [API returns Precip > 0, No active event]                   │
│      ↓                                                        │
│  CREATE new SwInsRainEvent (Status = Active)                 │
│  CREATE SwInsRainEventDatum (hourly data point)              │
│      ↓                                                        │
│  [Cumulative precip >= RainfallThreshold?]                   │
│      YES → GENERATE INSPECTION                               │
│      NO  → Continue monitoring                               │
│                                                               │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─                   │
│                                                               │
│  [API returns Precip > 0, Active event exists]               │
│      ↓                                                        │
│  ADD SwInsRainEventDatum (new hourly data point)             │
│  UPDATE event EndDateTime                                     │
│      ↓                                                        │
│  [Cumulative precip just crossed RainfallThreshold?]         │
│      YES → GENERATE INSPECTION (first time crossing only)    │
│      NO  → Continue monitoring                               │
│                                                               │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─                   │
│                                                               │
│  [API returns Precip = 0, Active event exists]               │
│      ↓                                                        │
│  ADD SwInsRainEventDatum (zero reading)                      │
│  INCREMENT consecutive zero count                            │
│      ↓                                                        │
│  [4 consecutive zero readings?]                              │
│      YES → DEACTIVATE event (Status = InActive)              │
│      NO  → Continue monitoring                               │
│                                                               │
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─                   │
│                                                               │
│  [API returns Precip = 0, No active event]                   │
│      → IGNORED (no action taken)                             │
│                                                               │
└─────────────────────────────────────────────────────────────┘

8.3 Inspection Generation from Events

When GenerateInspection is triggered:

1. It calls SwAdminInspection.GetTodayInspection(timeZone: null, IsEventSwIns: true, projectList).

2. Inside GetTodayInspection, for event-based inspections:

  • No deduplication check — a new inspection is created every time the threshold is crossed, even if one already exists for today.
  • No missed marking — the if (IsEventSwIns != true) block skips both deduplication and missed-marking logic.
  • No routine inspection generation — the GetTodayRoutineInspection() call is also skipped when IsEventSwIns == true.

8.4 Event-Based Inspection Details


Status = ActionPending
ScheduleDate = today (weekday) OR next Monday (if Saturday/Sunday)
InsTypeId = Routine_PostRainfall (3) for Fluid projects, original type for Non-Fluid
RainEventId = the associated SwInsRainEvent.RainEventId
Rainfall = cumulative precipitation from the event

8.5 Weekend Handling

If a rainfall event triggers an inspection on Saturday or Sunday, the ScheduleDate is set to the next Monday:


if (IsEventSwIns == true && ((int)currentDate.DayOfWeek == 6 || (int)currentDate.DayOfWeek == 0))
{
    inspection.ScheduleDate = nextMonday;
}

8.6 Event Capture (Updating Existing Inspections)

After generating new inspections, CaptureRainfallEvent updates all existing ActionPending and Draft inspections for the same project with the latest rainfall data:

  • RfEventAmt → current cumulative precipitation
  • RfEventDate → current timestamp
  • RfEventAmtPrv → previous precipitation value (shifted)
  • RfEventDatePrv → previous date (shifted)
  • RfEventDuration → hours since event start
  • Rainfall → updated to latest cumulative value

This means inspections that were already on the dashboard get their rainfall data continuously updated as the event progresses.

8.7 Two Events on the Same Day

If two separate rainfall events occur on the same day (Event 1 ends, Event 2 starts):

StepEvent 1 InspectionEvent 2 Inspection
Event 1 threshold crossedCreated: ActionPending, RainEventId = Event1—
Event 1 ends (4 zero hours)Still ActionPending, no status change—
Event 2 threshold crossedNo status change — still ActionPendingCreated: ActionPending, RainEventId = Event2
ResultBoth appear on dashboard as "Inspections Due"

The first inspection is NOT moved to Missed or Past Due when the second event fires. There is no code path that changes the status of existing event-based inspections when new events occur.


9. Dashboard Card Logic: Inspections Due, Past Due, Missed, Draft

9.1 Base Query (Common to All Cards)

All dashboard cards share the same base query that filters:


SwInsSetup.IsActive = true AND IsDeleted = false
SwIn.IsDeleted = false
SwIn.ScheduleDate <= today
SwIn.Status IN (ActionPending, Draft)

Additional filters:

  • User/team assignment matching
  • Organization matching
  • Fluid TwiceAWeek inspections are hidden on Sundays

9.2 Inspections Due (Card 1)

Definition: Total count of all inspections matching the base query.

Formula: COUNT(all records from base query)

This includes ALL ActionPending and Draft inspections with ScheduleDate &lt;= today, regardless of how overdue they are. Past Due and Draft inspections are subsets of this total.

9.3 Past Due (Card 2)

Definition: Inspections that have exceeded their expected completion window.

Formula (broken down by type):

Inspection TypePast Due Condition
Non-event, any frequency (RainEventId = null or 0)ScheduleDate < today
Event-based (RainEventId > 0)today >= ScheduleDate + 2 days
Fluid TwiceAWeek, Term 1Only on Fridays: DayOfWeek == Friday AND InsTerm == "1"
Fluid TwiceAWeek, any termScheduleDate.DayOfWeek == Saturday (i.e., carried over from prior week)
Non-Fluid, non-TwiceAWeekStandard ScheduleDate < today rule applies

Key insight: Event-based inspections get a 2-day grace period before appearing as Past Due. Non-event inspections become Past Due the very next day.

9.4 Draft (Card 3)

Definition: Inspections saved but not yet submitted.

Formula: Status == Draft (1)

9.5 Missed (Not a Dashboard Card — Background Status)

Important: "Missed" is NOT a visible dashboard card. It is a status (10) that inspections are moved to by the scheduler, effectively removing them from the dashboard entirely.

Once an inspection is marked Missed, it no longer appears in any dashboard card because the base query only includes ActionPending (8) and Draft (1).

9.6 Complete Dashboard Card Comparison

CardNon-Event RoutineEvent-Based (Rainfall)Fluid TwiceAWeek
Inspections DueScheduleDate <= today AND (ActionPending OR Draft)SameSame, except hidden on Sunday
Past DueScheduleDate < todayScheduleDate + 2 days <= todayFriday: Term 1 is Past Due; Saturday-dated: always Past Due
DraftStatus == DraftSameSame
MissedAuto-marked by scheduler when next inspection generatesNever auto-marked (code commented out)Auto-marked at start of new week for prior week's inspections

10. Inspection Submission & Rescheduling Logic

10.1 Non-Fluid Project Submission

When an inspection is submitted (Status → Submit):

If submitted on the scheduled day (InspectionDay matches current day):

  • All other ActionPending inspections with the same configuration are soft-deleted.
  • No rescheduling needed — future inspections are already on correct days.

If submitted on a different day than scheduled (early submission of a Scheduled inspection):

1. The inspection's ScheduleDate is updated to today.

2. The setup's InspectionDay is updated to the current day of the week.

3. All existing Scheduled future inspections for this setup are deleted.

4. New future inspections are generated based on the new inspection day.

This means: For Weekly, BiWeekly, Monthly, and Quarterly non-fluid inspections, submitting early permanently changes the inspection schedule to the new day.

10.2 Fluid Project Submission (Twice-a-Week)

Same-day duplicate prevention: If an inspection has already been submitted or saved as draft for the current date in this week, a validation error is returned: &quot;Inspection has already been completed for this date&quot;.

When submitting via "Add Report" (direct inspection):

  • The first ActionPending or Scheduled inspection in the current week is soft-deleted.
  • The submitted inspection takes the deleted inspection's InsTerm.

No day rescheduling occurs for TwiceAWeek fluid inspections — the system deliberately skips rescheduling for this frequency.

10.3 Fluid Project Submission (Non-TwiceAWeek Frequencies)

For fluid projects with Weekly, Monthly, etc.:

  • All ActionPending inspections for matching setups (excluding PostRainfall and TwiceAWeek) are deleted.
  • If the submission day differs from the setup's InspectionDay:
  • All Scheduled future inspections are deleted.
  • Setup's InspectionDay and InspectionMonth are updated.
  • New future inspections are rescheduled from the new day.

10.4 Non-Fluid Project Submission (Add Report / Direct Inspection)

When submitted via "Add Report" (IsDirectIns = true):

  • All ActionPending inspections for matching setups (same project, question set, frequency, type) are soft-deleted.

10.5 Submission Impact on Inspection Day — Summary Table

Project TypeFrequencySubmitted on Scheduled DaySubmitted on Different Day
Non-FluidWeeklyNo changeInspectionDay → current DayOfWeek; reschedule future
Non-FluidBiWeeklyNo changeInspectionDay → current DayOfWeek; reschedule future
Non-FluidMonthlyNo changeInspectionDay → current Day; reschedule future
Non-FluidQuarterlyNo changeInspectionDay → current Day; InspectionMonth → current Month; reschedule future
Non-FluidTwiceAWeekNo changeInspectionDay → current DayOfWeek; reschedule future (both days)
Non-FluidCustomNo changeReschedule from current day
FluidTwiceAWeekNo changeNo change — TwiceAWeek is explicitly skipped
FluidWeeklyNo changeInspectionDay → current DayOfWeek; reschedule future
FluidOtherNo changeInspectionDay updated; reschedule future
AnyPostRainfallNever rescheduledNever rescheduled — PostRainfall is explicitly skipped

11. Deferral Logic

Inspections can be deferred by the inspector instead of being completed.

11.1 Deferral Types

Type`IsMissedDeferral`New ScheduleDateUse Case
Standard Deferralfalsetoday + 1 dayInspector cannot complete today, defers to tomorrow
Missed DeferraltruetodayMissed inspection is being rescheduled to today

11.2 Deferral Processing

1. ScheduleDate is updated based on deferral type.

2. DeferredCount is incremented by 1.

3. A SwInsDeferral record is created with the reason and comment.

4. The inspection remains ActionPending — it does not change status.

11.3 Deferral Impact on Dashboard

  • A deferred inspection stays in "Inspections Due" with its new ScheduleDate.
  • If the new ScheduleDate is tomorrow (standard deferral), it temporarily disappears from the dashboard (since the base query filters ScheduleDate <= today) but reappears the next day.
  • If it's a missed deferral (ScheduleDate = today), it remains visible immediately.

12. Timezone-Based Scheduling

12.1 Scheduler Execution Windows

The routine scheduler (GetTodayRoutineInspection) is timezone-aware. It determines the timezone based on the current UTC hour:

UTC HourTimezone Processed
6–7Eastern (EST)
7–8Central (CST)
8–9Mountain (MST)
9–10Pacific (PST)
After 10null (all timezones processed)

Each site is assigned a timezone, and only sites matching the current processing window are included.

12.2 Rainfall Event Scheduler

The rainfall event scheduler (GenerateRainafallSwInspection) is not timezone-filtered — it processes all projects across all timezones in every run, since rainfall events are real-time and not calendar-bound.


13. Comparative Summary Tables

13.1 Inspection Generation — When & How

FrequencyNon-FluidFluid
DailyEvery day, 1 inspectionEvery day, 1 inspection
Daily (No QS)1 inspection/month, daily reports tracked separatelySame
WeeklyOn InspectionDay each weekOn InspectionDay each week
TwiceAWeekOn InspectionDay and InspectionDay2 each weekEvery day (scheduler decides whether to create/activate)
BiWeeklyOn InspectionDay every 14 daysOn InspectionDay every 14 days
MonthlyOn day InspectionDay of each monthSame
QuarterlyOn day InspectionDay of the configured quarterly monthsSame
CustomEvery N days from start dateSame
PostRainfall (Non-Event)When daily precip > thresholdSame
PostRainfall (Event)When ENVR cumulative precip crosses thresholdSame, but InsTypeId forced to Routine_PostRainfall

13.2 Missed Marking — When Inspections Become Missed

ScenarioNon-FluidFluid
Routine (non-TwiceAWeek)Next day when scheduler runs and generates the next inspectionSame
TwiceAWeek RoutineWhen next scheduled day arrives and old inspection is still ActionPendingOnly at start of new week (Monday) for prior week's inspections
PostRainfall (Non-Event)Next day when scheduler runs and a new rainfall inspection triggersSame
PostRainfall (Event-Based)Never (code commented out as of Oct 2025)Never
Daily ReportPrior month's inspection marked Missed when new month startsSame

13.3 Past Due — When Inspections Show as Past Due on Dashboard

ScenarioCondition
Non-event, all frequenciesScheduleDate < today (next day)
Event-based (has RainEventId)today >= ScheduleDate + 2 days (2-day grace)
Fluid TwiceAWeek, Term 1Only on Fridays
Fluid TwiceAWeek, carried from prior weekScheduleDate.DayOfWeek == Saturday

13.4 Inspection Day Change — Complete Matrix

TriggerWeeklyBiWeeklyTwiceAWeek (Non-Fluid)TwiceAWeek (Fluid)MonthlyQuarterlyCustomPostRainfall
Scheduled submissionNo changeNo changeNo changeNo changeNo changeNo changeNo changeN/A
Early submission (different day)Day changesDay changesDay changesNo changeDay changesDay+Month changesRescheduleNever
Scheduler generates nextFixed dayFixed dayFixed daysMonday + dynamicFixed dayFixed day+monthFixed intervalOn threshold breach

14. Scenario Walkthroughs

Scenario 1: Weekly Non-Fluid, Inspector Misses Scheduled Day

  • Setup: Weekly, InspectionDay = Wednesday (3)
  • Wednesday: Scheduler creates inspection, Status = ActionPending, ScheduleDate = Wed
  • Inspector does nothing all week
  • Next Wednesday: Scheduler runs again:

1. Previous Wed inspection (ActionPending, ScheduleDate &lt; today) → Marked Missed

2. New inspection created for today: ActionPending, ScheduleDate = this Wed

  • Dashboard impact: Old inspection disappears (Missed ≠ ActionPending), new one appears as "Inspections Due"

Scenario 2: Fluid Twice-a-Week, Normal Week

  • Monday: Scheduler creates:
  • Term 1: InsTerm = "1", Status = ActionPending (visible)
  • Term 2: InsTerm = "2", Status = NotScheduled (not visible)
  • Tuesday: Inspector submits Term 1. Dashboard shows 1 inspection submitted.
  • Wednesday: Scheduler sees Term 1 is Submit and Term 2 is NotScheduled (count = 2) → Activates Term 2: Status → ActionPending (now visible)
  • Thursday: Inspector submits Term 2. Both inspections completed for the week.

Scenario 3: Fluid Twice-a-Week, Inspector Doesn't Submit Term 1 Until Thursday

  • Monday: Term 1 created (ActionPending), Term 2 created (NotScheduled)
  • Tuesday–Wednesday: Term 2 activation conditions not met (Term 1 still ActionPending, not Submit)
  • Thursday: Scheduler activates Term 2 anyway (Thursday special rule: only 1 ActionPending/Submit exists)
  • Now both Term 1 and Term 2 are ActionPending
  • Friday: If Term 1 still ActionPending → shows as Past Due on dashboard
  • Next Monday: Any still-ActionPending inspections from prior week → Marked Missed

Scenario 4: Rainfall Event — Two Events Same Day

  • 10:00 AM: ENVR reports 0.3 inches for Project X. No active event → New event created (Event 1, Active).
  • Cumulative = 0.3 inches. Threshold = 0.5 inches. No inspection yet.
  • 11:00 AM: ENVR reports 0.25 inches. Event 1 data point added.
  • Cumulative = 0.55 inches > 0.5 threshold → Inspection 1 generated (ActionPending, RainEventId = Event1)
  • 12:00 PM: ENVR reports 0.0 inches. Zero count = 1.
  • 1:00 PM: ENVR reports 0.0 inches. Zero count = 2.
  • 2:00 PM: ENVR reports 0.0 inches. Zero count = 3.
  • 3:00 PM: ENVR reports 0.0 inches. Zero count = 4 → Event 1 deactivated (InActive).
  • 4:00 PM: ENVR reports 0.4 inches. No active event → New event created (Event 2, Active).
  • Cumulative = 0.4 inches < 0.5 threshold. No inspection yet.
  • 5:00 PM: ENVR reports 0.2 inches. Event 2 data point added.
  • Cumulative = 0.6 inches > 0.5 threshold → Inspection 2 generated (ActionPending, RainEventId = Event2)
  • Dashboard: 2 inspections in "Inspections Due". Inspection 1 is NOT moved to Missed or Past Due.
  • Day + 2: Both inspections move to Past Due if still not submitted.
  • Indefinitely: Both remain in Past Due — they are never automatically marked Missed.

Scenario 5: Non-Fluid Monthly, Inspector Submits Early

  • Setup: Monthly, InspectionDay = 15
  • March 15: Scheduler creates inspection. Inspector doesn't complete it.
  • March 20: Inspector submits the inspection (which was Scheduled for April 15, or submits the ActionPending one early).
  • Rescheduling occurs:

1. Setup's InspectionDay changes from 15 to 20.

2. All existing Scheduled inspections are deleted.

3. New future inspections are created for the 20th of each month.

  • From now on: Monthly inspections are on the 20th, not the 15th.

Scenario 6: Post-Rainfall Non-Event, Rainfall on Two Consecutive Days

  • Day 1: Precipitation = 0.8 inches > threshold 0.5. Inspection created: ActionPending, ScheduleDate = Day 1.
  • Day 2: Precipitation = 0.6 inches > threshold 0.5.
  • First: Day 1's inspection (ActionPending, ScheduleDate < today) → Marked Missed
  • Then: New inspection created: ActionPending, ScheduleDate = Day 2
  • Dashboard: Day 1 inspection gone (Missed), Day 2 inspection visible as "Inspections Due"