July 4 - Update with recurring/scheduled inspections
This commit is contained in:
@@ -389,6 +389,19 @@ notification_matrix: id, event_type, role_key, enabled, custom_emails (JSON)
|
||||
UniqueConstraint(event_type, role_key)
|
||||
```
|
||||
|
||||
### InspectionSchedule (phase34)
|
||||
|
||||
```
|
||||
inspection_schedules: id, name VARCHAR(255), template_id (FK→inspection_templates CASCADE),
|
||||
facility_id (FK→facilities CASCADE), area_id (FK→areas SET NULL, nullable),
|
||||
inspector_id (FK→users CASCADE), frequency ENUM(daily/weekly/monthly/quarterly),
|
||||
active BOOL, created_by (FK→users SET NULL), created_at DATETIME,
|
||||
last_run_at DATETIME NULL, next_run_at DATETIME NULL
|
||||
INDEX ix_ischd_active_next (active, next_run_at)
|
||||
```
|
||||
|
||||
Recurring inspection generator. `POST /inspection-schedules/run` (token-protected cron) walks active schedules where `next_run_at <= now`, creates one `in_progress` Inspection per due schedule (assigned to `inspector_id`, dated now), notifies the inspector (`event_type='inspection_scheduled'`), then advances `next_run_at`. Managed at `/inspection-schedules` by admin/director/project_manager. Purely additive — a schedule is an automated `inspections.start()`.
|
||||
|
||||
### AuditLog
|
||||
|
||||
```
|
||||
@@ -473,6 +486,7 @@ The `DeviceRegistration` model and the duplicate `api_devices` blueprint were **
|
||||
| `audit` | `/audit` | list (admin only), view, purge |
|
||||
| `reports` | `/reports` | index, facility report, scorecard, CSV/PDF/Excel export, issues-aging, sla-compliance, followup-closure, facility summary PDF |
|
||||
| `scheduled_reports` | `/scheduled-reports` | CRUD + manual trigger (accessible via Reports sub-nav) |
|
||||
| `inspection_schedules` | `/inspection-schedules` | phase34 — recurring inspection CRUD (`@project_manager_required`) + `POST /run-now` (manual) + `POST /run` (token-protected cron materialiser) |
|
||||
| `support` | `/support` | `GET /chat`, `POST /chat/message` (AJAX→Groq), `POST /tickets`, `GET /my-tickets`, `GET/POST /my-tickets/<id>`, `GET /admin/tickets`, `GET/POST /admin/tickets/<id>` |
|
||||
| `broadcast` | `/admin/broadcast` | `GET /` (compose + history), `POST /send` — admin-only push to iOS via Notification rows (phase29) |
|
||||
| `devices` | `/admin/devices` | `GET /` (registered device list), `POST /notify` — notify users on outdated app versions (reads `api_device_tokens`) |
|
||||
@@ -675,6 +689,7 @@ EVENT_ISSUE_FLAGGED = 'issue_flagged'
|
||||
EVENT_CUSTOMER_INSPECTION_DONE = 'customer_inspection_completed'
|
||||
EVENT_CUSTOMER_ISSUE_UPDATED = 'customer_issue_updated'
|
||||
EVENT_SCORE_ALERT = 'score_alert' ← Phase 27
|
||||
EVENT_INSPECTION_SCHEDULED = 'inspection_scheduled' ← phase34
|
||||
```
|
||||
|
||||
### Cron Endpoints (all require `token=DIGEST_SECRET`)
|
||||
@@ -687,6 +702,7 @@ EVENT_SCORE_ALERT = 'score_alert' ← Phase 27
|
||||
| `POST /notifications/check-score-trends` | Facility score drop alerts (Phase 27) | `0 8 * * *` |
|
||||
| `POST /notifications/trial-reminders` | Trial-ending warning emails (≤3 days left) | `0 9 * * *` |
|
||||
| `POST /notifications/dunning-reminders` | Payment-failure escalation emails (day 3/7/14) | `0 10 * * *` |
|
||||
| `POST /inspection-schedules/run` | Materialise due recurring inspections (phase34) | `0 6 * * *` |
|
||||
|
||||
---
|
||||
|
||||
@@ -741,7 +757,7 @@ limiter = Limiter(
|
||||
|
||||
## 17. Alembic Migration Chain
|
||||
|
||||
**Current HEAD:** `phase33_tenant_settings` (31 migrations total).
|
||||
**Current HEAD:** `phase34_inspection_schedules` (32 migrations total).
|
||||
|
||||
**Chain root:** `0003_add_user_active` — a guarded squashed baseline (MT-2) that recreates the full 25-table schema with INFORMATION_SCHEMA guards. The original baseline migrations (0001/0002/0003) were lost; this file restores the chain root so Alembic can build the revision map. `down_revision = None`.
|
||||
|
||||
@@ -769,7 +785,20 @@ limiter = Limiter(
|
||||
→ phase30_device_registry
|
||||
→ phase31_device_registry
|
||||
→ phase32_device_token_columns
|
||||
→ phase33_tenant_settings ← HEAD
|
||||
→ phase33_tenant_settings
|
||||
→ phase34_inspection_schedules ← HEAD
|
||||
```
|
||||
|
||||
### phase34_inspection_schedules
|
||||
|
||||
Creates the `inspection_schedules` table backing recurring/automated inspections (see §5 model + the `inspection_schedules` blueprint). A schedule pairs a template + facility (+ optional area) + inspector + cadence; the cron endpoint `POST /inspection-schedules/run` materialises a real `in_progress` Inspection per due schedule and notifies the inspector (`event_type='inspection_scheduled'`). Uses an `INFORMATION_SCHEMA` table-existence check — safe to re-run.
|
||||
|
||||
**Deploy order:**
|
||||
```bash
|
||||
flask db upgrade
|
||||
sudo systemctl restart gunicorn
|
||||
# Add to cron (materialise due schedules daily at 06:00):
|
||||
# 0 6 * * * curl -s -X POST https://yourdomain.com/inspection-schedules/run -d "token=YOUR_DIGEST_SECRET"
|
||||
```
|
||||
|
||||
### phase28_fix_inspection_notify
|
||||
@@ -1162,6 +1191,8 @@ set -a; . /etc/jqc/control.env; set +a
|
||||
-d "token=SECRET"
|
||||
0 10 * * * curl -s -X POST https://your-domain.com/notifications/dunning-reminders \
|
||||
-d "token=SECRET"
|
||||
0 6 * * * curl -s -X POST https://your-domain.com/inspection-schedules/run \
|
||||
-d "token=SECRET"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -1596,7 +1627,7 @@ Ask: Does this change break any other code path that uses the modified function,
|
||||
**Rule 13 — List every file changed** with the exact location of each change (function name and what was modified).
|
||||
|
||||
**Rule 14 — Migrations are required for any schema change.**
|
||||
Follow the `phase{N}_description.py` naming convention. The new migration's `down_revision` must point to the current HEAD (`phase33_tenant_settings`). Use `INFORMATION_SCHEMA` existence checks so migrations are safe to re-run. Never use `batch_alter_table` for MySQL.
|
||||
Follow the `phase{N}_description.py` naming convention. The new migration's `down_revision` must point to the current HEAD (`phase34_inspection_schedules`). Use `INFORMATION_SCHEMA` existence checks so migrations are safe to re-run. Never use `batch_alter_table` for MySQL.
|
||||
|
||||
Self-contained package, own `ControlBase` + engine/session, own Alembic chain. No imports from `app/`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user