Files
plumbing/PROJECT-PROGRESS.md
T

159 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 1030 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.