159 lines
6.7 KiB
Markdown
159 lines
6.7 KiB
Markdown
# ServiceM8 Project Progress
|
||
|
||
## Current Direction — Soft Release Poller + Apply Pipeline
|
||
|
||
We changed tune from relying mainly on ServiceM8 `form.response_created` webhooks to using a scheduled API poller as the operational safety-net/primary soft-release path.
|
||
|
||
Reason: ServiceM8 form webhooks are useful, but during testing some expected form completions did not reliably appear at the FastAPI listener. The ServiceM8 API endpoint `/api_1.0/formresponse.json` can be queried with a timestamp filter, so the safer operational pattern is now:
|
||
|
||
1. poll recent form responses with `timestamp gt 'YYYY-MM-DD HH:MM:SS'`
|
||
2. store every returned API row locally
|
||
3. detect Quote Template form responses
|
||
4. parse them into desired jobMaterial rows
|
||
5. apply only previously unapplied Quote Template responses to ServiceM8
|
||
6. track created jobMaterial UUIDs locally to avoid duplicate applies
|
||
|
||
This keeps the live webhook receiver useful as capture/diagnostics, but no longer depends on webhook delivery for completeness.
|
||
|
||
## Active Soft-Release Flow
|
||
|
||
### 1. Poll ServiceM8 form responses
|
||
- Script: `poll_form_responses_since.py`
|
||
- API endpoint: `/api_1.0/formresponse.json`
|
||
- Confirmed filter syntax:
|
||
- `?$filter=timestamp gt '2026-05-04 10:00:00'`
|
||
- Default operational DB:
|
||
- `servicem8_formresponse_poll.db`
|
||
- Poll queue/output:
|
||
- `quote-template-jobmaterials-poll-queue.jsonl`
|
||
- Quote Template form UUID:
|
||
- `3621b6be-1d19-4756-9ab4-9d5e4120f6d9`
|
||
|
||
The poller stores all fetched form responses in `form_responses_raw`, then parses Quote Template matches into `quote_template_form_responses`.
|
||
|
||
### 2. Parse Quote Template responses
|
||
- Parser: `servicem8_quote_template_parser.py`
|
||
- Extracts:
|
||
- description of works
|
||
- `Item 1..12` include lines
|
||
- `Works excluded 1..4` exclude lines
|
||
- extra descriptive include rows such as labour/materials/scaffolding/equipment fields
|
||
- Builds normalized `desired_job_materials` rows.
|
||
|
||
### 3. Select/apply parsed Quote Template responses
|
||
- Script: `apply_polled_quote_template_jobmaterials.py`
|
||
- Safe behaviour built in:
|
||
- processes one `form_response_uuid` at a time when called directly
|
||
- dry-run by default
|
||
- `--apply` performs live ServiceM8 `jobmaterial.json` creates
|
||
- refuses duplicate apply when generated material rows already exist for that form response unless `--force` is used
|
||
- Apply tracking tables in `servicem8_formresponse_poll.db`:
|
||
- `quote_template_apply_runs`
|
||
- `quote_template_apply_run_rows`
|
||
- Created ServiceM8 job material mappings are recorded in:
|
||
- `servicem8_quote_materials_state.db`
|
||
|
||
Current apply payload rules:
|
||
- All rows get:
|
||
- `tax_rate_uuid = 84e4dd28-06b3-452b-a796-1f58a20ac49b`
|
||
- `quantity = "0"`
|
||
- `price = ""`
|
||
- `displayed_amount = ""`
|
||
- `displayed_amount_is_tax_inclusive = ""`
|
||
- Header material UUIDs:
|
||
- `include_header` → `1924893b-917f-474a-adaa-2093bd622d4b`
|
||
- `exclude_header` → `4947bfd7-4875-48f7-9caf-2093b9751b9b`
|
||
- Non-header quote rows currently use:
|
||
- `f78b1d23-b9fa-40fe-a806-2425fe09cc0b`
|
||
|
||
### 4. Wrapper for scheduled/operational use
|
||
- Script: `poll_and_apply_quote_templates.sh`
|
||
- Default behaviour:
|
||
- polls the last 24 hours from script start
|
||
- stores/parses results
|
||
- applies any parsed Quote Template responses that are not already marked/applied
|
||
- logs each run under `logs/poll-and-apply-YYYYMMDD-HHMMSS.log`
|
||
- Examples:
|
||
- `./poll_and_apply_quote_templates.sh`
|
||
- `./poll_and_apply_quote_templates.sh --hours 48`
|
||
- `./poll_and_apply_quote_templates.sh --since '2026-05-04 08:00:00'`
|
||
|
||
This is the proposed scheduled entry point for soft release, e.g. every 10–30 minutes.
|
||
|
||
## Live Webhook Receiver Status
|
||
|
||
### Receiver
|
||
- Script: `servicem8_webhook_receiver.py`
|
||
- Still receives/stores:
|
||
- event webhooks
|
||
- object webhooks
|
||
- form-response webhooks
|
||
- DB:
|
||
- `servicem8_webhooks.db`
|
||
- Quote Template webhook queue:
|
||
- `quote-template-jobmaterials-queue.jsonl`
|
||
|
||
Important: webhook handling still does **not** perform live ServiceM8 writes. Heavy work stays outside the FastAPI webhook request path.
|
||
|
||
## Inspector / Web Viewer
|
||
|
||
- Script: `servicem8_inspector.py`
|
||
- Current intended views include:
|
||
- webhook events
|
||
- webhook objects
|
||
- webhook form responses
|
||
- polled form responses
|
||
- parsed polled Quote Template responses
|
||
- poll runs
|
||
- dry-run/apply runs
|
||
- generated material state
|
||
|
||
Note: the code was updated and tested on a temporary localhost port, but the existing live inspector process may need a manual/service restart before all new pages appear in the running viewer.
|
||
|
||
## Required Files for Current Soft Release
|
||
|
||
### Scripts
|
||
- `poll_and_apply_quote_templates.sh` — scheduled wrapper / main operational entry point
|
||
- `poll_form_responses_since.py` — polls ServiceM8 and populates poll DB
|
||
- `apply_polled_quote_template_jobmaterials.py` — applies parsed responses to ServiceM8
|
||
- `servicem8_quote_template_parser.py` — parsing logic
|
||
- `servicem8_inspector.py` — web inspection/progress viewer
|
||
- `servicem8_webhook_receiver.py` — still useful for webhook capture/diagnostics
|
||
|
||
### Databases / state
|
||
- `servicem8_formresponse_poll.db` — poll results, parsed quote responses, apply run status
|
||
- `servicem8_quote_materials_state.db` — created jobMaterial mapping/state to avoid duplicates
|
||
- `servicem8_webhooks.db` — webhook capture/archive/diagnostics
|
||
|
||
### Queue/log files
|
||
- `quote-template-jobmaterials-poll-queue.jsonl` — poll-derived parsed queue/output
|
||
- `logs/poll-and-apply-*.log` — wrapper run logs
|
||
- `quote-template-jobmaterials-queue.jsonl` — older webhook-derived queue; still useful but not the primary soft-release path
|
||
|
||
## Current Status
|
||
|
||
Operational soft-release pieces are now in place:
|
||
- API polling confirmed
|
||
- Quote Template detection confirmed
|
||
- parsing confirmed
|
||
- dry-run/apply command path tested
|
||
- payload adjusted for current ServiceM8 requirements
|
||
- duplicate-apply guard in place
|
||
- wrapper script created for scheduled operation
|
||
- inspector updated for progress visibility
|
||
|
||
## Not Yet Done / Next Steps
|
||
|
||
- Restart/reload the live inspector process so the new poll/apply pages are available in the active web viewer.
|
||
- Decide schedule interval for `poll_and_apply_quote_templates.sh` — likely every 10 or 30 minutes.
|
||
- Run the wrapper manually for a soft-release smoke test with a controlled recent form response.
|
||
- After confidence builds, wire the wrapper into cron/system scheduling.
|
||
- Future hardening: add reconciliation/update/delete behaviour if ServiceM8 quote form responses are edited after initial apply.
|
||
|
||
## Design Notes
|
||
|
||
- Webhooks remain lightweight and non-mutating.
|
||
- Polling is now the reliable source of completeness.
|
||
- Applying to ServiceM8 is tracked locally and guarded against duplicates.
|
||
- The wrapper intentionally skips dry-run for soft release, but the underlying apply script still supports dry-run and duplicate protection.
|