diff --git a/pos-module-accela_construct/CHANGELOG.md b/pos-module-accela_construct/CHANGELOG.md new file mode 100644 index 00000000..e69de29b diff --git a/pos-module-accela_construct/CONTRIBUTE.md b/pos-module-accela_construct/CONTRIBUTE.md new file mode 100644 index 00000000..479e2fba --- /dev/null +++ b/pos-module-accela_construct/CONTRIBUTE.md @@ -0,0 +1,8 @@ +# Publish + + git checkout master; git pull + pos-cli modules version x.x.x + git tag x.x.x + git push --tags; git push + pos-cli modules push --email your@email.com + diff --git a/pos-module-accela_construct/LICENSE b/pos-module-accela_construct/LICENSE new file mode 100644 index 00000000..f8dcd169 --- /dev/null +++ b/pos-module-accela_construct/LICENSE @@ -0,0 +1,20 @@ +Copyright platformOS and other contributors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/pos-module-accela_construct/README.md b/pos-module-accela_construct/README.md new file mode 100644 index 00000000..a71e9871 --- /dev/null +++ b/pos-module-accela_construct/README.md @@ -0,0 +1,969 @@ +# accela_construct + +A platformOS module that wraps the [Accela Construct API v4](https://developer.accela.com/docs/construct-apiIndex.html): +**Records** and all of its sub-resources (WorkflowTasks, Payments, Parcels, +Owners, Inspections, Documents, Conditions, Addresses), **Inspections** +(including its Checklists and Conditions sub-resources), and **Searches** +— including OAuth2 password-grant authentication with automatic token +refresh. See [Supported endpoints](#supported-endpoints) for the full list. + +## How it's built (platformOS constraints) + +platformOS doesn't let you attach custom resolvers to GraphQL, so this isn't +a "GraphQL API" in the REST-wrapper sense. The real architecture is: + +1. **API Call Notifications** (`public/api_calls/*.liquid`) are the only way + to make outbound HTTP requests. There are three of them: + `accela_generic` (handles GET/POST/PUT/DELETE, with the HTTP verb passed + through as `data.request_type` — one template, not one per verb), + `accela_post_multipart` (its headers/body shape differs enough from the + plain-JSON case to need its own file), and `accela_token_request` for + OAuth. They're generic (path/method/body come from the caller) rather + than one file per Accela endpoint, to keep the module maintainable. + `accela_generic` and `accela_post_multipart` build their `to:` URL as + `{% function accela_base_url = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_BASE_URL' %}{{ accela_base_url }}{{ data.path }}` + — `ACCELA_CONSTRUCT_BASE_URL` is looked up in exactly those 2 places, nowhere + else in the module; every query/command only ever builds a bare path + (e.g. `/records`), never a full URL. +2. **[pos-module-core](https://github.com/Platform-OS/pos-modules/tree/master/pos-module-core)'s + `modules/core/api_calls/send`** is the GraphQL operation that fires those + notifications synchronously via the built-in `api_call_send` mutation + and returns the HTTP response inline (aliased as `api_call` in the + response). This module doesn't own its own copy of that mutation - + `pos-module.json` already depends on `core` (`^2.0.0`), so `send.liquid` + and `get_valid_token.liquid` call core's wrapper directly instead of + maintaining a near-identical `generic_send.graphql` of our own. +3. **Liquid functions** are the actual developer-facing "wrapper" — one + function per Accela endpoint, split per platformOS module convention into + **queries** (`public/lib/queries/**/*.liquid`, read-only calls like + `records/search`, `records/inspection_types/list`) and **commands** + (`public/lib/commands/**/*.liquid`, mutating calls like + `records/create`, `inspections/schedule`, `records/documents/upload`). + Each builds the path/query string/JSON body, calls + `lib/accela_client/send`, and returns a normalized result hash. + The shared HTTP/token plumbing itself (`send.liquid`, + `get_valid_token.liquid`) lives in `public/lib/accela_client/` since it + isn't a resource-facing query or command. +4. **`accela_oauth_token`** is a Table (`public/schema/accela_oauth_token.yml`) + used to cache the OAuth token between requests. `get_valid_token.liquid` + reads it via `lib/queries/accela_oauth_token/find` (the same + query-wrapper convention used for Accela's own resources, applied here + to the module's internal token table), and only calls Accela's token + endpoint when the cached token is missing/expired. + +Call chain: `your page/partial` → `lib/queries/records/search` → +`lib/accela_client/send` → (`lib/accela_client/get_valid_token` if needed) → +`modules/core/api_calls/send` → `api_call_send` → Accela. + +This module also uses pos-module-core for validation and constant +lookups rather than hand-rolling either: every command's `check.liquid` +calls `modules/core/validations/presence`, and every constant read +anywhere in the module — including the `api_calls/*.liquid` templates' +`to:` URL — goes through `modules/core/queries/constants/find` instead of +`context.constants[...]` directly. There are zero direct +`context.constants` reads left in this module. Using the query there +instead of direct access is actually *more* robust, not just more +consistent: `modules/core/queries/constants/find` itself falls back to a +live `constant()` GraphQL query when `context.constants` isn't populated, +so even if that turns out not to be hydrated inside a notification +template's frontmatter (see Known gaps), the lookup still works. +`get_valid_token.liquid`'s OAuth form body is also built with core's +`modules/core/helpers/hash_to_x_form_encoded` from a plain hash, instead +of manually `url_encode`-ing and concatenating each field. + +5. **Background retries** are opt-in per call via a `with_retries: true` + param, present on every query and command except `records/documents/upload` + (always MULTIPART, so retrying would never apply - the param is simply + not exposed there rather than being a documented no-op). + `lib/accela_client/send.liquid` still makes its first attempt + synchronously and returns that result either way; if it fails and + `with_retries` was set, it hands off to `lib/accela_client/schedule_retry.liquid`, + which schedules a `{% background %}` job after + `ACCELA_CONSTRUCT_RETRY_DELAY_MINUTES * retry number` minutes (linear backoff - + 1x, 2x, 3x the base delay for the 1st/2nd/3rd retry), up to + `ACCELA_CONSTRUCT_MAX_RETRIES` retries. Every file in the chain + (`send.liquid`/`schedule_retry.liquid`/`perform_retry_attempt.liquid`) + shares one absolute, 1-based `attempt_number` (1 = the original call, + 2 = the first retry, ...) rather than mixing that with a separate + retry-relative counter, and `ACCELA_CONSTRUCT_RETRY_DELAY_MINUTES` is looked up + once (by whichever call first triggers scheduling) and threaded through + the rest of the chain instead of being re-queried on every retry. + Neither `schedule_retry.liquid` nor the `{% background %}` job's data + carries the request itself (`method`/`path`/`payload`) - only the + `accela_request` row's id (see point 6 below). `lib/accela_client/perform_retry_attempt.liquid` + runs inside that job, looks the request back up via + `queries/accela_request/get`, calls `send` again with it (without + `with_retries`, so it doesn't re-trigger its own scheduling), and + either logs success, schedules the next attempt, or logs + `accela_retry_exhausted` and gives up. Retries are log-only - + there's no table tracking retry state, and nothing observes the + eventual outcome except logs (`accela_retry_scheduled`/ + `accela_retry_succeeded`/`accela_retry_exhausted`) and the + `accela_request`/`accela_request_response` tables below. MULTIPART + requests are never retried, since file content can't be safely + re-sent from a detached background job. + +6. **Every request/response is logged, in two tables - one row per + logical request, one row per attempt against it** - unconditionally, + unlike retries, which are opt-in. `accela_request` + (`public/schema/accela_request.yml`: `method`, `path`, + `request_payload`, `reference_id`, `reference_schema`) holds one row + per logical request, created once on its first attempt - and never + written to again after that, even across retries. + `accela_request_response` (`public/schema/accela_request_response.yml`: + `request_id` [`belongs_to: accela_request`], `attempt_number`, + `status`, `response_body` [the raw response string], `success`, + `error`) holds one row per attempt against that request, including + every retry - so a request that retries twice ends up with one + `accela_request` row and three `accela_request_response` rows + (`attempt_number` 1, 2, 3). There's no stored "how many attempts so + far" counter on `accela_request` - filter `queries/accela_request_response/list` + by `request_id` and read its `total_entries` instead of maintaining a + separate count that could drift from the rows it's supposed to + summarize. + `reference_id`/`reference_schema` are stored as two flat columns + (naming matches [pos-module-core](https://github.com/Platform-OS/pos-modules/tree/master/pos-module-core)'s + own polymorphic-reference convention on its `status` table), but every + caller-facing param is a single hash: `reference: { "id": ..., "table": ... }`. + `table` is a real platformOS `Record.table` value, not a caller-invented + label - if you already have the fetched record in hand and its own + query selected `table`, just pass it directly (`reference: application`); + if you only have an id, pass `reference: { "id": application_id }` and + `table` is looked up automatically via `accela_client/resolve_reference_table.liquid` + (one extra GraphQL read - `records()` can look up any record by id + regardless of which table it's actually in, so this works for any + platformOS record, not just ones this module knows about). Set once at + creation, otherwise unused by this module. `send.liquid`/`post_search.liquid` + accept `reference` directly, and every query/command wrapper function + forwards it the same way it forwards `with_retries` - e.g. + `{% function result = 'modules/accela_construct/commands/records/create', + record: record, reference: { "id": application.id, "table": application.table } %}`. + `lib/accela_client/log_request.liquid` (called from `send.liquid`) + owns the write: if `request_id` is blank (attempt 1) it resolves + `table` if needed and creates the `accela_request` row, then uses its + new id; otherwise it reuses the `request_id` passed in from a prior + attempt as-is - retries touch `accela_request_response` only, and + `reference` is never looked at again once the request row exists. A + failed write here is ignored - it never fails or blocks the underlying + Accela request. The write happens synchronously whenever something + needs its result: when this attempt is about to trigger a retry (the + `accela_request` id becomes the chain's `request_id` before + scheduling), and when this attempt succeeded (the + `accela_construct_request_succeeded` event - see "Events" below - + needs both ids). Only a non-retried failure has nothing waiting on it, + so that's the one case the write still runs in the background, + unread by anything. For that one case, the rows for a given call may + not be queryable for a brief moment after the call returns (eventual + consistency), rather than being guaranteed visible immediately. Read + access is three normal queries - + `queries/accela_request/list` (filterable by `method`/`path`/ + `reference: { "id", "table" }` - unlike the write side, `table` is + never auto-resolved here, since filtering by `id` alone is already + unambiguous), `queries/accela_request/get` (fetch one by id - also + what `perform_retry_attempt.liquid` uses to look up what to resend), + and `queries/accela_request_response/list` (filterable by + `request_id`/`success`, so `request_id: ` pulls a whole retry + chain's responses together, and `total_entries` on that result is "how + many attempts so far") - there's no admin UI, only the GraphQL/Liquid + layer. + +## Install + +1. Copy `modules/accela_construct` into your instance's `modules/` directory + (sibling to `app/`), or install/push it through the Partner Portal + Marketplace per platformOS module conventions. +2. Fill in real values in `template-values.json` (or set them directly as + Constants — see below) — **do not commit real secrets**. +3. Deploy: + ``` + pos-cli deploy + ``` + Table creation isn't a separate migration step - `pos-cli deploy`/`sync` + creates and syncs the `accela_oauth_token`/`accela_request`/ + `accela_request_response` tables directly from their `schema/*.yml` + files as part of a normal deploy. +4. Seed the `ACCELA_CONSTRUCT_*` constants from `template-values.json` by + running the one migration this module ships (`public/migrations/..._set_accela_constants.liquid`, + which does need an explicit migration since it's seeding Constants + data, not creating a table): + ``` + pos-cli migrations run 20260730120100 + ``` +5. Verify the tables/constants exist (GraphiQL console): + ```graphql + query { records(filter: { table: { value: "modules/accela_construct/accela_oauth_token" } }, per_page: 1) { results { id } } } + ``` +6. Register an app at the [Accela Developer Portal](https://developer.accela.com/ApplicationList/Index) + to get your `client_id`/`client_secret` (app id/app secret). Accela + publishes a public sandbox for initial testing: agency `Nullisland`, + user `developer` / password `accela`, `environment: TEST`. + +## Required constants + +Set these as encrypted platformOS Constants (`constant_set` mutation, or via +the seed migration + `template-values.json`): + +| Constant | Example | Notes | +|---|---|---| +| `ACCELA_CONSTRUCT_BASE_URL` | `https://apis.accela.com/v4` | API base URL | +| `ACCELA_CONSTRUCT_AUTH_URL` | `https://auth.accela.com/oauth2/token` | OAuth token endpoint | +| `ACCELA_CONSTRUCT_APP_ID` | — | sent as `x-accela-appid` on every call | +| `ACCELA_CONSTRUCT_CLIENT_ID` | — | OAuth client_id | +| `ACCELA_CONSTRUCT_CLIENT_SECRET` | — | OAuth client_secret | +| `ACCELA_CONSTRUCT_USERNAME` | — | Civic ID or Accela Automation account | +| `ACCELA_CONSTRUCT_PASSWORD` | — | | +| `ACCELA_CONSTRUCT_AGENCY` | `Nullisland` | agency name | +| `ACCELA_CONSTRUCT_ENVIRONMENT` | `TEST` or `PROD` | must match the agency's configured environments | +| `ACCELA_CONSTRUCT_SCOPE` | `get_record create_record update_record get_inspections create_inspections update_inspections get_documents create_documents` | space-delimited, per endpoint you plan to call | +| `ACCELA_CONSTRUCT_MAX_RETRIES` | `3` | optional, defaults to `3`; total background retries per call when `with_retries: true` is passed (0 disables retrying) | +| `ACCELA_CONSTRUCT_RETRY_DELAY_MINUTES` | `1` | optional, defaults to `1`; base delay in minutes, multiplied by the retry number (1st, 2nd, ...) for linear backoff | + +## Usage examples + +All functions return `{ success, status, body, raw, error }`. Always check +`success` (or, for bulk cancel/delete calls, each item's `isSuccess` inside +`body.result[]` — see gotcha below). Commands additionally short-circuit +before calling Accela if required params are missing, returning +`{ success: false, status: null, error: "accela_validation_failed", errors: { : [] } }` +— note `errors[field]` is an **array** of messages (pos-module-core's +`register_error` appends to it), not a single string. See +[Queries vs. commands](#queries-vs-commands) below. + +**Search records** +```liquid +{% liquid + assign criteria = { "module": "Building", "address": { "postalCode": "94108" } } + function result = 'modules/accela_construct/queries/records/search', criteria: criteria, limit: 25 +%} +{% if result.success %}{{ result.body.result | json }}{% endif %} +``` + +**Get a record** +```liquid +{% function result = 'modules/accela_construct/queries/records/get', ids: '12CAP-00000-00001', expand: 'addresses,parcels' %} +``` + +**Check required fields, then create a record** +```liquid +{% liquid + function described = 'modules/accela_construct/queries/records/describe_create', type: 'Building/Residential/Alteration/NA' + + assign record = { + "type": { "id": "Building-Residential-Alteration-NA" }, + "description": "Residence alteration", + "parcels": [{ "parcelNumber": "005020018" }], + "addresses": [{ "isPrimary": "Y", "streetName": "123 Main Street", "city": "Pleasanton", "postalCode": "94588", "state": { "value": "CA" } }], + "contacts": [{ "isPrimary": "Y", "fullName": "Joe Smith", "email": "jsmith@email.com", "type": { "value": "Contractor" } }] + } + function result = 'modules/accela_construct/commands/records/create', record: record +%} +``` + +**Schedule an inspection** +```liquid +{% liquid + function types = 'modules/accela_construct/queries/records/inspection_types/list', record_ids: record_id + # pick the right type.id from types.body.result, then: + assign inspection = { "type": { "id": 173 }, "inspectorId": "MINSPECTOR", "recordId": { "id": "ISLANDTON-12CAP-00000-0000L" }, "requestDate": "2026-08-01", "scheduleDate": "2026-08-05" } + function result = 'modules/accela_construct/commands/inspections/schedule', inspection: inspection +%} +``` + +**Cancel an inspection** +```liquid +{% function result = 'modules/accela_construct/commands/inspections/cancel', ids: inspection_id %} +{% comment %} check result.body.result[0].isSuccess, not just result.success {% endcomment %} +``` + +**Retry a failed call in the background** +```liquid +{% function result = 'modules/accela_construct/commands/records/create', record: record, with_retries: true %} +{% comment %} + result is still this attempt's outcome, returned synchronously. If it + failed, up to ACCELA_CONSTRUCT_MAX_RETRIES retries are now scheduled in the + background with increasing delay - see "Background retries" above and + lib/accela_client/send.liquid. Their outcome is log-only. +{% endcomment %} +``` + +**Tag a call with a reference object** +```liquid +{% comment %} if `application` was fetched via a query that selected `table`, just pass it: {% endcomment %} +{% function result = 'modules/accela_construct/commands/records/create', record: record, reference: application %} + +{% comment %} or, with only an id in hand - `table` gets resolved automatically: {% endcomment %} +{% function result = 'modules/accela_construct/commands/records/create', record: record, reference: { "id": application_id } %} + +{% comment %} + Either way, the accela_request row this call creates carries + reference_id/reference_schema, so later you can find every Accela call + made on behalf of this application with: + {% function requests = 'modules/accela_construct/queries/accela_request/list', reference: { "id": application_id } %} +{% endcomment %} +``` + +**List and upload documents** +```liquid +{% function docs = 'modules/accela_construct/queries/records/documents/list', record_id: record_id %} +{% function result = 'modules/accela_construct/commands/records/documents/upload', + record_id: record_id, file_field: file_content, file_name: 'site_plan.pdf', + content_type: 'application/pdf', description: 'Site plan' %} +``` + +A working smoke-test page is included at `/accela_construct/test?module=Building` +(remove or lock this down before going to production). + +## Supported endpoints + +Every function below is `modules/accela_construct//`. +The **Params** column lists every param the function itself takes, in +call order, *excluding* `with_retries` and `reference`, which every +single query and command accepts identically (see "Background +retries" and "Request/response logging" above) - repeating them on all 88 +rows would just be noise. A plain name means the param is required (this +module's own `check.liquid` rejects the call with `accela_validation_failed` +before ever reaching Accela if it's missing); `name?` means optional; +`name(!)` means required *and* Accela's own docs mark it required +independently of this module's interface contract (everywhere else, a +required body-hash param like `record`/`parcel`/`condition` is required by +*this module's own convention*, not by Accela, which documents those +bodies' individual fields as optional - see "Queries vs. commands" below +and each function's own `check.liquid`). + +### Records + +| Function | Params | Method | Accela path | +|---|---|---|---| +| `queries/records/get` | `ids`, `expand?`, `fields?` | GET | `/records/{ids}` | +| `queries/records/search` | `criteria?`, `offset?`, `limit?`, `expand?`, `fields?` | POST | `/search/records` | +| `queries/records/describe_create` | `type` | GET | `/records/describe/create` | +| `queries/records/list` | `offset?`, `limit?`, `fields?`, `module?`, `status?` | GET | `/records` | +| `queries/records/mine` | `offset?`, `limit?`, `fields?` | GET | `/records/mine` | +| `queries/records/additional` | `record_id` | GET | `/records/{recordId}/additional` | +| `queries/records/related` | `record_id` | GET | `/records/{recordId}/related` | +| `queries/records/usercomments` (deprecated by Accela) | `record_id` | GET | `/records/{recordId}/usercomments` | +| `queries/records/votes` | `record_id` | GET | `/records/{recordId}/votes` | +| `queries/records/votes_summary` | `record_id` | GET | `/records/{recordId}/votes/summary` | +| `commands/records/create` | `record` | POST | `/records` | +| `commands/records/update` | `id`, `record` | PUT | `/records/{id}` | +| `commands/records/initialize` | `record` | POST | `/records/initialize` | +| `commands/records/delete` | `ids` | DELETE | `/records/{ids}` | +| `commands/records/finalize` | `record_id` | POST | `/records/{recordId}/finalize` | +| `commands/records/additional/update` | `record_id`, `additional?` | PUT | `/records/{recordId}/additional` | +| `commands/records/votes/create` | `record_id`, `vote?` | POST | `/records/{recordId}/votes` | +| `commands/records/usercomments/create` (deprecated by Accela) | `record_id`, `comment?` | POST | `/records/{recordId}/usercomments` | +| `commands/records/related/create` | `record_id`, `related_record_ids(!)` | POST | `/records/{recordId}/related` | +| `commands/records/related/delete` | `record_id`, `child_record_ids` | DELETE | `/records/{recordId}/related/{childRecordIds}` | + +### Records/WorkflowTasks, Payments + +| Function | Params | Method | Accela path | +|---|---|---|---| +| `queries/records/workflow_tasks/list` | `record_id` | GET | `/records/{recordId}/workflowTasks` | +| `queries/records/workflow_tasks/get` | `record_id`, `id` | GET | `/records/{recordId}/workflowTasks/{id}` | +| `queries/records/workflow_tasks/statuses` | `record_id`, `id` | GET | `/records/{recordId}/workflowTasks/{id}/statuses` | +| `queries/records/workflow_tasks/histories` | `record_id` | GET | `/records/{recordId}/workflowTasks/histories` | +| `queries/records/workflow_tasks/comments_histories` | `record_id` | GET | `/records/{recordId}/workflowTasks/comments/histories` | +| `commands/records/workflow_tasks/update` | `record_id`, `id`, `task` | PUT | `/records/{recordId}/workflowTasks/{id}` | +| `queries/records/payments/list` | `record_id` | GET | `/records/{recordId}/payments` | +| `queries/records/payments/get` | `record_id`, `payment_id` | GET | `/records/{recordId}/payments/{paymentId}` | + +### Records/Parcels, Owners, Addresses + +Same shape for all three (`` = `parcels` \| `owners` \| `addresses`; +body param = `parcel` \| `owner` \| `address`): + +| Function | Params | Method | Accela path | +|---|---|---|---| +| `queries/records//list` | `record_id` | GET | `/records/{recordId}/` | +| `commands/records//create` | `record_id`, `` | POST | `/records/{recordId}/` | +| `commands/records//update` | `record_id`, `id`, `` | PUT | `/records/{recordId}//{id}` | +| `commands/records//delete` | `record_id`, `ids` | DELETE | `/records/{recordId}//{ids}` | + +### Records/Conditions + +| Function | Params | Method | Accela path | +|---|---|---|---| +| `queries/records/conditions/list` | `record_id` | GET | `/records/{recordId}/conditions` | +| `queries/records/conditions/get` | `record_id`, `id` | GET | `/records/{recordId}/conditions/{id}` | +| `queries/records/conditions/histories` | `record_id`, `id` | GET | `/records/{recordId}/conditions/{id}/histories` | +| `commands/records/conditions/create` | `record_id`, `condition` | POST | `/records/{recordId}/conditions` | +| `commands/records/conditions/update` | `record_id`, `id`, `condition` | PUT | `/records/{recordId}/conditions/{id}` | +| `commands/records/conditions/delete` | `record_id`, `ids` | DELETE | `/records/{recordId}/conditions/{ids}` | + +### Records/Inspections, Records/Documents + +| Function | Params | Method | Accela path | +|---|---|---|---| +| `queries/records/inspections/list` (record-scoped) | `record_id`, `offset?`, `limit?`, `fields?` | GET | `/records/{recordId}/inspections` | +| `queries/records/inspection_types/list` (record-scoped) | `record_ids` | GET | `/records/{recordIds}/inspectionTypes` | +| `queries/records/documents/list` | `record_id`, `fields?` | GET | `/records/{recordId}/documents` | +| `queries/records/documents/categories` | `record_id` | GET | `/records/{recordId}/documentCategories` | +| `queries/documents/download` | `document_id` | GET | `/documents/{documentId}/download` | +| `commands/records/documents/upload` | `record_id`, `file_field`, `file_name`, `content_type`, `category?`, `description?` | POST | `/records/{recordId}/documents` | +| `commands/records/documents/delete` | `record_id`, `document_ids` | DELETE | `/records/{recordId}/documents/{documentIds}` | + +### Inspections + +| Function | Params | Method | Accela path | +|---|---|---|---| +| `queries/inspections/all` (unscoped listing/filter) | `module?`, `types?`, `scheduled_date_from?`, `scheduled_date_to?`, `inspector_ids?`, `district_ids?`, `offset?`, `limit?` | GET | `/inspections` | +| `queries/inspections/get` | `ids`, `fields?` | GET | `/inspections/{ids}` | +| `queries/inspections/available_dates` | `type_id(!)`, `record_id(!)`, `start_date(!)`, `offset?`, `limit?`, `fields?` | GET | `/inspections/availableDates` | +| `queries/inspections/histories` | `inspection_ids` | GET | `/inspections/{inspectionIds}/histories` | +| `queries/inspections/related` | `id` | GET | `/inspections/{id}/related` | +| `commands/inspections/schedule` | `inspection` | POST | `/inspections/schedule` | +| `commands/inspections/set_schedule` (schedule a pending inspection) | `id`, `inspection` | PUT | `/inspections/{id}/schedule` | +| `commands/inspections/reschedule` | `id`, `changes` | PUT | `/inspections/{id}/reschedule` | +| `commands/inspections/result` | `id`, `inspection_result` | PUT | `/inspections/{id}/result` | +| `commands/inspections/update` | `id`, `inspection` | PUT | `/inspections/{id}` | +| `commands/inspections/assign` | `ids`, `inspector_id(!)` | PUT | `/inspections/{ids}/assign` | +| `commands/inspections/cancel` | `ids` | DELETE | `/inspections/{ids}/cancel` | +| `commands/inspections/delete` | `ids` | DELETE | `/inspections/{ids}` | +| `commands/inspections/related/create` | `id`, `related_inspection_ids(!)` | POST | `/inspections/{id}/related` | +| `commands/inspections/related/delete` | `id`, `child_ids` | DELETE | `/inspections/{id}/related/{childIds}` | + +### Inspections/Checklists, Inspections/Conditions + +| Function | Params | Method | Accela path | +|---|---|---|---| +| `queries/inspections/checklists/list` | `inspection_id` | GET | `/inspections/{inspectionId}/checklists` | +| `commands/inspections/checklists/create` | `inspection_id`, `checklist` | POST | `/inspections/{inspectionId}/checklists` | +| `commands/inspections/checklists/delete` | `inspection_id`, `ids` | DELETE | `/inspections/{inspectionId}/checklists/{ids}` | +| `queries/inspections/conditions/list` | `inspection_id` | GET | `/inspections/{inspectionId}/conditions` | +| `queries/inspections/conditions/get` | `inspection_id`, `id` | GET | `/inspections/{inspectionId}/conditions/{id}` | +| `queries/inspections/conditions/histories` | `inspection_id`, `id` | GET | `/inspections/{inspectionId}/conditions/{id}/histories` | +| `commands/inspections/conditions/create` | `inspection_id`, `condition` | POST | `/inspections/{inspectionId}/conditions` | +| `commands/inspections/conditions/update` | `inspection_id`, `id`, `condition` | PUT | `/inspections/{inspectionId}/conditions/{id}` | +| `commands/inspections/conditions/delete` | `inspection_id`, `ids` | DELETE | `/inspections/{inspectionId}/conditions/{ids}` | + +### Searches + +`queries/records/search` (above) covers Search/records; every other +Search endpoint lives under a new `queries/searches/` namespace. All take +the same `criteria?`/`offset?`/`limit?`/`expand?`/`fields?` shape, except +`global` (plain GET, query-string only) - repeated per row below for +completeness, even though it's identical every time: + +| Function | Params | Method | Accela path | +|---|---|---|---| +| `queries/searches/addresses` | `criteria?`, `offset?`, `limit?`, `expand?`, `fields?` | POST | `/search/addresses` | +| `queries/searches/agencies` | `criteria?`, `offset?`, `limit?`, `expand?`, `fields?` | POST | `/search/agencies` | +| `queries/searches/global` | `query?`, `type?`, `modules?`, `offset?`, `limit?`, `sort?`, `direction?` | GET | `/search/global` | +| `queries/searches/assessments` | `criteria?`, `offset?`, `limit?`, `expand?`, `fields?` | POST | `/search/assessments` | +| `queries/searches/contacts` | `criteria?`, `offset?`, `limit?`, `expand?`, `fields?` | POST | `/search/contacts` | +| `queries/searches/costs` | `criteria?`, `offset?`, `limit?`, `expand?`, `fields?` | POST | `/search/costs` | +| `queries/searches/inspections` | `criteria?`, `offset?`, `limit?`, `expand?`, `fields?` | POST | `/search/inspections` | +| `queries/searches/owners` | `criteria?`, `offset?`, `limit?`, `expand?`, `fields?` | POST | `/search/owners` | +| `queries/searches/parcels` | `criteria?`, `offset?`, `limit?`, `expand?`, `fields?` | POST | `/search/parcels` | +| `queries/searches/parts` | `criteria?`, `offset?`, `limit?`, `expand?`, `fields?` | POST | `/search/parts` | +| `queries/searches/professionals` | `criteria?`, `offset?`, `limit?`, `expand?`, `fields?` | POST | `/search/professionals` | + +## Known gaps — verify against a real sandbox before production use + +This module was built from Accela/platformOS documentation without a live +sandbox, per the requester's choice to scaffold first and add credentials +later. Before relying on it, verify: + +- **Newly added endpoints' field-level requirements** (everything in + [Supported endpoints](#supported-endpoints) beyond the original + records/inspections/documents core): a representative sample of ~15 + endpoints across every resource category was individually verified + against Accela's per-endpoint docs at + `developer.accela.com/docs/api_reference/v4.*.html` (confirming, among + other things, that Accela documents essentially no request-body field as + hard-required anywhere in the API — required-ness is agency/record-type + configured, not fixed in the schema — with the handful of genuine + exceptions marked `(!)` in the table above). The remaining ~70 endpoints + follow the same structural pattern by extension but were not + individually re-verified field-by-field; if an endpoint's actual required + fields differ from what's documented here, only `check.liquid`'s + presence checks need updating — `build.liquid`'s path/payload + construction is generic and doesn't hardcode field names it doesn't need. +- **Multipart document upload** (`commands/records/documents/upload/build.liquid`, + `api_calls/accela_post_multipart.liquid`): platformOS's `post_multipart` + request type is documented to exist, but the exact Liquid syntax for + attaching a raw binary part inside an API Call Notification body is not + documented. The current implementation is a best-effort scaffold. +- **`{% function %}` calls inside an API Call Notification body**: both + generic templates (`api_calls/accela_{generic,post_multipart}.liquid`) + build their `to:` URL by calling `modules/core/queries/constants/find` + inline inside the `to:` frontmatter string (a `{% function %}` tag with + no output, immediately followed by `{{ accela_base_url }}{{ data.path }}` + on the same line). Every other `{% function %}` call in this module is + inside a page or a `{% liquid %}`-block lib file, contexts already + proven to support it; whether an API Call Notification template's own + frontmatter renders custom tags (as opposed to just `{{ }}` output, + which it already does for `data.app_id` etc.) the same way has not been + independently confirmed. If it doesn't, fall back to reading + `context.constants['ACCELA_CONSTRUCT_BASE_URL']` directly there (as earlier + versions of this module did) instead of going through the query. +- **`{% liquid %}` multi-statement tag, native hash-literal `assign`, + dot-notation `assign` (`assign object.key = value`), and string + interpolation in `assign`**: every file in this module uses one + `{% liquid ... %}` block per file (instead of many separate single-line + `{% tag %}`s), builds/patches hashes with `assign x = { "key": value }` + and `assign x.key = value` (instead of `capture` + `parse_json`, or a + `hash_merge` filter this module no longer uses at all), and builds + URLs/query strings/form bodies with `assign x = "text {{ var }} text"` + (instead of `capture`). Unlike when this caveat was first written, these + aren't just inferred from documentation — pos-module-core's own shipped + source uses every one of these constructs (e.g. `modules/core/public/lib/commands/email/send/check.liquid` + does `assign object.valid = c.valid`; `modules/core/public/lib/validations/presence.liquid` + is a bare `{% liquid %}` block ending in `return c`), which is meaningful + corroboration since core is officially maintained by platformOS. Still + worth a live smoke test on your instance before relying on this in + production, since none of this has been exercised outside these two repos. +- **Binary document download** (`documents/download.liquid`): assumes + `response.body` is JSON-parseable, which is wrong for a binary stream. + Confirm how `api_call_send` exposes binary/non-JSON response bodies + (likely base64) and adjust `lib/accela_client/send.liquid` accordingly, e.g. by + passing a `raw_response: true` flag that skips `parse_json`. +- **`json` Liquid filter**: used throughout to serialize hashes into JSON + strings for request bodies/constants. Confirm this filter is available on + your platformOS instance (it's a common Liquid extension but wasn't + independently confirmed in the docs pulled for this module); if not, + switch to explicit string concatenation or `to_json`/`hash_to_json` if + that's what your instance provides. +- **`constant_set` from a migration** with `<%= template_value %>` + interpolation: observed in other shipped modules (e.g. `payments-stripe`) + but not documented as an official pattern. Confirm it works, or set + constants manually via GraphiQL instead. +- **No `client_credentials` OAuth grant**: Accela's docs only document + `password`, `authorization_code`, `token` (implicit), and `refresh_token`. + This module uses `password` grant (resource owner credentials) since + that's the standard approach for unattended agency-side integrations. + There's also a separate, non-OAuth "App credentials" header auth + (`x-accela-appid` + `x-accela-appsecret`) for a narrower set of endpoints, + not currently wired up. +- **Accela can return HTTP 200 with an embedded error** (EMSE server-side + scripting failures surface as `{"message": "EMSE operation failed.", + "code": "emse_error"}` inside a 2xx response). `lib/accela_client/send.liquid` + currently treats any 2xx as `success: true` — add a check for + `body.code == 'emse_error'` if your agency uses EMSE scripts. +- **Rate limits**: Accela exposes `x-ratelimit-*` response headers but + publishes no fixed numeric limit. This module doesn't currently read or + react to those headers — add backoff logic if you hit 429s in practice. +- **`accela_request`/`accela_request_response` have no retention policy**: + every logical request and every attempt against it is logged (see + "Request/response logging" above) and nothing ever prunes old rows. On + a busy integration these tables grow unbounded - add a scheduled + cleanup (e.g. a `{% background %}` job deleting rows past some age) + before relying on this in a high-volume production environment. + `accela_request_response` also stores response bodies as plain text: + for the binary document-download gap noted above, whatever + `response_body` ends up holding for that endpoint is whatever + `send.liquid` put in `result.raw` - fix that gap first if you need those + rows to be meaningful. The full raw body is stored even for large + successful responses (e.g. a `searches/*` call returning close to the + 1000-record Accela max) - if that turns out to matter, cap/truncate + `response_body` for successful attempts rather than storing it + unconditionally. +- **`accela_client/resolve_reference_table.liquid` assumes `records()` + can look up any record by `id` alone, across every table in the + instance, without a `table` filter.** This is what makes + `reference: { "id": ... }` (without `table`) work for *any* platformOS + record, not just ones this module knows about - but it hasn't been + exercised against a live instance. If `id` values aren't actually + unique across tables (e.g. two unrelated tables both happen to have a + row with the same numeric id) or `records()` requires a `table` filter + to return anything, the lookup will return the wrong record's `table` + or nothing at all. Verify this before relying on the auto-resolve path + in production - passing `reference: fetched_record` directly (skipping + the lookup entirely, since you already have `table`) sidesteps this + gap completely. +- **The whole retry chain depends on the `accela_request` write on + attempt 1 succeeding** - and this is a bigger deal than it sounds, + since `perform_retry_attempt.liquid` fetches `method`/`path`/`payload` + from that row rather than carrying them through the chain (see point 5 + above). `log_request.liquid` only creates an `accela_request` row on + attempt 1 (when `request_id` is blank); if that specific write fails, + `request_id` comes back blank and `send.liquid` schedules the retry with + it anyway. `perform_retry_attempt.liquid` guards the obvious + consequence - it checks whether `queries/accela_request/get` actually + found a row before calling `send`, and logs `accela_retry_exhausted` and + gives up if not, rather than calling `send` with a nil `method`/`path`. + So the failure mode is contained (no crash, no malformed Accela call), + but the retry chain still silently stops instead of ever resending the + original request. In other words: under the *old* single-table design + this failure mode only broke correlation (cosmetic); under this one it + aborts the retry outright. In practice this only matters if the + `accela_request` write fails on attempt 1 specifically but the rest of + the module's writes keep working (if writes are failing consistently, + there's nothing to retry against anyway). +- **Retry/logging orchestration lives inside `send.liquid` itself**, + which the file's own header still describes as a plain "generic + authenticated Accela API request." A cleaner layering would keep + `send.liquid` a pure one-call HTTP function and move retry-scheduling + + logging into a thin wrapper that all 88 query/command files call + instead - `perform_retry_attempt.liquid` already has to work around + `send.liquid` doing more than transport (it must never pass + `with_retries: true` back in, to avoid re-triggering scheduling from + inside a retry). Not fixed here since it would mean repointing all 88 + call sites, which is out of scope for the current diff. A related, + smaller version of the same issue: "should this attempt retry at all" + (`send.liquid`'s `with_retries`/success/method/`max_retries>0` check) + and "should the chain continue" (`perform_retry_attempt.liquid`'s + success/`retry_number` vs `max_retries` check) are two independently + written predicates that happen to agree today only because retryability + is currently trivial (any non-2xx, non-MULTIPART failure qualifies). If + retry eligibility ever grows real rules (e.g. only retry 5xx, never + retry `DELETE`), that rule has to be added and kept in sync in both + places rather than owned by one shared predicate - same root cause as + the layering point above, not a new problem to fix separately. +- **The retry chain's arithmetic (`schedule_retry.liquid`'s backoff delay, + `perform_retry_attempt.liquid`'s exhaustion check) has no automated test + coverage**, unlike this module's other pure/deterministic helpers + (`error_result`, `build_query_string`, both unit-tested in + `test/accela_client_test.liquid`). Calling `schedule_retry`/ + `perform_retry_attempt`/`send` directly from a test would trigger real + background-job scheduling and (for `send`) a real Accela HTTP call, + which this module's test suite deliberately avoids elsewhere (see + "Running the test suite" above) - the arithmetic itself is simple enough + to reason about by inspection, but hasn't been exercised beyond that and + the manual live-instance smoke test already called for below. A + structural CI check that every query/command file forwards `with_retries` + (guarding against a future new endpoint silently omitting it) was also + considered and rejected as a *test* specifically - `pos-module-tests` + runs as Liquid inside platformOS, which has no filesystem access to walk + this module's own file tree at runtime; that check would need to be a + separate build-time/CI script, not a `*_test.liquid` file. +- **`with_retries` has no idempotency awareness**: the same boolean is + exposed identically on read-only queries/searches (safe to retry blindly) + and mutating commands like `records/create` (a retried POST after a + timeout could double-create a record if the original request actually + reached Accela). This module doesn't currently distinguish the two - + decide per call site whether retrying is actually safe for that specific + write before enabling `with_retries` on a command. +- **`{% background %}`'s native `max_attempts` isn't used for retry + backoff**: platformOS's background/consumer system has its own built-in + automatic-retry-with-increasing-delay behavior (see pos-module-core's + docs on consumer `max_attempts`), which could in principle replace this + module's own hand-rolled `schedule_retry.liquid`/`perform_retry_attempt.liquid` + recursion. Kept the hand-rolled version instead because (a) the native + backoff schedule isn't documented as configurable via a constant, which + the user's ask explicitly required, and (b) it's unconfirmed whether the + native mechanism triggers on a background block completing with an + application-level failure (this module's `send.liquid` returns + `{success: false}` rather than raising an error) or only on an actual + unhandled exception - adopting it without confirming that would trade + one unverified assumption for another instead of removing one. +- **Access token lifetime**: Accela shortened access tokens to 15 minutes + (May 2024). `get_valid_token.liquid` refreshes 60 seconds early; adjust if + Accela's actual sandbox behavior differs. +- **`{% background %}` semantics for retries** (`lib/accela_client/schedule_retry.liquid`, + `perform_retry_attempt.liquid`, `send.liquid`): all three schedule work + via the direct-invocation form (`background result_var = 'modules/.../some_function', + data: some_hash, priority: ..., max_attempts: ...`, e.g. + `schedule_retry.liquid`'s `background attempt_job = 'modules/accela_construct/accela_client/perform_retry_attempt', + data: retry_data, priority: 'low', delay: delay_minutes, max_attempts: 1`), + rather than the block form (`background priority: ... \n ... \n endbackground`). + This assumes `data:` reaches the invoked function as its own `data` + parameter the same way a normal `{% function %}` call would, and that a + background job is itself allowed to schedule another background job + this way (needed for retry attempt 2+, since `perform_retry_attempt.liquid` + already runs inside one - and, now, for every retry attempt's log write + too, since `send.liquid` backgrounds its own logging call whenever + it isn't the one triggering the next retry, which is always true when + `send.liquid` is invoked from inside `perform_retry_attempt.liquid`). + None of this was exercised against a live instance for this module - if + nesting isn't supported, only the first retry will ever fire (and + retry-attempt log rows may simply never get written); if `data:` isn't + delivered the way assumed, every retry attempt will fail immediately with + a Liquid error instead of re-attempting the Accela call. Smoke test by + calling any command with `with_retries: true` against an endpoint you + know will fail (e.g. a bad path) and checking for the + `accela_retry_scheduled` → `accela_retry_succeeded`/`accela_retry_exhausted` + log sequence, plus checking `accela_request`/`accela_request_response` for + the corresponding rows. +- **API Call Notification template naming for pos-module-core's own + templates**: this module deliberately does NOT use core's generic + `modules/core/api_calls/generic`/`generic_x_form_encoded` *templates* + (as opposed to its `api_calls/send` *graphql mutation*, which it does + use). Those two templates have no `name:` field in their frontmatter, + and the one confirmed usage example found in core's own source passes + `template: 'modules/core/generic'` — a path-style identifier that drops + the `api_calls/` segment present in the file's actual path + (`modules/core/public/api_calls/generic.liquid`). Since every one of + *our own* templates (`api_calls/accela_*.liquid`) instead declares an + explicit `name:` and is referenced by that literal name, and the exact + rule platformOS uses to resolve an unnamed template to a `template: {name: X}` + lookup isn't confirmed, this module keeps its own 3 templates + (`accela_generic`, `accela_post_multipart`, `accela_token_request`) + rather than gambling on an unconfirmed identifier. If you confirm the correct + identifier on your instance, `commands/records/documents/upload`'s and + `get_valid_token.liquid`'s hand-built bodies could shrink further by + switching to core's generic templates. +- **`lib/legacy/to_legacy_record.liquid`** was built by diffing exactly one + before/after pair of real responses, not from any documented mapping - + every field it derives (`recordId`'s `downcase`, `availableInspGroup`'s + `upcase`, the `addressArr[].address` format string, `tpia`'s "find the + non-Removed TPIA condition" rule) held consistently across that one + record's ~14 conditions and 1 address, but hasn't been checked against a + second record. `userID`, `recInsps`, `messages`, `wallCheckRequired`, and + `wallCheckComplete` have no v4 field behind them at all in that sample + (every condition carried the same literal `userID` regardless of what + triggered it, and the other four were simply absent) - they're taken + as-is from this function's params rather than guessed at. Verify against + a few more real records, especially ones with a non-"TPIA" condition + name, before trusting this for anything beyond the one record shape it + was built from. + +## Running the test suite + +Tests use [pos-module-tests](https://github.com/Platform-OS/pos-modules/tree/master/pos-module-tests) +(the `tests` platformOS module, `"tests": "^1.3.4"` in `pos-module.json`) — +install/deploy it alongside this module to run them. Test files live under +`public/lib/test/**/*_test.liquid` (15 files, ~330 assertions total): + +- `test/accela_client_test.liquid` — unit tests for the pure helpers + (`error_result`, `build_query_string`). +- `test/commands/*_test.liquid` (6 files) — for every command, calls + `build.liquid`/`check.liquid` **directly** (deterministic, no network: + asserts `check.liquid` rejects missing required fields and accepts valid + ones via `valid_object`/`invalid_object`, and asserts `build.liquid` + produces the exact expected `path`/`payload`), plus calls the full + orchestrator **only** with a required param missing, asserting it + returns `{success: false, error: "accela_validation_failed"}` — that + path is guaranteed to short-circuit before any network I/O. No test + ever calls an orchestrator with complete/valid params, since that would + attempt a real HTTP request to Accela. +- `test/queries/*_test.liquid` (9 files) — **contract/shape smoke tests + only**. Queries now have the same build/check split as commands (see + "Queries vs. commands" below), but these tests still call the full + orchestrator with plausible, valid dummy params for every required + field rather than exercising `build.liquid`/`check.liquid` directly the + way `test/commands/*_test.liquid` does - so every call here passes + validation and always attempts the real `send` → `get_valid_token` → + Accela HTTP chain. They assert `not_true` on `result.success` + + `presence` on `result.error` - i.e. they verify the call completes and + returns the documented envelope shape, **not** that the path/query-string + built was correct, or that check.liquid actually rejects missing + required params (unlike the command tests, which test that rejection + path directly - queries' check.liquid layer is exercised structurally + by every real call but has no dedicated unit test yet). This only + holds when no live Accela credentials are configured, which is the + expected state for automated test runs; with real credentials + configured in a staging environment, some of these assertions would + need to expect success instead. `test/queries/accela_oauth_token_test.liquid`, + `test/queries/accela_request_test.liquid`, and + `test/queries/accela_request_response_test.liquid` are the three + exceptions — they only read their own local table (no outbound HTTP + call), so they're asserted concretely; the latter two filter by a + path/`request_id` that can't exist rather than asserting the table is + empty, since real usage writes to both continuously (see + "Request/response logging" below). + +Run via browser at `/_tests` (staging/development only) or in CI with +`pos-cli test run `. + +## File map + +``` +modules/accela_construct/ +├── pos-module.json +├── template-values.json +├── README.md +└── public/ + ├── schema/{accela_oauth_token,accela_request,accela_request_response}.yml + │ (tables created/synced from these directly on deploy - no migration needed) + ├── migrations/ + │ └── ..._set_accela_constants.liquid (seeds Constants data - the one thing migrations are actually for here) + ├── graphql/ + │ ├── accela_oauth_token/{create,update,find_latest}.graphql + │ ├── accela_request/{create,get,list}.graphql + │ ├── accela_request_response/{create,list}.graphql + │ ├── reference/get_table.graphql (generic any-table lookup by id) + │ └── constants/set.graphql + ├── api_calls/ + │ ├── accela_token_request.liquid + │ ├── accela_generic.liquid + │ └── accela_post_multipart.liquid + ├── views/pages/accela_construct/test.liquid + └── lib/ + ├── accela_client/ + │ ├── get_valid_token.liquid + │ ├── send.liquid + │ ├── schedule_retry.liquid + │ ├── perform_retry_attempt.liquid + │ ├── log_request.liquid + │ ├── resolve_reference_table.liquid + │ ├── error_result.liquid + │ ├── build_query_string.liquid + │ └── post_search.liquid + ├── queries/ (read-only; see Supported endpoints; + │ │ each action = orchestrator + build.liquid + check.liquid, + │ │ same as commands - except the 4 below, which are plain + │ │ single-file GraphQL reads with no Accela call to validate) + │ ├── accela_oauth_token/find.liquid + │ ├── accela_request/{get,list}.liquid + │ ├── accela_request_response/list.liquid + │ ├── records/**/*.liquid (81 files: 27 actions x 3, across top-level + + │ │ parcels/owners/addresses/conditions/workflow_tasks/payments/ + │ │ documents/inspections/inspection_types - the last three moved + │ │ here from queries/documents/, queries/inspections/ since they + │ │ wrap /records/{recordId}/... paths, not /documents/ or + │ │ /inspections/. `inspection_types` (Accela's "Get Inspection + │ │ Types" endpoint, GET /records/{recordIds}/inspectionTypes) is + │ │ its own sub-resource, not part of `inspections` - it lists + │ │ the inspection *types* configured for a record, not actual + │ │ inspection instances) + │ ├── inspections/**/*.liquid (27 files: 9 actions x 3 - only endpoints actually + │ │ under /inspections/..., see above) + │ ├── documents/*.liquid (3 files: 1 action x 3 - only `download`, the one + │ │ documents endpoint not scoped under /records/{recordId}/) + │ └── searches/*.liquid (33 files: 11 actions x 3 - build.liquid is a no-op for 10 of + │ these, since post_search.liquid does the real work) + ├── commands/ (mutating; see Supported endpoints) + │ ├── records/**/*.liquid (each action = orchestrator + build.liquid + check.liquid; + │ │ includes documents/{upload,delete}, moved here for the + │ │ same reason as the queries above) + │ └── inspections/**/*.liquid + ├── legacy/ + │ └── to_legacy_record.liquid (pure data reshape, no Accela call - see below) + ├── events/ + │ └── accela_construct_request_succeeded.liquid (validates the event send.liquid broadcasts - see below) + └── test/ (pos-module-tests suite; see above) + ├── accela_client_test.liquid + ├── queries/*_test.liquid (9 files) + └── commands/*_test.liquid (6 files) +``` + +318 files total. Every `.liquid` query or command orchestrator has +an `/build.liquid` and `/check.liquid` sibling (never an +`execute.liquid` — see "Queries vs. commands" below). Run +`find public/lib -type f | sort` for the literal list. + +## Queries vs. commands + +Following the [platformOS module conventions](https://documentation.platformos.com/developer-guide/modules/platformos-modules.md) +used by the [core module](https://github.com/Platform-OS/pos-modules/blob/master/pos-module-core/README.md), +resource wrappers are split by whether they read or write: + +- **`lib/queries//`** — read-only Accela calls, one per + GET endpoint. See [Supported endpoints](#supported-endpoints) for the + full list (records, records/{parcels,owners,addresses,conditions, + workflow_tasks,payments,documents,inspections,inspection_types}, + inspections, inspections/{checklists,conditions}, documents, searches - + `documents` and `inspections` appear twice because most of their + endpoints are record-scoped [`/records/{recordId}/...`, live under + `records/`] while a few (`documents/download`, and every top-level, + unscoped `inspections/*` endpoint like `/inspections`, `/inspections/{ids}`) + aren't; `records/inspection_types` is its own sub-resource, not part of + `records/inspections` - it lists the inspection *types* configured for + a record, not actual inspection instances). +- **`lib/commands//`** — calls that create or mutate + something in Accela, one per POST/PUT/DELETE endpoint. See + [Supported endpoints](#supported-endpoints) for the full list. +- **`lib/accela_client/`** — shared transport plumbing used by every query + and command above; not part of the public per-resource API: + - `send`/`get_valid_token` — token retrieval/refresh and the generic + authenticated request (via pos-module-core's `api_calls/send`). + - `error_result` — builds the `{ success: false, status: null, ... }` + failure envelope; used by `send.liquid`'s own failure branches and by + every query/command's validation-failure branch, so that shape is + defined once instead of retyped at each call site. Also logs the + error via `{% log %}` (type `"accela_error"`), tagged with the + caller's own module path - every query/command orchestrator passes + its own path (verbatim from its own doc comment header) as `caller` + into both its own `error_result` call and its `send`/`post_search` + call (which forwards it back to `error_result` if the live Accela + call itself fails), so a failure in the logs is always labeled with + which endpoint it came from, not just the bare error string. + - `build_query_string` — joins a hash of optional query params into a + `key=val&key=val` string (skipping blanks, url-encoding values); used + by every query that takes optional filter params instead of each one + hand-rolling `&`-joining differently. (No pos-module-core equivalent + exists for this one — it's module-specific.) + - `post_search` — the shared implementation behind every + `lib/queries/searches/.liquid` (all of them except `global`, + which is a plain GET): builds the `/search/?` path and + JSON criteria payload once, since all 10 were otherwise byte-for-byte + identical apart from the resource name. Each `searches/.liquid` + file still exists on its own — same one-file-per-endpoint convention + as everywhere else — it just delegates to this helper for its body. + +Both queries and commands follow the +[pos-module-core build/check/execute workflow](https://github.com/Platform-OS/pos-modules/blob/master/pos-module-core/README.md), +adapted to skip a separate execute file: every +`lib/{queries,commands}//.liquid` is a thin orchestrator +around two sibling files in `//`, and executes the +request itself: + +1. **`build.liquid`** — normalizes the params into an `object` hash and + prepares the Accela request: the request path (relative to + `ACCELA_CONSTRUCT_BASE_URL` - see "How it's built" above) and, for + commands, the JSON-serialized request body (`payload`, or `file_info` + for the multipart upload). +2. **`check.liquid`** — validates that required params are present using + pos-module-core's validation contract convention: builds a local + `c = { "errors": {}, "valid": true }`, calls + `modules/core/validations/presence` once per required field, then + copies `c.valid`/`c.errors` onto `object.valid`/`object.errors`. For + queries, "required" means a param the endpoint is structurally + meaningless without (an id/type used to build the path or an + Accela-required filter), never an optional filter/pagination param - + many queries (e.g. `records/list`, `records/search`, every + `searches/*`) have nothing to validate at all, so their `check.liquid` + just sets `valid: true` unconditionally. Commands validate required + body fields the same way. +3. **execute step, inlined in the orchestrator** — if `object.valid`, calls + `lib/accela_client/send` (or, for `searches/*`, `post_search`) with the + fields `build.liquid` prepared and returns the normalized response. + `searches/*` queries delegate their actual path-building to the shared + `post_search.liquid` helper (see below), so their own `build.liquid` is + a no-op passthrough - kept only for structural consistency, not because + there's anything to build there. + +The orchestrator returns that response on success, or a +`{ success: false, error: "accela_validation_failed", errors: {...} }` +result (without ever calling Accela) when `check.liquid` fails. + +## Events + +Following [pos-module-core's events convention](https://github.com/Platform-OS/pos-modules/blob/master/pos-module-core/README.md#events), +`lib/accela_client/send.liquid` broadcasts a `modules/core/commands/events/publish` +event of type `accela_construct_request_succeeded` after every successful +Accela attempt (this one or a retry) - never on failure. Its payload +identifies which request it was via `caller` (the query/command's own +module path), `method`, `path`, `reference` (the `{ "id", "table" }` this +call was made on behalf of, if any), `attempt_number`, and the ids of the +two log rows `log_request.liquid` writes for this attempt: `request_id` +(the `accela_request` row - one per logical request, shared across +retries) and `response_id` (the `accela_request_response` row - one per +attempt). Getting both ids into the event is the reason a *successful* +attempt's log write is synchronous rather than backgrounded (a non-retried +*failure*'s write still runs in the background, since nothing needs its +ids and no event fires) - see send.liquid's doc comment and +`lib/events/accela_construct_request_succeeded.liquid` (the event's +validated shape) for the full explanation. + +To react to it, add your own consumer at +`lib/consumers/accela_construct_request_succeeded/.liquid` +(see pos-module-core's docs linked above) - this module doesn't ship one +itself, since what to do on success is entirely app-specific. + +## Legacy response shape (backwards compatibility) + +`lib/legacy/to_legacy_record.liquid` reshapes a v4 record (`queries/records/get` +with `expand: 'addresses,conditions,owners'`, then `.body.result.first`) into +the flatter shape an older, pre-v4 integration's consumers still expect - +useful when rolling this module out in front of code you don't want to +rewrite in lockstep. It's a pure data reshape (no Accela call of its own), +so it composes with any query that returns a v4 record, not just `get`: + +```liquid +{% liquid + function result = 'modules/accela_construct/queries/records/get', ids: 'B120434', expand: 'addresses,conditions,owners' + function legacy = 'modules/accela_construct/legacy/to_legacy_record', record: result.body.result.first, user_id: 'NEARME' +%} +``` + +Most fields are a straight rename (`appStatus` <- `status.text`, `workDesc` +<- `description`, ...); see the doc comment at the top of +`to_legacy_record.liquid` for the full field-by-field mapping, including how +`addressArr[].address` and `capConditions[]` are built up from the v4 +`addresses[]`/`conditions[]` arrays. Four legacy fields have no v4 +equivalent at all and are only as good as what you pass in - see Known Gaps +below: `recInsps`, `messages` (both default `[]`), and +`wallCheckRequired`/`wallCheckComplete` (both default `false`). diff --git a/pos-module-accela_construct/changelog-template.hbs b/pos-module-accela_construct/changelog-template.hbs new file mode 100644 index 00000000..329c55a4 --- /dev/null +++ b/pos-module-accela_construct/changelog-template.hbs @@ -0,0 +1,41 @@ +# Changelog + +All notable changes to this project will be documented in this file. Dates are displayed in UTC. + +{{#each releases}} + {{#if href}} + ## [{{title}}]({{href}}) + {{else}} + ## {{title}} + {{/if}} + + {{#if niceDate}} + > {{niceDate}} + {{/if}} + + {{#if summary}} + {{summary}} + {{/if}} + + ### Breaking changes + {{#each merges}} + {{#if commit.breaking}}- {{message}}{{#if href}} [`#{{id}}`]({{href}}){{/if}}{{/if}} + {{/each}} + {{#each fixes}} + {{#if commit.breaking}}- {{commit.subject}}{{#each fixes}}{{#if href}} [`#{{id}}`]({{href}}){{/if}}{{/each}}{{/if}} + {{/each}} + {{#each commits}} + {{#if breaking}}- {{subject}}{{#if href}} [`{{shorthash}}`]({{href}}){{/if}}{{/if}} + {{/each}} + + ### Merged pull requests + {{#each merges}} + - {{message}}{{#if href}} [`#{{id}}`]({{href}}){{/if}} + {{/each}} + + ### Fixes + {{#each fixes}} + - {{commit.subject}}{{#each fixes}}{{#if href}} [`#{{id}}`]({{href}}){{/if}}{{/each}} + {{/each}} + +{{/each}} diff --git a/pos-module-accela_construct/modules/accela_construct/.mcp.json b/pos-module-accela_construct/modules/accela_construct/.mcp.json new file mode 100644 index 00000000..04082b9f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/.mcp.json @@ -0,0 +1,10 @@ +{ + "mcpServers": { + "platformos": { + "command": "pos-cli-mcp" + }, + "platformos-supervisor": { + "command": "pos-cli-supervisor" + } + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/CLAUDE.md b/pos-module-accela_construct/modules/accela_construct/CLAUDE.md new file mode 100644 index 00000000..dbfa92e4 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/CLAUDE.md @@ -0,0 +1,30 @@ + + + + + + +## BACKLOG WORKFLOW INSTRUCTIONS + +This project uses Backlog.md MCP for all task and project management activities. + +**CRITICAL GUIDANCE** + +- If your client supports MCP resources, read `backlog://workflow/overview` to understand when and how to use Backlog for this project. +- If your client only supports tools or the above request fails, call `backlog.get_backlog_instructions()` to load the tool-oriented overview. Use the `instruction` selector when you need `task-creation`, `task-execution`, or `task-finalization`. + +- **First time working here?** Read the overview resource IMMEDIATELY to learn the workflow +- **Already familiar?** You should have the overview cached ("## Backlog.md Overview (MCP)") +- **When to read it**: BEFORE creating tasks, or when you're unsure whether to track work + +These guides cover: +- Decision framework for when to create tasks +- Search-first workflow to avoid duplicates +- Links to detailed guides for task creation, execution, and finalization +- MCP tools reference + +You MUST read the overview resource to understand the complete workflow. The information is NOT summarized here. + + + + diff --git a/pos-module-accela_construct/modules/accela_construct/pos-module.json b/pos-module-accela_construct/modules/accela_construct/pos-module.json new file mode 100644 index 00000000..44f4b1b2 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/pos-module.json @@ -0,0 +1,10 @@ +{ + "name": "Accela Construct API Wrapper", + "machine_name": "accela_construct", + "version": "0.1.0", + "description": "platformOS module that wraps the Accela Construct API (v4) - Records and all its sub-resources (WorkflowTasks, Payments, Parcels, Owners, Inspections, Documents, Conditions, Addresses), Inspections (including Checklists and Conditions), and Searches - including OAuth2 password-grant token management with automatic refresh.", + "dependencies": { + "core": "^2.0.0", + "tests": "^1.3.4" + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/api_calls/accela_generic.liquid b/pos-module-accela_construct/modules/accela_construct/public/api_calls/accela_generic.liquid new file mode 100644 index 00000000..bec23622 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/api_calls/accela_generic.liquid @@ -0,0 +1,17 @@ +--- +name: accela_generic +delay: '0' +format: https +request_headers: > + { + "Content-Type": "application/json", + "Accept": "application/json", + "x-accela-appid": "{{ data.app_id }}", + "Authorization": "{{ data.access_token }}" + } +request_type: "{{ data.request_type }}" +to: > + {% function accela_base_url = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_BASE_URL' %} + {{ accela_base_url }}{{ data.path }} +--- +{{ data.payload }} diff --git a/pos-module-accela_construct/modules/accela_construct/public/api_calls/accela_post_multipart.liquid b/pos-module-accela_construct/modules/accela_construct/public/api_calls/accela_post_multipart.liquid new file mode 100644 index 00000000..abe8e0b6 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/api_calls/accela_post_multipart.liquid @@ -0,0 +1,18 @@ +--- +name: accela_post_multipart +delay: '0' +format: http +request_headers: > + { + "x-accela-appid": "{{ data.app_id }}", + "Authorization": "{{ data.access_token }}" + } +request_type: POST +to: > + {% function accela_base_url = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_BASE_URL' %} + {{ accela_base_url }}{{ data.path }} +--- +{ + "uploadedFile": {{ data.file_field | json }}, + "fileInfo": {{ data.file_info }} +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/api_calls/accela_token_request.liquid b/pos-module-accela_construct/modules/accela_construct/public/api_calls/accela_token_request.liquid new file mode 100644 index 00000000..4b6203e6 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/api_calls/accela_token_request.liquid @@ -0,0 +1,13 @@ +--- +name: accela_token_request +delay: '0' +format: http +request_headers: > + { + "Content-Type": "application/x-www-form-urlencoded", + "Accept": "application/json" + } +request_type: POST +to: "{{ data.auth_url }}" +--- +{{ data.form_body }} diff --git a/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_oauth_token/create.graphql b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_oauth_token/create.graphql new file mode 100644 index 00000000..0eaffc27 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_oauth_token/create.graphql @@ -0,0 +1,28 @@ +mutation accela_oauth_token_create( + $access_token: String! + $refresh_token: String + $expires_at: String! + $refresh_token_expires_at: String +) { + record_create( + record: { + table: "modules/accela_construct/accela_oauth_token" + properties: [ + { name: "access_token", value: $access_token } + { name: "refresh_token", value: $refresh_token } + { name: "expires_at", value: $expires_at } + { name: "refresh_token_expires_at", value: $refresh_token_expires_at } + ] + } + ) { + id + created_at + updated_at + table + + access_token: property(name: "access_token") + refresh_token: property(name: "refresh_token") + expires_at: property(name: "expires_at") + refresh_token_expires_at: property(name: "refresh_token_expires_at") + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_oauth_token/find_latest.graphql b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_oauth_token/find_latest.graphql new file mode 100644 index 00000000..17633cc9 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_oauth_token/find_latest.graphql @@ -0,0 +1,19 @@ +query accela_oauth_token_find_latest { + records( + filter: { table: { value: "modules/accela_construct/accela_oauth_token" } } + sort: { created_at: { order: DESC } } + per_page: 1 + ) { + results { + id + created_at + updated_at + table + + access_token: property(name: "access_token") + refresh_token: property(name: "refresh_token") + expires_at: property(name: "expires_at") + refresh_token_expires_at: property(name: "refresh_token_expires_at") + } + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_oauth_token/update.graphql b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_oauth_token/update.graphql new file mode 100644 index 00000000..ce959c8f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_oauth_token/update.graphql @@ -0,0 +1,29 @@ +mutation accela_oauth_token_update( + $id: ID! + $access_token: String! + $refresh_token: String + $expires_at: String! + $refresh_token_expires_at: String +) { + record_update( + id: $id + record: { + properties: [ + { name: "access_token", value: $access_token } + { name: "refresh_token", value: $refresh_token } + { name: "expires_at", value: $expires_at } + { name: "refresh_token_expires_at", value: $refresh_token_expires_at } + ] + } + ) { + id + created_at + updated_at + table + + access_token: property(name: "access_token") + refresh_token: property(name: "refresh_token") + expires_at: property(name: "expires_at") + refresh_token_expires_at: property(name: "refresh_token_expires_at") + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request/create.graphql b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request/create.graphql new file mode 100644 index 00000000..83e59224 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request/create.graphql @@ -0,0 +1,31 @@ +mutation accela_request_create( + $method: String! + $path: String! + $request_payload: String + $reference_id: String + $reference_schema: String +) { + record_create( + record: { + table: "modules/accela_construct/accela_request" + properties: [ + { name: "method", value: $method } + { name: "path", value: $path } + { name: "request_payload", value: $request_payload } + { name: "reference_id", value: $reference_id } + { name: "reference_schema", value: $reference_schema } + ] + } + ) { + id + created_at + updated_at + table + + method: property(name: "method") + path: property(name: "path") + request_payload: property(name: "request_payload") + reference_id: property(name: "reference_id") + reference_schema: property(name: "reference_schema") + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request/get.graphql b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request/get.graphql new file mode 100644 index 00000000..928596c2 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request/get.graphql @@ -0,0 +1,19 @@ +query accela_request_get($id: ID!) { + records( + per_page: 1 + filter: { id: { value: $id }, table: { value: "modules/accela_construct/accela_request" } } + ) { + results { + id + created_at + updated_at + table + + method: property(name: "method") + path: property(name: "path") + request_payload: property(name: "request_payload") + reference_id: property(name: "reference_id") + reference_schema: property(name: "reference_schema") + } + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request/list.graphql b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request/list.graphql new file mode 100644 index 00000000..889d3a0d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request/list.graphql @@ -0,0 +1,40 @@ +query accela_request_list( + $limit: Int! + $page: Int! + $method: String + $path: String + $reference_id: String + $reference_schema: String +) { + records( + per_page: $limit + page: $page + filter: { + table: { value: "modules/accela_construct/accela_request" } + properties: [ + { name: "method", value: $method } + { name: "path", value: $path } + { name: "reference_id", value: $reference_id } + { name: "reference_schema", value: $reference_schema } + ] + } + sort: [{ created_at: { order: DESC } }] + ) { + total_entries + has_next_page + current_page + + results { + id + created_at + updated_at + table + + method: property(name: "method") + path: property(name: "path") + request_payload: property(name: "request_payload") + reference_id: property(name: "reference_id") + reference_schema: property(name: "reference_schema") + } + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request_response/create.graphql b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request_response/create.graphql new file mode 100644 index 00000000..15b8b498 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request_response/create.graphql @@ -0,0 +1,34 @@ +mutation accela_request_response_create( + $request_id: String! + $attempt_number: Int! + $status: Int + $response_body: String + $success: Boolean! + $error: String +) { + record_create( + record: { + table: "modules/accela_construct/accela_request_response" + properties: [ + { name: "request_id", value: $request_id } + { name: "attempt_number", value_int: $attempt_number } + { name: "status", value_int: $status } + { name: "response_body", value: $response_body } + { name: "success", value_boolean: $success } + { name: "error", value: $error } + ] + } + ) { + id + created_at + updated_at + table + + request_id: property(name: "request_id") + attempt_number: property_int(name: "attempt_number") + status: property_int(name: "status") + response_body: property(name: "response_body") + success: property_boolean(name: "success") + error: property(name: "error") + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request_response/list.graphql b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request_response/list.graphql new file mode 100644 index 00000000..78c8fd69 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/graphql/accela_request_response/list.graphql @@ -0,0 +1,37 @@ +query accela_request_response_list( + $limit: Int! + $page: Int! + $request_id: String + $success: Boolean +) { + records( + per_page: $limit + page: $page + filter: { + table: { value: "modules/accela_construct/accela_request_response" } + properties: [ + { name: "request_id", value: $request_id } + { name: "success", value_boolean: $success } + ] + } + sort: [{ created_at: { order: DESC } }] + ) { + total_entries + has_next_page + current_page + + results { + id + created_at + updated_at + table + + request_id: property(name: "request_id") + attempt_number: property_int(name: "attempt_number") + status: property_int(name: "status") + response_body: property(name: "response_body") + success: property_boolean(name: "success") + error: property(name: "error") + } + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/graphql/constants/set.graphql b/pos-module-accela_construct/modules/accela_construct/public/graphql/constants/set.graphql new file mode 100644 index 00000000..1aa5bce3 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/graphql/constants/set.graphql @@ -0,0 +1,6 @@ +mutation accela_constant_set($name: String!, $value: String!) { + constant_set(name: $name, value: $value) { + name + value + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/graphql/reference/get_table.graphql b/pos-module-accela_construct/modules/accela_construct/public/graphql/reference/get_table.graphql new file mode 100644 index 00000000..1244f76e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/graphql/reference/get_table.graphql @@ -0,0 +1,7 @@ +query reference_get_table($id: ID!) { + records(per_page: 1, filter: { id: { value: $id } }) { + results { + table + } + } +} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/build_query_string.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/build_query_string.liquid new file mode 100644 index 00000000..186ce562 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/build_query_string.liquid @@ -0,0 +1,32 @@ +{% comment %} + modules/accela_construct/accela_client/build_query_string + + Joins a hash of query params into a URL query string, url-encoding each + value and skipping blank ones. Shared by every query wrapper that takes + optional filter params, instead of each one hand-rolling `&`-joining. + + Params: + params - hash of param name => value (blank values are skipped) + + Returns: "key1=val1&key2=val2", or '' if every value was blank. + + Usage: + {% function qs = 'modules/accela_construct/accela_client/build_query_string', params: { "offset": 0, "limit": 25, "expand": expand } %} +{% endcomment %} + +{% liquid + assign qs = '' + for pair in params + assign value = pair[1] + if value != blank + assign encoded_value = value | url_encode + assign part = pair[0] | append: '=' | append: encoded_value + if qs == blank + assign qs = part + else + assign qs = qs | append: '&' | append: part + endif + endif + endfor + return qs +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/error_result.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/error_result.liquid new file mode 100644 index 00000000..f17e51c9 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/error_result.liquid @@ -0,0 +1,42 @@ +{% comment %} + modules/accela_construct/accela_client/error_result + + Builds the standard failure envelope every query/command returns when it + can't complete a request - either before calling Accela (a local + validation failure) or because the HTTP call itself failed. Single + source of truth for this shape so it can't drift between call sites. + Also logs the error via `{% log %}`, tagged with the caller's own + module path, so a failure shows up in logs already labeled with which + query/command it came from, instead of just the bare error string. + + Params: + error - String error message (required) + errors - optional hash of per-field validation errors + caller - optional. The calling function's own module path, e.g. + `modules/accela_construct/queries/records/inspection_types/list` + - every query/command orchestrator passes its own path here + (verbatim from its own doc comment header), and send.liquid + accepts and forwards the same param so a live Accela failure + (not just a local validation failure) is traced back to its + caller too. + + Returns: { "success": false, "status": null, "body": null, "raw": null, "error": error [, "errors": errors] } + + Usage: + {% function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/get' %} +{% endcomment %} + +{% liquid + assign result = { "success": false, "status": null, "body": null, "raw": null, "error": error } + if errors != blank + assign result.errors = errors + endif + + if caller != blank + log errors, type: "ACCELA CONSTRUCT MODULE ERROR: {{ caller }}" + else + log errors, type: "ACCELA CONSTRUCT MODULE ERROR: " + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/get_valid_token.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/get_valid_token.liquid new file mode 100644 index 00000000..45153b65 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/get_valid_token.liquid @@ -0,0 +1,74 @@ +{% comment %} + modules/accela_construct/accela_client/get_valid_token + + Returns a valid Accela access token, transparently refreshing (or + obtaining a brand new one via the password grant) when the cached token + has expired. Persists the token in the accela_oauth_token table so it is + reused across requests instead of re-authenticating every call. + + Usage: + {% function access_token = 'modules/accela_construct/accela_client/get_valid_token' %} + + Returns: String access token, or '' (blank) if authentication failed - + callers MUST check for blank and surface an auth error rather than + sending a request with an empty Authorization header. + + NOTE ON TOKEN LIFETIME: per Accela's docs (effective 2024-05-31), access + tokens expire in 15 minutes and refresh tokens in 8 hours. We refresh + 60 seconds early to absorb clock drift/network latency. +{% endcomment %} + +{% liquid + function token_record = 'modules/accela_construct/queries/accela_oauth_token/find' + assign now_ts = 'now' | date: '%s' + assign access_token = '' + + if token_record and token_record.access_token != blank and token_record.expires_at != blank and now_ts < token_record.expires_at + assign access_token = token_record.access_token + else + function accela_client_id = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_CLIENT_ID' + function accela_client_secret = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_CLIENT_SECRET' + + if token_record and token_record.refresh_token != blank and token_record.refresh_token_expires_at != blank and now_ts < token_record.refresh_token_expires_at + assign token_payload = { "grant_type": "refresh_token", "client_id": accela_client_id, "client_secret": accela_client_secret, "refresh_token": token_record.refresh_token } + else + function accela_username = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_USERNAME' + function accela_password = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_PASSWORD' + function accela_scope = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_SCOPE' + function accela_agency = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_AGENCY' + function accela_environment = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_ENVIRONMENT' + assign token_payload = { "grant_type": "password", "client_id": accela_client_id, "client_secret": accela_client_secret, "username": accela_username, "password": accela_password, "scope": accela_scope, "agency_name": accela_agency, "environment": accela_environment } + endif + + function form_body = 'modules/core/helpers/hash_to_x_form_encoded', payload: token_payload + function accela_auth_url = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_AUTH_URL' + assign token_data = { "auth_url": accela_auth_url, "form_body": form_body } + graphql send_result = 'modules/core/api_calls/send', template: 'modules/accela_construct/accela_token_request', data: token_data + + if send_result.api_call.errors.size == 0 and send_result.api_call.response.status == 200 + assign body = send_result.api_call.response.body | parse_json + + if body.access_token != blank + assign expires_in = body.expires_in | plus: 0 + if expires_in == 0 + assign expires_in = 900 + endif + assign expires_at = now_ts | plus: expires_in | minus: 60 + assign refresh_expires_at = now_ts | plus: 28800 | minus: 60 + + if token_record + graphql update_result = 'modules/accela_construct/accela_oauth_token/update', id: token_record.id, access_token: body.access_token, refresh_token: body.refresh_token, expires_at: expires_at, refresh_token_expires_at: refresh_expires_at + else + graphql create_result = 'modules/accela_construct/accela_oauth_token/create', access_token: body.access_token, refresh_token: body.refresh_token, expires_at: expires_at, refresh_token_expires_at: refresh_expires_at + endif + + assign access_token = body.access_token + endif + else + log "Payload: {{ token_payload }}. Result: {{ send_result }}", type: "ACCELA GET TOKEN ERROR: accela_client/get_valid_token" + endif + + endif + + return access_token +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/log_request.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/log_request.liquid new file mode 100644 index 00000000..112c56d3 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/log_request.liquid @@ -0,0 +1,57 @@ +{% comment %} + modules/accela_construct/accela_client/log_request + + Writes this attempt's outcome to the accela_request/accela_request_response + tables - one accela_request row per logical request (created once, on + the first attempt), and one accela_request_response row per attempt, + including every retry, each pointing back at its accela_request via + `request_id`. Shared by send.liquid's two logging paths - called + directly (synchronously) when a retry is about to be scheduled and the + accela_request id is needed as the chain's request_id, and via a direct + `{% background %}` invocation otherwise. + + Params: + data - Hash with method, path, request_payload, request_id, + attempt_number, status, response_body, success, error, + reference (the exact shape send.liquid builds as `log_data`). + When `data.request_id` is blank, this is attempt 1 of a fresh + logical request - creates the accela_request row (using + `data.reference.id`/`data.reference.table` if given - if + `id` is present but `table` isn't, looks `table` up via + accela_client/resolve_reference_table rather than requiring + the caller to supply it), using its own new id as the + response row's request_id. When `data.request_id` is already + set (attempts 2+, passed through from a prior attempt), reuses + it directly - no accela_request row is touched on retries at + all, only a new accela_request_response row is created (and + `data.reference` is ignored then, since it was already + resolved and stored at creation and doesn't change across + retries). + + Returns { "request_id": , + "response_id": }. If either write fails, the corresponding id comes + back blank (see README's Known Gaps on request_id correlation) - this + never raises, matching send.liquid's "a failed log write never blocks + the underlying Accela request" contract. +{% endcomment %} + +{% liquid + assign request_id = data.request_id + if request_id == blank + assign reference_id = data.reference.id + assign reference_table = data.reference.table + if reference_table == blank and reference_id != blank + function reference_table = 'modules/accela_construct/accela_client/resolve_reference_table', id: reference_id + endif + + graphql request_result = 'modules/accela_construct/accela_request/create', method: data.method, path: data.path, request_payload: data.request_payload, reference_id: reference_id, reference_schema: reference_table + assign request_id = request_result.record_create.id + endif + + graphql response_result = 'modules/accela_construct/accela_request_response/create', request_id: request_id, attempt_number: data.attempt_number, status: data.status, response_body: data.response_body, success: data.success, error: data.error + assign response_id = response_result.record_create.id + + assign log_result = { "request_id": request_id, "response_id": response_id } + return log_result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/perform_retry_attempt.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/perform_retry_attempt.liquid new file mode 100644 index 00000000..4ef66e29 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/perform_retry_attempt.liquid @@ -0,0 +1,46 @@ +{% comment %} + modules/accela_construct/accela_client/perform_retry_attempt + + Runs one retry attempt from inside the background job scheduled by + `schedule_retry.liquid`. Looks up the original method/path/payload from + the accela_request row (`data.request_id`) via `queries/accela_request/get` + rather than having them passed down through the chain, then re-sends + the request via `send.liquid` (never with `with_retries: true` itself - + this file owns the retry loop explicitly, rather than letting + send.liquid re-trigger its own scheduling on top of this one). On + success, logs and stops. On failure, logs and either schedules the next + attempt (if `retry_number < data.max_retries`) or gives up. + + Params: + data - Hash with `request_id`, `attempt_number`- the exact shape `schedule_retry.liquid` + builds and passes as this function's `data` argument via + `{% background %}`. + + Returns the attempt's result hash, or nil if the accela_request row + couldn't be found (see below) - either way, nothing reads the return + value, since this runs detached from whatever request originally + triggered the retry chain. +{% endcomment %} + +{% liquid + assign retry_number = data.attempt_number | minus: 1 + function accela_request = 'modules/accela_construct/queries/accela_request/get', id: data.request_id + + if accela_request == blank + log "Accela retry {{ retry_number }}/{{ data.max_retries }} for accela_request {{ data.request_id }} aborted: accela_request row not found (its creation on attempt 1 likely failed) - giving up rather than resending with a blank method/path", type: "accela_retry_exhausted" + return null + endif + + function result = 'modules/accela_construct/accela_client/send', method: accela_request.method, path: accela_request.path, payload: accela_request.request_payload, attempt_number: data.attempt_number, request_id: data.request_id + + if result.success + log "Accela retry {{ retry_number }}/{{ data.max_retries }} for accela_request {{ data.request_id }} succeeded", type: "accela_retry_succeeded" + elsif retry_number >= data.max_retries + log "Accela retry {{ retry_number }}/{{ data.max_retries }} for accela_request {{ data.request_id }} failed, giving up: {{ result.error }}", type: "accela_retry_exhausted" + else + assign next_attempt_number = data.attempt_number | plus: 1 + function schedule_result = 'modules/accela_construct/accela_client/schedule_retry', attempt_number: next_attempt_number, last_error: result.error, request_id: data.request_id + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/post_search.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/post_search.liquid new file mode 100644 index 00000000..a7a5f8a9 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/post_search.liquid @@ -0,0 +1,42 @@ +{% comment %} + modules/accela_construct/accela_client/post_search + + Shared implementation for every POST /v4/search/ query - they + all take the same criteria hash plus optional pagination/filter params + and differ only in which Accela resource they search. Each + `lib/queries/searches/.liquid` file delegates here instead of + repeating the same body verbatim. + + Params: + resource - URL segment to search, e.g. "addresses", "parcels" (required) + criteria - Hash of search criteria (all fields Accela documents for + these endpoints are individually optional) + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded to + send.liquid - see send.liquid. + caller - optional module path forwarded to send.liquid - see + send.liquid and error_result.liquid. + + Usage: + {% function result = 'modules/accela_construct/accela_client/post_search', resource: 'addresses', criteria: criteria %} +{% endcomment %} + +{% liquid + assign offset = offset | default: 0 + assign limit = limit | default: 25 + + assign qs_params = { "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function qs = 'modules/accela_construct/accela_client/build_query_string', params: qs_params + + assign path = "/search/{{ resource }}?{{ qs }}" + assign payload = criteria | json + + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: path, payload: payload, with_retries: with_retries, reference: reference, caller: caller + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/resolve_reference_table.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/resolve_reference_table.liquid new file mode 100644 index 00000000..6a921e48 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/resolve_reference_table.liquid @@ -0,0 +1,28 @@ +{% comment %} + modules/accela_construct/accela_client/resolve_reference_table + + Looks up a platformOS record's own `table` field by id alone, with no + table filter - `records()` searches across every table in the instance, + not just one, so this works regardless of what table the referenced + record actually lives in. Used by log_request.liquid when a caller + passes `reference: { "id": ... }` without `table` - saves the caller + from having to look it up themselves when they only have an id in hand + (if they already have the fetched record instead, e.g. from their own + GraphQL query that also selected `table`, they can just pass + `reference: that_record` directly and skip this lookup entirely). + + Params: + id - platformOS record id (required) + + Returns the record's `table` string, or nil if no record with that id + exists. + + Usage: + {% function table = 'modules/accela_construct/accela_client/resolve_reference_table', id: some_id %} +{% endcomment %} + +{% liquid + graphql result = 'modules/accela_construct/reference/get_table', id: id + assign record = result.records.results.first + return record.table +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/schedule_retry.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/schedule_retry.liquid new file mode 100644 index 00000000..78981ffd --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/schedule_retry.liquid @@ -0,0 +1,51 @@ +{% comment %} + modules/accela_construct/accela_client/schedule_retry + + Schedules the next retry attempt for a failed Accela request to run + later in the background (via platformOS's `{% background %}` tag), + after an increasing delay: `base_delay_minutes * (attempt_number - 1)` + minutes (linear backoff - 1x, 2x, 3x, ... the base delay per retry). + Called by `send.liquid` after the first, synchronous attempt (attempt_number + 1) fails with `with_retries: true`, and recursively by + `perform_retry_attempt.liquid` after each subsequent failed attempt, + until `attempt_number` exceeds `max_retries`. + + Doesn't carry the request itself (method/path/payload) through the + chain - only `request_id` (the accela_request row's id). Whatever + eventually calls `send` again (`perform_retry_attempt.liquid`) looks + the request up from there via `queries/accela_request/get`, instead of + every hop in the chain passing those fields along by hand. + + `attempt_number` is the same absolute, 1-based counter used throughout + this file, `perform_retry_attempt.liquid`, and `send.liquid`'s own + `attempt_number` param: 1 = the original synchronous call, 2 = the + first retry, 3 = the second, etc. `max_retries` doesn't count that + initial attempt, so retrying is exhausted once `attempt_number` would + exceed `max_retries + 1`. + + Params: + request_id - id of the accela_request row being retried + (required) + attempt_number - the absolute attempt number about to be + scheduled - 2 for the first retry, 3 for the + second, etc. (required) + last_error - the previous attempt's error message, for logging only + + Fire-and-forget: returns nothing meaningful. Logs the scheduling + decision (type "accela_retry_scheduled") since nothing else observes + this - a `{% background %}` job runs in a detached execution context + with no way to report back to whatever request originally failed. +{% endcomment %} + +{% liquid + function accela_max_retries = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_MAX_RETRIES', type: 'integer' + assign retry_number = attempt_number | minus: 1 + function accela_retry_delay_minutes = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_RETRY_DELAY_MINUTES', type: 'integer' + + assign delay_minutes = accela_retry_delay_minutes | default: 1 | times: retry_number + assign retry_data = { "request_id": request_id, "attempt_number": attempt_number, "max_retries": accela_max_retries} + + log "Scheduling Accela retry {{ retry_number }}/{{ accela_max_retries }} for accela_request {{ request_id }} in {{ delay_minutes }}m (previous error: {{ last_error }})", type: "accela_retry_scheduled" + + background attempt_job = 'modules/accela_construct/accela_client/perform_retry_attempt', data: retry_data, priority: 'low', delay: delay_minutes, max_attempts: 1 +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/send.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/send.liquid new file mode 100644 index 00000000..fe102864 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/accela_client/send.liquid @@ -0,0 +1,172 @@ +{% comment %} + modules/accela_construct/accela_client/send + + Generic authenticated Accela API request. Handles token retrieval, + builds the api_call_send `data` hash, and normalizes the result. + GET/POST/PUT/DELETE all share one API Call Notification template + (`api_calls/accela_generic.liquid`), with `method` passed through as + `data.request_type`; only MULTIPART needs its own template + (`accela_post_multipart.liquid`) since its body/headers shape differs. + Fires the request through pos-module-core's generic api_call_send + wrapper (modules/core/api_calls/send) rather than a module-owned + GraphQL mutation. + + Params: + method - "GET" | "POST" | "PUT" | "DELETE" | "MULTIPART" (required) + path - Request path relative to ACCELA_CONSTRUCT_BASE_URL, e.g. "/records" or + "/records/123?expand=parcels" (required). The api_calls/* + templates prepend ACCELA_CONSTRUCT_BASE_URL themselves - callers here + never reference that constant directly. + payload - JSON string request body (POST/PUT only) + file_info - JSON string array, required for MULTIPART (see commands/records/documents/upload/build.liquid) + file_field - raw file content, required for MULTIPART + with_retries - optional boolean, default false/blank. When true and + this attempt fails, schedules up to `ACCELA_CONSTRUCT_MAX_RETRIES` background + retries (see schedule_retry.liquid) with linearly increasing delay + (`ACCELA_CONSTRUCT_RETRY_DELAY_MINUTES * retry number` minutes each). This + attempt's result is still returned synchronously either way - + retries never block the original call, and their eventual outcome + is only observable via the accela_request/accela_request_response + tables (see below), not through this function's return value. Not + supported for MULTIPART requests - file content can't be safely + re-sent from a detached background job. Retries don't carry + `method`/`path`/`payload` through the chain - `schedule_retry.liquid`/ + `perform_retry_attempt.liquid` only pass around this accela_request's + id, looking the request itself back up from the accela_request row + when it's time to resend (see schedule_retry.liquid). + attempt_number - optional integer, default 1. The same absolute, + 1-based counter used throughout the retry chain - 1 for the + original synchronous call, 2 for the first retry, 3 for the + second, etc. Callers normally never set this; it's passed + internally by perform_retry_attempt.liquid. + request_id - optional. Id of the accela_request row this attempt + belongs to, so every attempt of a retry chain (each its own + accela_request_response row) points back at the same logical + request. Leave blank for a fresh call (attempt 1) - a new + accela_request row is created for it; passed internally by + perform_retry_attempt.liquid for attempts 2+, which reuse it rather + than creating another accela_request row. + reference - optional hash `{ "id": ..., "table": ... }`. Polymorphic + association from the accela_request row this call creates back to + whatever platformOS record triggered it. `table` is the record's + actual `table` value (not a caller-invented label) - if you already + have the fetched record in hand (and its own query selected + `table`), just pass it directly, e.g. `reference: application`; + if you only have an id, pass `reference: { "id": application_id }` + and `table` is looked up automatically (one extra GraphQL read - see + accela_client/resolve_reference_table.liquid) since `records()` can + look up any record by id regardless of which table it's in. Only + meaningful on attempt 1 (a fresh call, `request_id` blank); ignored + on retries, since the accela_request row already has it set from + creation. Every query/command wrapper function forwards this the + same way it forwards `with_retries`. + caller - optional. The calling query/command's own module path + (verbatim from its own doc comment header), forwarded to + error_result.liquid if this attempt fails, so a live Accela failure + gets logged with the same "which endpoint was this" context a local + validation failure already gets - see error_result.liquid. + + Every attempt (success or failure) is written via + lib/accela_client/log_request.liquid: one accela_request row per + logical request (created once, on attempt 1) plus one + accela_request_response row per attempt, including every retry - see + the schema files for the exact columns. A failed log write never fails + or blocks the underlying Accela request. The write happens synchronously + and its result IS consumed whenever something downstream needs the id(s) + it produces: when this attempt is about to trigger a retry (the + accela_request id becomes the chain's `request_id`, needed before + scheduling - a blank id from a failed write just means the chain loses + correlation, not that anything here fails - see README's Known Gaps), + and when this attempt succeeded (the event below needs both ids). Only + a non-retried *failure* has nothing waiting on the write, so that's the + one case the log write still runs in the background, unread by anything. + + Every successful attempt (this one or a retry) also broadcasts a + `modules/core/commands/events/publish` event of type + `accela_construct_request_succeeded` - see + lib/events/accela_construct_request_succeeded.liquid for its validated + shape. Its payload identifies which request this was via `caller`, + `method`, `path` (always present), `reference`, `attempt_number`, and + the ids of the log rows this attempt itself just wrote synchronously: + `request_id` (the accela_request row) and `response_id` (this specific + attempt's accela_request_response row) - both blank only in the rare + case the corresponding write itself failed. No event fires on failure - + use the `accela_request`/`accela_request_response` rows (or + `with_retries`) to react to those instead. + + Returns a hash: + { + "success": true|false, + "status": , + "body": , + "raw": , + "error": + } +{% endcomment %} + +{% liquid + function access_token = 'modules/accela_construct/accela_client/get_valid_token' + + assign attempt_number = attempt_number | default: 1 + + if access_token == blank + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_authentication_failed: unable to obtain an access token - check ACCELA_* constants', caller: caller + else + assign template = 'modules/accela_construct/accela_generic' + if method == 'MULTIPART' + assign template = 'modules/accela_construct/accela_post_multipart' + endif + + function accela_app_id = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_APP_ID' + assign request_data = { "app_id": accela_app_id, "access_token": access_token, "path": path, "payload": payload, "file_info": file_info, "file_field": file_field, "request_type": method } + graphql send_result = 'modules/core/api_calls/send', template: template, data: request_data + assign response = send_result.api_call.response + assign call_errors = send_result.api_call.errors + + if call_errors.size > 0 + function result = 'modules/accela_construct/accela_client/error_result', error: call_errors.first.message, caller: caller + else + assign is_success = false + if response.status and response.status >= 200 and response.status < 300 + assign is_success = true + endif + + assign parsed_body = response.body | parse_json + assign error_message = nil + unless is_success + assign error_message = parsed_body.message | default: parsed_body.error_description | default: 'accela_request_failed' + endunless + + assign result = { "success": is_success, "status": response.status, "raw": response.body, "body": parsed_body, "error": error_message } + endif + endif + + assign log_data = { "method": method, "path": path, "request_payload": payload, "attempt_number": attempt_number, "request_id": request_id, "status": result.status, "response_body": result.raw, "success": result.success, "error": result.error, "reference": reference } + + assign will_retry = false + if with_retries and result.success != true and method != 'MULTIPART' + function accela_max_retries = 'modules/core/queries/constants/find', name: 'ACCELA_CONSTRUCT_MAX_RETRIES', type: 'integer' + assign accela_max_retries = accela_max_retries | default: 3 + if accela_max_retries > 0 + assign will_retry = true + endif + endif + + if will_retry + function log_record = 'modules/accela_construct/accela_client/log_request', data: log_data + assign correlation_id = request_id | default: log_record.request_id + + function schedule_result = 'modules/accela_construct/accela_client/schedule_retry', attempt_number: 2, last_error: result.error, request_id: correlation_id + elsif result.success == true + function log_record = 'modules/accela_construct/accela_client/log_request', data: log_data + else + background log_job = 'modules/accela_construct/accela_client/log_request', data: log_data, priority: 'low', max_attempts: 1 + endif + + if result.success == true + assign event_payload = { "caller": caller, "method": method, "path": path, "reference": reference, "request_id": log_record.request_id, "response_id": log_record.response_id, "attempt_number": attempt_number } + function _ = 'modules/core/commands/events/publish', type: 'accela_construct_request_succeeded', object: event_payload, delay: nil, max_attempts: nil + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/assign.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/assign.liquid new file mode 100644 index 00000000..30306548 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/assign.liquid @@ -0,0 +1,37 @@ +{% comment %} + modules/accela_construct/commands/inspections/assign + Wraps: PUT /v4/inspections/{ids}/assign (Accela "Assign Inspections") + + Params: + ids - String, comma-separated inspection id(s) (required) + inspector_id - String, inspector id (required) - Accela documents this + as a required QUERY PARAM, not a body field; this + request has no body at all. + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + assign/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/assign', ids: inspection_id, inspector_id: 'MINSPECTOR' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "ids": ids, "inspector_id": inspector_id } + function object = 'modules/accela_construct/commands/inspections/assign/build', object: object + function object = 'modules/accela_construct/commands/inspections/assign/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/assign' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/assign' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/assign/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/assign/build.liquid new file mode 100644 index 00000000..f8c13a22 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/assign/build.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/inspections/assign/build + + Normalizes input and prepares the request for PUT + /v4/inspections/{ids}/assign: the request path with `ids` and the + required `inspectorId` query param. This request has no body. + + Params: + object - Hash with `ids` and `inspector_id` (see assign.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.ids | url_encode }}/assign?inspectorId={{ object.inspector_id | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/assign/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/assign/check.liquid new file mode 100644 index 00000000..c1dcd517 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/assign/check.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/inspections/assign/check + Validates the object built by build.liquid before it's sent to Accela. + + Accela documents both `ids` (path) and `inspectorId` (query param) as + required for this endpoint - a real exception to the module's usual + "every body field is optional" pattern. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspector_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/cancel.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/cancel.liquid new file mode 100644 index 00000000..a9b53f5d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/cancel.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/inspections/cancel + Wraps: DELETE /v4/inspections/{ids}/cancel (Accela "Cancel Inspections") + + Params: + ids - String, comma-separated inspection id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + NOTE: Accela returns HTTP 200 with a per-id result array + [{ code, id, isSuccess, message }] even for partial failures - always + check result.body.result[].isSuccess, don't rely on the HTTP status alone. + + Follows the pos-module-core build/check/execute command pattern (see + cancel/{build,check}.liquid): build prepares the request URL, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/cancel', ids: inspection_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "ids": ids } + function object = 'modules/accela_construct/commands/inspections/cancel/build', object: object + function object = 'modules/accela_construct/commands/inspections/cancel/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/cancel' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/cancel' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/cancel/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/cancel/build.liquid new file mode 100644 index 00000000..5a77400a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/cancel/build.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/inspections/cancel/build + + Normalizes input and prepares the request for DELETE + /v4/inspections/{ids}/cancel: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL). This request has no body. + + Params: + object - Hash with `ids` (see inspections/cancel.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.ids | url_encode }}/cancel" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/cancel/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/cancel/check.liquid new file mode 100644 index 00000000..3076928a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/cancel/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/inspections/cancel/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/create.liquid new file mode 100644 index 00000000..223cff91 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/create.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/inspections/checklists/create + Wraps: POST /v4/inspections/{inspectionId}/checklists (Accela "Create Inspection Checklist") + + Params: + inspection_id - Inspection id (required) + checklist - Hash of checklist fields (required as this module's + own interface contract - Accela documents every body + field for this endpoint as optional, so this is a + sanity check on our side, not Accela-mandated) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + create/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/checklists/create', inspection_id: inspection_id, checklist: checklist %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "inspection_id": inspection_id, "checklist": checklist } + function object = 'modules/accela_construct/commands/inspections/checklists/create/build', object: object + function object = 'modules/accela_construct/commands/inspections/checklists/create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/checklists/create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/checklists/create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/create/build.liquid new file mode 100644 index 00000000..e929350c --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/create/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/inspections/checklists/create/build + + Normalizes input and prepares the request for POST + /v4/inspections/{inspectionId}/checklists: the request path and the + JSON-serialized checklist body. + + Params: + object - Hash with `inspection_id` and `checklist` (see create.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.inspection_id | url_encode }}/checklists" + assign object.payload = object.checklist | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/create/check.liquid new file mode 100644 index 00000000..3fb52368 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/create/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/inspections/checklists/create/check + Validates the object built by build.liquid before it's sent to Accela. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'checklist' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/delete.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/delete.liquid new file mode 100644 index 00000000..59f9167c --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/delete.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/commands/inspections/checklists/delete + Wraps: DELETE /v4/inspections/{inspectionId}/checklists/{ids} (Accela "Delete Inspection Checklists") + + Params: + inspection_id - Inspection id (required) + ids - String, comma-separated checklist id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + delete/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/checklists/delete', inspection_id: inspection_id, ids: checklist_ids %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "inspection_id": inspection_id, "ids": ids } + function object = 'modules/accela_construct/commands/inspections/checklists/delete/build', object: object + function object = 'modules/accela_construct/commands/inspections/checklists/delete/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/checklists/delete' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/checklists/delete' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/delete/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/delete/build.liquid new file mode 100644 index 00000000..3b61d3c7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/delete/build.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/inspections/checklists/delete/build + + Normalizes input and prepares the request for DELETE + /v4/inspections/{inspectionId}/checklists/{ids}: the request path. This + request has no body. + + Params: + object - Hash with `inspection_id` and `ids` (see delete.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.inspection_id | url_encode }}/checklists/{{ object.ids | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/delete/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/delete/check.liquid new file mode 100644 index 00000000..72912c7d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/checklists/delete/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/inspections/checklists/delete/check + Validates the object built by build.liquid before it's sent to Accela. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/create.liquid new file mode 100644 index 00000000..b4805cfe --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/create.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/inspections/conditions/create + Wraps: POST /v4/inspections/{inspectionId}/conditions (Accela "Create Inspection Standard Conditions") + + Params: + inspection_id - Inspection id (required) + condition - Hash of condition fields (required by this module's own + interface contract - Accela's documented request body + fields for this endpoint are all individually optional; + not independently verified against a live sandbox) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + create/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/conditions/create', inspection_id: inspection_id, condition: condition %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "inspection_id": inspection_id, "condition": condition } + function object = 'modules/accela_construct/commands/inspections/conditions/create/build', object: object + function object = 'modules/accela_construct/commands/inspections/conditions/create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/conditions/create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/conditions/create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/create/build.liquid new file mode 100644 index 00000000..ef5ba4ed --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/create/build.liquid @@ -0,0 +1,20 @@ +{% comment %} + modules/accela_construct/commands/inspections/conditions/create/build + + Normalizes input and prepares the request for POST + /v4/inspections/{inspectionId}/conditions: the request path (relative + to ACCELA_CONSTRUCT_BASE_URL, with the inspection id) and the JSON-serialized + condition body. + + Params: + object - Hash with `inspection_id` and `condition` (see + inspections/conditions/create.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.inspection_id | url_encode }}/conditions" + assign object.payload = object.condition | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/create/check.liquid new file mode 100644 index 00000000..086205d0 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/create/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/inspections/conditions/create/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'condition' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/delete.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/delete.liquid new file mode 100644 index 00000000..199590fb --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/delete.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/commands/inspections/conditions/delete + Wraps: DELETE /v4/inspections/{inspectionId}/conditions/{ids} (Accela "Delete Inspection Conditions") + + Params: + inspection_id - Inspection id (required) + ids - String, comma-separated condition id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + delete/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/conditions/delete', inspection_id: inspection_id, ids: condition_ids %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "inspection_id": inspection_id, "ids": ids } + function object = 'modules/accela_construct/commands/inspections/conditions/delete/build', object: object + function object = 'modules/accela_construct/commands/inspections/conditions/delete/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/conditions/delete' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/conditions/delete' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/delete/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/delete/build.liquid new file mode 100644 index 00000000..0c04411f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/delete/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/inspections/conditions/delete/build + + Normalizes input and prepares the request for DELETE + /v4/inspections/{inspectionId}/conditions/{ids}: the request path + (relative to ACCELA_CONSTRUCT_BASE_URL). This request has no body. + + Params: + object - Hash with `inspection_id` and `ids` (see + inspections/conditions/delete.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.inspection_id | url_encode }}/conditions/{{ object.ids | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/delete/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/delete/check.liquid new file mode 100644 index 00000000..b1740983 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/delete/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/inspections/conditions/delete/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/update.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/update.liquid new file mode 100644 index 00000000..28d660df --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/update.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/inspections/conditions/update + Wraps: PUT /v4/inspections/{inspectionId}/conditions/{id} (Accela "Update Inspection Condition") + + Params: + inspection_id - Inspection id (required) + id - Condition id (required) + condition - Hash of condition fields to update (required by this + module's own interface contract; not independently + verified against a live sandbox) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + update/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/conditions/update', inspection_id: inspection_id, id: condition_id, condition: condition %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "inspection_id": inspection_id, "id": id, "condition": condition } + function object = 'modules/accela_construct/commands/inspections/conditions/update/build', object: object + function object = 'modules/accela_construct/commands/inspections/conditions/update/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/conditions/update' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/conditions/update' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/update/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/update/build.liquid new file mode 100644 index 00000000..60952f0c --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/update/build.liquid @@ -0,0 +1,20 @@ +{% comment %} + modules/accela_construct/commands/inspections/conditions/update/build + + Normalizes input and prepares the request for PUT + /v4/inspections/{inspectionId}/conditions/{id}: the request path + (relative to ACCELA_CONSTRUCT_BASE_URL, with the inspection and condition ids) + and the JSON-serialized condition body. + + Params: + object - Hash with `inspection_id`, `id`, and `condition` (see + inspections/conditions/update.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.inspection_id | url_encode }}/conditions/{{ object.id | url_encode }}" + assign object.payload = object.condition | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/update/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/update/check.liquid new file mode 100644 index 00000000..b13b1e84 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/conditions/update/check.liquid @@ -0,0 +1,16 @@ +{% comment %} + modules/accela_construct/commands/inspections/conditions/update/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'condition' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/delete.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/delete.liquid new file mode 100644 index 00000000..f84760c7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/delete.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/commands/inspections/delete + Wraps: DELETE /v4/inspections/{ids} (Accela "Delete Inspections") + + Params: + ids - String, comma-separated inspection id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + delete/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/delete', ids: inspection_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "ids": ids } + function object = 'modules/accela_construct/commands/inspections/delete/build', object: object + function object = 'modules/accela_construct/commands/inspections/delete/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/delete' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/delete' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/delete/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/delete/build.liquid new file mode 100644 index 00000000..f032343f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/delete/build.liquid @@ -0,0 +1,16 @@ +{% comment %} + modules/accela_construct/commands/inspections/delete/build + + Normalizes input and prepares the request for DELETE + /v4/inspections/{ids}: the request path. This request has no body. + + Params: + object - Hash with `ids` (see delete.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.ids | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/delete/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/delete/check.liquid new file mode 100644 index 00000000..74050499 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/delete/check.liquid @@ -0,0 +1,13 @@ +{% comment %} + modules/accela_construct/commands/inspections/delete/check + Validates the object built by build.liquid before it's sent to Accela. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/create.liquid new file mode 100644 index 00000000..b323fdc8 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/create.liquid @@ -0,0 +1,40 @@ +{% comment %} + modules/accela_construct/commands/inspections/related/create + Wraps: POST /v4/inspections/{id}/related (Accela "Create Related Inspections") + + Params: + id - Inspection id (required) + related_inspection_ids - String, comma-separated inspection id(s) to + link to `id` (required) - Accela documents + body array `relatedInspectionIds[]` as + required for this endpoint, a real exception + to the module's usual "every body field is + optional" pattern. + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + create/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/related/create', id: inspection_id, related_inspection_ids: '123,456' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "id": id, "related_inspection_ids": related_inspection_ids } + function object = 'modules/accela_construct/commands/inspections/related/create/build', object: object + function object = 'modules/accela_construct/commands/inspections/related/create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/related/create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/related/create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/create/build.liquid new file mode 100644 index 00000000..1a0b26d7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/create/build.liquid @@ -0,0 +1,19 @@ +{% comment %} + modules/accela_construct/commands/inspections/related/create/build + + Normalizes input and prepares the request for POST + /v4/inspections/{id}/related: the request path and the JSON-serialized + `relatedInspectionIds` array body. + + Params: + object - Hash with `id` and `related_inspection_ids` (see related/create.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.id | url_encode }}/related" + assign related_inspection_ids_array = object.related_inspection_ids | split: ',' + assign object.payload = { "relatedInspectionIds": related_inspection_ids_array } | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/create/check.liquid new file mode 100644 index 00000000..b8cdd383 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/create/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/inspections/related/create/check + Validates the object built by build.liquid before it's sent to Accela. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'related_inspection_ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/delete.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/delete.liquid new file mode 100644 index 00000000..79738ab7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/delete.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/commands/inspections/related/delete + Wraps: DELETE /v4/inspections/{id}/related/{childIds} (Accela "Delete Related Inspections") + + Params: + id - Inspection id (required) + child_ids - String, comma-separated related inspection id(s) to unlink (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + delete/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/related/delete', id: inspection_id, child_ids: '123,456' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "id": id, "child_ids": child_ids } + function object = 'modules/accela_construct/commands/inspections/related/delete/build', object: object + function object = 'modules/accela_construct/commands/inspections/related/delete/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/related/delete' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/related/delete' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/delete/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/delete/build.liquid new file mode 100644 index 00000000..bc7eb2c6 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/delete/build.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/inspections/related/delete/build + + Normalizes input and prepares the request for DELETE + /v4/inspections/{id}/related/{childIds}: the request path. This request + has no body. + + Params: + object - Hash with `id` and `child_ids` (see related/delete.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.id | url_encode }}/related/{{ object.child_ids | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/delete/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/delete/check.liquid new file mode 100644 index 00000000..f0be6040 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/related/delete/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/inspections/related/delete/check + Validates the object built by build.liquid before it's sent to Accela. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'child_ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/reschedule.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/reschedule.liquid new file mode 100644 index 00000000..fe840791 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/reschedule.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/commands/inspections/reschedule + Wraps: PUT /v4/inspections/{id}/reschedule (Accela "Reschedule Inspection") + + Params: + id - Inspection id (required) + changes - Hash, e.g. { "inspectorId": "BINSPECTOR", "scheduleDate": "2014-12-31" } + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + reschedule/{build,check}.liquid): build prepares the request URL/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/reschedule', id: inspection_id, changes: changes %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "id": id, "changes": changes } + function object = 'modules/accela_construct/commands/inspections/reschedule/build', object: object + function object = 'modules/accela_construct/commands/inspections/reschedule/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/reschedule' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/reschedule' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/reschedule/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/reschedule/build.liquid new file mode 100644 index 00000000..204f0e2e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/reschedule/build.liquid @@ -0,0 +1,19 @@ +{% comment %} + modules/accela_construct/commands/inspections/reschedule/build + + Normalizes input and prepares the request for PUT + /v4/inspections/{id}/reschedule: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the inspection id) and the JSON-serialized + changes body. + + Params: + object - Hash with `id` and `changes` (see inspections/reschedule.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.id | url_encode }}/reschedule" + assign object.payload = object.changes | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/reschedule/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/reschedule/check.liquid new file mode 100644 index 00000000..789e1568 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/reschedule/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/inspections/reschedule/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'changes' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/result.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/result.liquid new file mode 100644 index 00000000..76578c00 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/result.liquid @@ -0,0 +1,36 @@ +{% comment %} + modules/accela_construct/commands/inspections/result + Wraps: PUT /v4/inspections/{id}/result (Accela "Result Inspection") + Agency-app auth only (not available to citizen/CivicID accounts). + + Params: + id - Inspection id (required) + inspection_result - Hash, e.g. { "status": { "value": "Passed", "text": "Passed" }, "resultComment": "All requirements met." } + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + result/{build,check}.liquid): build prepares the request URL/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/result', id: inspection_id, inspection_result: inspection_result %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "id": id, "inspection_result": inspection_result } + function object = 'modules/accela_construct/commands/inspections/result/build', object: object + function object = 'modules/accela_construct/commands/inspections/result/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/result' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/result' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/result/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/result/build.liquid new file mode 100644 index 00000000..bc11950e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/result/build.liquid @@ -0,0 +1,19 @@ +{% comment %} + modules/accela_construct/commands/inspections/result/build + + Normalizes input and prepares the request for PUT + /v4/inspections/{id}/result: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the inspection id) and the JSON-serialized + result body. + + Params: + object - Hash with `id` and `inspection_result` (see inspections/result.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.id | url_encode }}/result" + assign object.payload = object.inspection_result | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/result/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/result/check.liquid new file mode 100644 index 00000000..a0b612fd --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/result/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/inspections/result/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection_result' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/schedule.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/schedule.liquid new file mode 100644 index 00000000..4634d271 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/schedule.liquid @@ -0,0 +1,42 @@ +{% comment %} + modules/accela_construct/commands/inspections/schedule + Wraps: POST /v4/inspections/schedule (Accela "Schedule Inspection") + + Params: + inspection - Hash, e.g. + { "type": { "value": "Initial Investigation", "id": 173 }, + "inspectorId": "MINSPECTOR", + "recordId": { "id": "ISLANDTON-12CAP-00000-0000L" }, + "requestDate": "2014-10-15", "scheduleDate": "2014-12-01" } + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + TIP: call lib/queries/records/inspection_types/list first to get the correct + type.id, and inspections/available_dates (not yet wrapped - add if + needed) to pick a valid scheduleDate. + + Follows the pos-module-core build/check/execute command pattern (see + schedule/{build,check}.liquid): build prepares the request URL/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/schedule', inspection: inspection %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "inspection": inspection } + function object = 'modules/accela_construct/commands/inspections/schedule/build', object: object + function object = 'modules/accela_construct/commands/inspections/schedule/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/schedule' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/schedule' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/schedule/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/schedule/build.liquid new file mode 100644 index 00000000..0255fd33 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/schedule/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/inspections/schedule/build + + Normalizes input and prepares the request for POST + /v4/inspections/schedule: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL) and the JSON-serialized inspection body. + + Params: + object - Hash with `inspection` (see inspections/schedule.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = '/inspections/schedule' + assign object.payload = object.inspection | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/schedule/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/schedule/check.liquid new file mode 100644 index 00000000..52ffe6ee --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/schedule/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/inspections/schedule/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/set_schedule.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/set_schedule.liquid new file mode 100644 index 00000000..fb39f70d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/set_schedule.liquid @@ -0,0 +1,43 @@ +{% comment %} + modules/accela_construct/commands/inspections/set_schedule + Wraps: PUT /v4/inspections/{id}/schedule (Accela "Schedule Pending Inspection") + Schedules a previously-created, not-yet-scheduled inspection - distinct + from lib/commands/inspections/schedule (POST /v4/inspections/schedule), + which creates *and* schedules a new inspection in one call. + + Params: + id - Inspection id (required) + inspection - Hash of fields to set when scheduling, e.g. + { "inspectorId": "MINSPECTOR", "scheduleDate": "2026-08-05" } + - required as this module's own interface contract; Accela + itself documents every body field on the sibling POST + schedule endpoint as optional, so this is a sanity check + on our side, not an Accela-mandated requirement. + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + set_schedule/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/set_schedule', id: inspection_id, inspection: inspection %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "id": id, "inspection": inspection } + function object = 'modules/accela_construct/commands/inspections/set_schedule/build', object: object + function object = 'modules/accela_construct/commands/inspections/set_schedule/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/set_schedule' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/set_schedule' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/set_schedule/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/set_schedule/build.liquid new file mode 100644 index 00000000..5df391c2 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/set_schedule/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/inspections/set_schedule/build + + Normalizes input and prepares the request for PUT + /v4/inspections/{id}/schedule: the request path (with the inspection + id) and the JSON-serialized inspection body. + + Params: + object - Hash with `id` and `inspection` (see set_schedule.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.id | url_encode }}/schedule" + assign object.payload = object.inspection | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/set_schedule/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/set_schedule/check.liquid new file mode 100644 index 00000000..921bbb26 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/set_schedule/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/inspections/set_schedule/check + Validates the object built by build.liquid before it's sent to Accela. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/update.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/update.liquid new file mode 100644 index 00000000..a12ed7d1 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/update.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/inspections/update + Wraps: PUT /v4/inspections/{id} (Accela "Update Inspection") + + Params: + id - Inspection id (required) + inspection - Hash of fields to update - required as this module's own + interface contract; Accela documents every body field on + the sibling Schedule Inspection endpoint as optional, so + this is a sanity check on our side, not Accela-mandated. + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + update/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/inspections/update', id: inspection_id, inspection: changes %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "id": id, "inspection": inspection } + function object = 'modules/accela_construct/commands/inspections/update/build', object: object + function object = 'modules/accela_construct/commands/inspections/update/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/inspections/update' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/inspections/update' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/update/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/update/build.liquid new file mode 100644 index 00000000..7426b369 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/update/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/inspections/update/build + + Normalizes input and prepares the request for PUT /v4/inspections/{id}: + the request path (with the inspection id) and the JSON-serialized + inspection body. + + Params: + object - Hash with `id` and `inspection` (see update.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.id | url_encode }}" + assign object.payload = object.inspection | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/update/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/update/check.liquid new file mode 100644 index 00000000..f28e87e1 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/inspections/update/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/inspections/update/check + Validates the object built by build.liquid before it's sent to Accela. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/additional/update.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/additional/update.liquid new file mode 100644 index 00000000..374e6f9b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/additional/update.liquid @@ -0,0 +1,39 @@ +{% comment %} + modules/accela_construct/commands/records/additional/update + Wraps: PUT /v4/records/{recordId}/additional (Accela "Update Additional Details") + + Params: + record_id - Record id (required) + additional - Hash of additional-detail fields, e.g. + { "buildingCount": 2, "estimatedValue": 150000 }. Every + field Accela documents here is Optional except `recordId` + itself, which build.liquid populates automatically from + `record_id` - callers never need to pass it twice. + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + update/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/additional/update', record_id: record_id, additional: additional %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "additional": additional } + function object = 'modules/accela_construct/commands/records/additional/update/build', object: object + function object = 'modules/accela_construct/commands/records/additional/update/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/additional/update' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/additional/update' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/additional/update/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/additional/update/build.liquid new file mode 100644 index 00000000..1b0c95d6 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/additional/update/build.liquid @@ -0,0 +1,26 @@ +{% comment %} + modules/accela_construct/commands/records/additional/update/build + + Normalizes input and prepares the request for PUT + /v4/records/{recordId}/additional: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id) and the JSON-serialized body. + Accela documents `recordId` as a required body field on this endpoint + (in addition to it being part of the path) - merged in here so callers + only ever pass `record_id` once. + + Params: + object - Hash with `record_id` and optional `additional` (see + records/additional/update.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/additional" + + assign body = object.additional | default: {} + assign body.recordId = object.record_id + assign object.payload = body | json + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/additional/update/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/additional/update/check.liquid new file mode 100644 index 00000000..8a44153e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/additional/update/check.liquid @@ -0,0 +1,16 @@ +{% comment %} + modules/accela_construct/commands/records/additional/update/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. `additional`'s + internal fields are all Accela-documented Optional, so only `record_id` + is checked here. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/create.liquid new file mode 100644 index 00000000..482a1a06 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/create.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/records/addresses/create + Wraps: POST /v4/records/{recordId}/addresses (Accela "Create Record Addresses") + + Params: + record_id - Record id (required) + address - Hash of address fields, e.g. { "streetName": "Main St", "city": "Pleasanton", "isPrimary": "Y" } + (required by this module as a sanity check on the call site - + Accela's own docs mark every address field Optional at the + schema level, so this isn't an Accela-mandated requirement) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + create/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/addresses/create', record_id: record_id, address: address %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "address": address } + function object = 'modules/accela_construct/commands/records/addresses/create/build', object: object + function object = 'modules/accela_construct/commands/records/addresses/create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/addresses/create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/addresses/create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/create/build.liquid new file mode 100644 index 00000000..b4d1e7b3 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/create/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/records/addresses/create/build + + Normalizes input and prepares the request for POST + /v4/records/{recordId}/addresses: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id) and the JSON-serialized address body. + + Params: + object - Hash with `record_id` and `address` (see addresses/create.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/addresses" + assign object.payload = object.address | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/create/check.liquid new file mode 100644 index 00000000..0cb3b679 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/create/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/records/addresses/create/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'address' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/delete.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/delete.liquid new file mode 100644 index 00000000..eeb8efdf --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/delete.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/commands/records/addresses/delete + Wraps: DELETE /v4/records/{recordId}/addresses/{ids} (Accela "Delete Record Addresses") + + Params: + record_id - Record id (required) + ids - String, comma-separated address id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + delete/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/addresses/delete', record_id: record_id, ids: address_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "ids": ids } + function object = 'modules/accela_construct/commands/records/addresses/delete/build', object: object + function object = 'modules/accela_construct/commands/records/addresses/delete/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/addresses/delete' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/addresses/delete' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/delete/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/delete/build.liquid new file mode 100644 index 00000000..36c844c0 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/delete/build.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/records/addresses/delete/build + + Normalizes input and prepares the request for DELETE + /v4/records/{recordId}/addresses/{ids}: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL). This request has no body. + + Params: + object - Hash with `record_id` and `ids` (see addresses/delete.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/addresses/{{ object.ids | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/delete/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/delete/check.liquid new file mode 100644 index 00000000..9d275edb --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/delete/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/records/addresses/delete/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/update.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/update.liquid new file mode 100644 index 00000000..e03530c0 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/update.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/records/addresses/update + Wraps: PUT /v4/records/{recordId}/addresses/{id} (Accela "Update Record Address") + + Params: + record_id - Record id (required) + id - Address id (required) + address - Hash of address fields to update (required by this module + as a sanity check - Accela's own docs mark every address + field Optional at the schema level) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + update/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/addresses/update', record_id: record_id, id: address_id, address: changes %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "id": id, "address": address } + function object = 'modules/accela_construct/commands/records/addresses/update/build', object: object + function object = 'modules/accela_construct/commands/records/addresses/update/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/addresses/update' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/addresses/update' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/update/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/update/build.liquid new file mode 100644 index 00000000..d8e15f5f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/update/build.liquid @@ -0,0 +1,19 @@ +{% comment %} + modules/accela_construct/commands/records/addresses/update/build + + Normalizes input and prepares the request for PUT + /v4/records/{recordId}/addresses/{id}: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id and address id) and the + JSON-serialized address body. + + Params: + object - Hash with `record_id`, `id`, and `address` (see addresses/update.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/addresses/{{ object.id | url_encode }}" + assign object.payload = object.address | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/update/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/update/check.liquid new file mode 100644 index 00000000..1c74ac9a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/addresses/update/check.liquid @@ -0,0 +1,16 @@ +{% comment %} + modules/accela_construct/commands/records/addresses/update/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'address' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/create.liquid new file mode 100644 index 00000000..aab07796 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/create.liquid @@ -0,0 +1,39 @@ +{% comment %} + modules/accela_construct/commands/records/conditions/create + Wraps: POST /v4/records/{recordId}/conditions (Accela "Create Record Conditions") + + Params: + record_id - Record id (required) + condition - Hash of condition fields (required by this module as an + interface-level sanity check; Accela's own docs mark every + body field on sibling create endpoints, e.g. parcels/owners, + as Optional at the schema level - required-ness there is + agency-configured, not fixed in the API contract) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + create/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/conditions/create', record_id: record_id, condition: condition %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "condition": condition } + function object = 'modules/accela_construct/commands/records/conditions/create/build', object: object + function object = 'modules/accela_construct/commands/records/conditions/create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/conditions/create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/conditions/create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/create/build.liquid new file mode 100644 index 00000000..d3400c6a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/create/build.liquid @@ -0,0 +1,19 @@ +{% comment %} + modules/accela_construct/commands/records/conditions/create/build + + Normalizes input and prepares the request for POST + /v4/records/{recordId}/conditions: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id) and the JSON-serialized condition + body. + + Params: + object - Hash with `record_id` and `condition` (see records/conditions/create.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/conditions" + assign object.payload = object.condition | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/create/check.liquid new file mode 100644 index 00000000..66e30b21 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/create/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/records/conditions/create/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'condition' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/delete.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/delete.liquid new file mode 100644 index 00000000..70526488 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/delete.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/commands/records/conditions/delete + Wraps: DELETE /v4/records/{recordId}/conditions/{ids} (Accela "Delete Record Conditions") + + Params: + record_id - Record id (required) + ids - String, comma-separated condition id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + delete/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/conditions/delete', record_id: record_id, ids: condition_ids %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "ids": ids } + function object = 'modules/accela_construct/commands/records/conditions/delete/build', object: object + function object = 'modules/accela_construct/commands/records/conditions/delete/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/conditions/delete' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/conditions/delete' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/delete/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/delete/build.liquid new file mode 100644 index 00000000..7c2a467b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/delete/build.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/records/conditions/delete/build + + Normalizes input and prepares the request for DELETE + /v4/records/{recordId}/conditions/{ids}: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL). This request has no body. + + Params: + object - Hash with `record_id` and `ids` (see records/conditions/delete.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/conditions/{{ object.ids | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/delete/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/delete/check.liquid new file mode 100644 index 00000000..72c04dd7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/delete/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/records/conditions/delete/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/update.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/update.liquid new file mode 100644 index 00000000..3b99c491 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/update.liquid @@ -0,0 +1,39 @@ +{% comment %} + modules/accela_construct/commands/records/conditions/update + Wraps: PUT /v4/records/{recordId}/conditions/{id} (Accela "Update Record Condition") + + Params: + record_id - Record id (required) + id - Condition id (required) + condition - Hash of condition fields to update (required by this + module as an interface-level sanity check; see the note + in create.liquid about Accela's body fields being + schema-optional) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + update/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/conditions/update', record_id: record_id, id: condition_id, condition: changes %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "id": id, "condition": condition } + function object = 'modules/accela_construct/commands/records/conditions/update/build', object: object + function object = 'modules/accela_construct/commands/records/conditions/update/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/conditions/update' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/conditions/update' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/update/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/update/build.liquid new file mode 100644 index 00000000..828bbbee --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/update/build.liquid @@ -0,0 +1,19 @@ +{% comment %} + modules/accela_construct/commands/records/conditions/update/build + + Normalizes input and prepares the request for PUT + /v4/records/{recordId}/conditions/{id}: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record and condition ids) and the + JSON-serialized condition body. + + Params: + object - Hash with `record_id`, `id`, and `condition` (see records/conditions/update.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/conditions/{{ object.id | url_encode }}" + assign object.payload = object.condition | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/update/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/update/check.liquid new file mode 100644 index 00000000..f7c66923 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/conditions/update/check.liquid @@ -0,0 +1,16 @@ +{% comment %} + modules/accela_construct/commands/records/conditions/update/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'condition' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/create.liquid new file mode 100644 index 00000000..0db1cc69 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/create.liquid @@ -0,0 +1,43 @@ +{% comment %} + modules/accela_construct/commands/records/create + Wraps: POST /v4/records (Accela "Create Record") + + Params: + record - Hash matching Accela's record schema, e.g. + { "type": { "id": "Building-Residential-Alteration-NA" }, + "description": "Residence alteration", + "parcels": [{ "parcelNumber": "005020018" }], + "addresses": [{ "isPrimary": "Y", "streetName": "123 Main Street", ... }], + "contacts": [{ "isPrimary": "Y", "fullName": "Joe Smith", ... }] } + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + TIP: call lib/queries/records/describe_create first with the same `type` to + discover which fields/elements Accela's agency configuration requires - + required fields vary per agency and record type. + + Follows the pos-module-core build/check/execute command pattern (see + create/{build,check}.liquid): build prepares the request URL/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/create', record: record %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record": record } + function object = 'modules/accela_construct/commands/records/create/build', object: object + function object = 'modules/accela_construct/commands/records/create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/create/build.liquid new file mode 100644 index 00000000..d8beb98d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/create/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/records/create/build + + Normalizes input and prepares the request for POST /v4/records: the + request path (relative to ACCELA_CONSTRUCT_BASE_URL) and the JSON-serialized + record body. + + Params: + object - Hash with `record` (see records/create.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = '/records' + assign object.payload = object.record | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/create/check.liquid new file mode 100644 index 00000000..ce172848 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/create/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/records/create/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/delete.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/delete.liquid new file mode 100644 index 00000000..e182c710 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/delete.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/commands/records/delete + Wraps: DELETE /v4/records/{ids} (Accela "Delete Records") + + Params: + ids - String, comma-separated record id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + delete/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/delete', ids: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "ids": ids } + function object = 'modules/accela_construct/commands/records/delete/build', object: object + function object = 'modules/accela_construct/commands/records/delete/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/delete' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/delete' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/delete/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/delete/build.liquid new file mode 100644 index 00000000..eca1f77f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/delete/build.liquid @@ -0,0 +1,16 @@ +{% comment %} + modules/accela_construct/commands/records/delete/build + + Normalizes input and prepares the request for DELETE /v4/records/{ids}: + the request path (relative to ACCELA_CONSTRUCT_BASE_URL). This request has no body. + + Params: + object - Hash with `ids` (see records/delete.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.ids | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/delete/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/delete/check.liquid new file mode 100644 index 00000000..b3c19061 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/delete/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/records/delete/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/delete.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/delete.liquid new file mode 100644 index 00000000..0f4949e1 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/delete.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/commands/records/documents/delete + Wraps: DELETE /v4/records/{recordId}/documents/{documentIds} (Accela "Delete Record Documents") + + Params: + record_id - Record id (required) + document_ids - String, comma-separated document id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + delete/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/documents/delete', record_id: record_id, document_ids: document_ids %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "document_ids": document_ids } + function object = 'modules/accela_construct/commands/records/documents/delete/build', object: object + function object = 'modules/accela_construct/commands/records/documents/delete/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/documents/delete' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/documents/delete' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/delete/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/delete/build.liquid new file mode 100644 index 00000000..12e913bf --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/delete/build.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/records/documents/delete/build + + Normalizes input and prepares the request for DELETE + /v4/records/{recordId}/documents/{documentIds}: the request path + (relative to ACCELA_CONSTRUCT_BASE_URL). This request has no body. + + Params: + object - Hash with `record_id` and `document_ids` (see documents/delete.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/documents/{{ object.document_ids | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/delete/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/delete/check.liquid new file mode 100644 index 00000000..a331118a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/delete/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/records/documents/delete/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'document_ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/upload.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/upload.liquid new file mode 100644 index 00000000..f731498a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/upload.liquid @@ -0,0 +1,56 @@ +{% comment %} + modules/accela_construct/commands/records/documents/upload + Wraps: POST /v4/records/{recordId}/documents (Accela "Create Record Documents") + Accela requires multipart/form-data with two parts: `uploadedFile` + (the binary) and `fileInfo` (a JSON string array of metadata). + + *** VERIFY BEFORE PRODUCTION USE *** + platformOS API Call Notifications support a `post_multipart` request + type, but the exact Liquid syntax for attaching a raw file part inside + the notification template is not clearly documented. The current + implementation in public/api_calls/accela_post_multipart.liquid is a + best-effort scaffold - confirm against your platformOS instance/support + how binary file uploads should be represented in an API Call + Notification body (likely needs the file made available via a prior + file-upload mutation and referenced by URL/id rather than inlined). + + Params: + record_id - Record id (required) + file_field - Raw file content or a reference to already-uploaded file data (required) + file_name - Original file name, e.g. "site_plan.pdf" (required) + content_type- MIME type, e.g. "application/pdf" (required) + category - optional, must match a value from documents/categories + description - optional description string + reference - optional hash `{ "id", "table" }` forwarded to + send.liquid - see send.liquid. + + No with_retries param here - MULTIPART requests are never retried since + file content can't be safely re-sent from a detached background job + (see lib/accela_client/send.liquid), so exposing the flag would be a + documented no-op. + + Follows the pos-module-core build/check/execute command pattern (see + upload/{build,check}.liquid): build prepares the request URL and the + `fileInfo` body, check validates required params, and this file + executes the request itself once valid (rather than delegating to a + separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/documents/upload', + record_id: record_id, file_field: file_content, file_name: 'site_plan.pdf', + content_type: 'application/pdf', description: 'Site plan' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "file_field": file_field, "file_name": file_name, "content_type": content_type, "category": category, "description": description } + function object = 'modules/accela_construct/commands/records/documents/upload/build', object: object + function object = 'modules/accela_construct/commands/records/documents/upload/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'MULTIPART', path: object.path, file_field: object.file_field, file_info: object.file_info, reference: reference, caller: 'modules/accela_construct/commands/records/documents/upload' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/documents/upload' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/upload/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/upload/build.liquid new file mode 100644 index 00000000..a9084b11 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/upload/build.liquid @@ -0,0 +1,29 @@ +{% comment %} + modules/accela_construct/commands/records/documents/upload/build + + Normalizes input and prepares the request for POST + /v4/records/{recordId}/documents: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL) and the `fileInfo` JSON body Accela expects alongside + the uploaded file part. + + Params: + object - Hash with `record_id`, `file_name`, `content_type`, and + optional `category`/`description` (see documents/upload.liquid) + + Returns object with `path` and `file_info` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/documents" + + assign file_info_item = { "fileName": object.file_name, "type": object.content_type } + if object.category != blank + assign file_info_item.category = object.category + endif + if object.description != blank + assign file_info_item.description = object.description + endif + assign object.file_info = "[{{ file_info_item | json }}]" + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/upload/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/upload/check.liquid new file mode 100644 index 00000000..75bf84dd --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/documents/upload/check.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/records/documents/upload/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'file_field' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'file_name' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'content_type' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/finalize.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/finalize.liquid new file mode 100644 index 00000000..7b66079b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/finalize.liquid @@ -0,0 +1,39 @@ +{% comment %} + modules/accela_construct/commands/records/finalize + Wraps: POST /v4/records/{recordId}/finalize (Accela "Finalize Record") + + Params: + record_id - Record id (required) + + No request body fields are documented for this endpoint - it's sent + with no payload. + + Params (continued): + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + finalize/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/finalize', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/commands/records/finalize/build', object: object + function object = 'modules/accela_construct/commands/records/finalize/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/finalize' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/finalize' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/finalize/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/finalize/build.liquid new file mode 100644 index 00000000..822778ab --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/finalize/build.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/records/finalize/build + + Normalizes input and prepares the request for POST + /v4/records/{recordId}/finalize: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id). This request has no body. + + Params: + object - Hash with `record_id` (see records/finalize.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/finalize" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/finalize/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/finalize/check.liquid new file mode 100644 index 00000000..b936cc01 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/finalize/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/records/finalize/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/initialize.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/initialize.liquid new file mode 100644 index 00000000..f0463c5a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/initialize.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/records/initialize + Wraps: POST /v4/records/initialize (Accela "Create Partial Record") + + Params: + record - Hash matching Accela's record schema (same shape as + records/create.liquid's `record` param). Accela's own docs + mark every Create Record body field Optional - `record` + being required here is this module's own interface-level + requirement, not an Accela-documented one. + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + initialize/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/initialize', record: record %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record": record } + function object = 'modules/accela_construct/commands/records/initialize/build', object: object + function object = 'modules/accela_construct/commands/records/initialize/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/initialize' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/initialize' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/initialize/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/initialize/build.liquid new file mode 100644 index 00000000..b1366df8 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/initialize/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/records/initialize/build + + Normalizes input and prepares the request for POST /v4/records/initialize: + the request path (relative to ACCELA_CONSTRUCT_BASE_URL) and the JSON-serialized + record body. + + Params: + object - Hash with `record` (see records/initialize.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = '/records/initialize' + assign object.payload = object.record | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/initialize/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/initialize/check.liquid new file mode 100644 index 00000000..d9016f1e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/initialize/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/records/initialize/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/create.liquid new file mode 100644 index 00000000..639cada3 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/create.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/records/owners/create + Wraps: POST /v4/records/{recordId}/owners (Accela "Create Record Owners") + + Params: + record_id - Record id (required) + owner - Hash of owner fields, e.g. { "firstName": "Joe", "lastName": "Smith", "isPrimary": "Y" } + (required by this module as a sanity check on the call site - + Accela's own docs mark every owner field Optional at the + schema level, so this isn't an Accela-mandated requirement) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + create/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/owners/create', record_id: record_id, owner: owner %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "owner": owner } + function object = 'modules/accela_construct/commands/records/owners/create/build', object: object + function object = 'modules/accela_construct/commands/records/owners/create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/owners/create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/owners/create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/create/build.liquid new file mode 100644 index 00000000..3931c8c4 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/create/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/records/owners/create/build + + Normalizes input and prepares the request for POST + /v4/records/{recordId}/owners: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id) and the JSON-serialized owner body. + + Params: + object - Hash with `record_id` and `owner` (see owners/create.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/owners" + assign object.payload = object.owner | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/create/check.liquid new file mode 100644 index 00000000..075936fc --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/create/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/records/owners/create/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'owner' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/delete.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/delete.liquid new file mode 100644 index 00000000..f41f6339 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/delete.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/commands/records/owners/delete + Wraps: DELETE /v4/records/{recordId}/owners/{ids} (Accela "Delete Record Owners") + + Params: + record_id - Record id (required) + ids - String, comma-separated owner id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + delete/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/owners/delete', record_id: record_id, ids: owner_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "ids": ids } + function object = 'modules/accela_construct/commands/records/owners/delete/build', object: object + function object = 'modules/accela_construct/commands/records/owners/delete/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/owners/delete' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/owners/delete' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/delete/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/delete/build.liquid new file mode 100644 index 00000000..d52b6fb7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/delete/build.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/records/owners/delete/build + + Normalizes input and prepares the request for DELETE + /v4/records/{recordId}/owners/{ids}: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL). This request has no body. + + Params: + object - Hash with `record_id` and `ids` (see owners/delete.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/owners/{{ object.ids | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/delete/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/delete/check.liquid new file mode 100644 index 00000000..4bcc73c9 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/delete/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/records/owners/delete/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/update.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/update.liquid new file mode 100644 index 00000000..71614caf --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/update.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/records/owners/update + Wraps: PUT /v4/records/{recordId}/owners/{id} (Accela "Update Record Owner") + + Params: + record_id - Record id (required) + id - Owner id (required) + owner - Hash of owner fields to update (required by this module as + a sanity check - Accela's own docs mark every owner field + Optional at the schema level) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + update/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/owners/update', record_id: record_id, id: owner_id, owner: changes %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "id": id, "owner": owner } + function object = 'modules/accela_construct/commands/records/owners/update/build', object: object + function object = 'modules/accela_construct/commands/records/owners/update/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/owners/update' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/owners/update' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/update/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/update/build.liquid new file mode 100644 index 00000000..872dbc67 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/update/build.liquid @@ -0,0 +1,19 @@ +{% comment %} + modules/accela_construct/commands/records/owners/update/build + + Normalizes input and prepares the request for PUT + /v4/records/{recordId}/owners/{id}: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id and owner id) and the + JSON-serialized owner body. + + Params: + object - Hash with `record_id`, `id`, and `owner` (see owners/update.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/owners/{{ object.id | url_encode }}" + assign object.payload = object.owner | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/update/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/update/check.liquid new file mode 100644 index 00000000..17d99e35 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/owners/update/check.liquid @@ -0,0 +1,16 @@ +{% comment %} + modules/accela_construct/commands/records/owners/update/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'owner' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/create.liquid new file mode 100644 index 00000000..23c59e2e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/create.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/records/parcels/create + Wraps: POST /v4/records/{recordId}/parcels (Accela "Create Record Parcels") + + Params: + record_id - Record id (required) + parcel - Hash of parcel fields, e.g. { "parcelNumber": "005020018", "isPrimary": "Y" } + (required by this module as a sanity check on the call site - + Accela's own docs mark every parcel field Optional at the + schema level, so this isn't an Accela-mandated requirement) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + create/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/parcels/create', record_id: record_id, parcel: parcel %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "parcel": parcel } + function object = 'modules/accela_construct/commands/records/parcels/create/build', object: object + function object = 'modules/accela_construct/commands/records/parcels/create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/parcels/create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/parcels/create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/create/build.liquid new file mode 100644 index 00000000..6d1a7816 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/create/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/records/parcels/create/build + + Normalizes input and prepares the request for POST + /v4/records/{recordId}/parcels: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id) and the JSON-serialized parcel body. + + Params: + object - Hash with `record_id` and `parcel` (see parcels/create.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/parcels" + assign object.payload = object.parcel | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/create/check.liquid new file mode 100644 index 00000000..1534f5a1 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/create/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/records/parcels/create/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'parcel' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/delete.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/delete.liquid new file mode 100644 index 00000000..ea062e68 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/delete.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/commands/records/parcels/delete + Wraps: DELETE /v4/records/{recordId}/parcels/{ids} (Accela "Delete Record Parcels") + + Params: + record_id - Record id (required) + ids - String, comma-separated parcel id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + delete/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/parcels/delete', record_id: record_id, ids: parcel_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "ids": ids } + function object = 'modules/accela_construct/commands/records/parcels/delete/build', object: object + function object = 'modules/accela_construct/commands/records/parcels/delete/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/parcels/delete' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/parcels/delete' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/delete/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/delete/build.liquid new file mode 100644 index 00000000..7253506b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/delete/build.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/records/parcels/delete/build + + Normalizes input and prepares the request for DELETE + /v4/records/{recordId}/parcels/{ids}: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL). This request has no body. + + Params: + object - Hash with `record_id` and `ids` (see parcels/delete.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/parcels/{{ object.ids | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/delete/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/delete/check.liquid new file mode 100644 index 00000000..a2d5addf --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/delete/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/records/parcels/delete/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/update.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/update.liquid new file mode 100644 index 00000000..87e6ced7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/update.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/commands/records/parcels/update + Wraps: PUT /v4/records/{recordId}/parcels/{id} (Accela "Update Record Parcel") + + Params: + record_id - Record id (required) + id - Parcel id (required) + parcel - Hash of parcel fields to update (required by this module as + a sanity check - Accela's own docs mark every parcel field + Optional at the schema level) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + update/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/parcels/update', record_id: record_id, id: parcel_id, parcel: changes %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "id": id, "parcel": parcel } + function object = 'modules/accela_construct/commands/records/parcels/update/build', object: object + function object = 'modules/accela_construct/commands/records/parcels/update/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/parcels/update' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/parcels/update' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/update/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/update/build.liquid new file mode 100644 index 00000000..b7d36f11 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/update/build.liquid @@ -0,0 +1,19 @@ +{% comment %} + modules/accela_construct/commands/records/parcels/update/build + + Normalizes input and prepares the request for PUT + /v4/records/{recordId}/parcels/{id}: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id and parcel id) and the + JSON-serialized parcel body. + + Params: + object - Hash with `record_id`, `id`, and `parcel` (see parcels/update.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/parcels/{{ object.id | url_encode }}" + assign object.payload = object.parcel | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/update/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/update/check.liquid new file mode 100644 index 00000000..fd5b4377 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/parcels/update/check.liquid @@ -0,0 +1,16 @@ +{% comment %} + modules/accela_construct/commands/records/parcels/update/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'parcel' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/create.liquid new file mode 100644 index 00000000..b7b57c0e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/create.liquid @@ -0,0 +1,39 @@ +{% comment %} + modules/accela_construct/commands/records/related/create + Wraps: POST /v4/records/{recordId}/related (Accela "Create Related Details") + + Params: + record_id - Record id (required) + related_record_ids - String, comma-separated record id(s) to link to + this record (required - Accela documents + `relatedRecordIds[]` as a required body array on + this endpoint, unlike most other Create + endpoints where every body field is optional) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + create/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/related/create', record_id: record_id, related_record_ids: '12CAP-00000-00002,12CAP-00000-00003' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "related_record_ids": related_record_ids } + function object = 'modules/accela_construct/commands/records/related/create/build', object: object + function object = 'modules/accela_construct/commands/records/related/create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/related/create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/related/create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/create/build.liquid new file mode 100644 index 00000000..228134be --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/create/build.liquid @@ -0,0 +1,23 @@ +{% comment %} + modules/accela_construct/commands/records/related/create/build + + Normalizes input and prepares the request for POST + /v4/records/{recordId}/related: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id) and the JSON-serialized + `relatedRecordIds` array body Accela requires for this endpoint. + + Params: + object - Hash with `record_id` and `related_record_ids` (comma- + separated string; see records/related/create.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/related" + + assign related_record_ids_array = object.related_record_ids | split: ',' + assign object.payload = { "relatedRecordIds": related_record_ids_array } | json + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/create/check.liquid new file mode 100644 index 00000000..24f0a295 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/create/check.liquid @@ -0,0 +1,17 @@ +{% comment %} + modules/accela_construct/commands/records/related/create/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. Both fields + checked here are genuinely Accela-required (not just this module's own + sanity check) - see build.liquid's comment. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'related_record_ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/delete.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/delete.liquid new file mode 100644 index 00000000..c053ed72 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/delete.liquid @@ -0,0 +1,37 @@ +{% comment %} + modules/accela_construct/commands/records/related/delete + Wraps: DELETE /v4/records/{recordId}/related/{childRecordIds} + (Accela "Delete Related Details") + + Params: + record_id - Record id (required) + child_record_ids - String, comma-separated related record id(s) to + unlink (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + delete/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/related/delete', record_id: record_id, child_record_ids: '12CAP-00000-00002' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "child_record_ids": child_record_ids } + function object = 'modules/accela_construct/commands/records/related/delete/build', object: object + function object = 'modules/accela_construct/commands/records/related/delete/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'DELETE', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/related/delete' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/related/delete' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/delete/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/delete/build.liquid new file mode 100644 index 00000000..56104bb0 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/delete/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/records/related/delete/build + + Normalizes input and prepares the request for DELETE + /v4/records/{recordId}/related/{childRecordIds}: the request path + (relative to ACCELA_CONSTRUCT_BASE_URL). This request has no body. + + Params: + object - Hash with `record_id` and `child_record_ids` (see + records/related/delete.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/related/{{ object.child_record_ids | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/delete/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/delete/check.liquid new file mode 100644 index 00000000..e9933bd5 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/related/delete/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/records/related/delete/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'child_record_ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/update.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/update.liquid new file mode 100644 index 00000000..d557257a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/update.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/commands/records/update + Wraps: PUT /v4/records/{id} (Accela "Update Record") + + Params: + id - Record id (required) + record - Hash of fields to update, e.g. { "description": "...", "status": { "value": "Issued" } } + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + update/{build,check}.liquid): build prepares the request URL/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/update', id: record_id, record: changes %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "id": id, "record": record } + function object = 'modules/accela_construct/commands/records/update/build', object: object + function object = 'modules/accela_construct/commands/records/update/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/update' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/update' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/update/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/update/build.liquid new file mode 100644 index 00000000..1fcdbf9c --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/update/build.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/commands/records/update/build + + Normalizes input and prepares the request for PUT /v4/records/{id}: the + request path (relative to ACCELA_CONSTRUCT_BASE_URL, with the record id) and the + JSON-serialized changes body. + + Params: + object - Hash with `id` and `record` (see records/update.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.id | url_encode }}" + assign object.payload = object.record | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/update/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/update/check.liquid new file mode 100644 index 00000000..164e22ed --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/update/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/commands/records/update/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/usercomments/create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/usercomments/create.liquid new file mode 100644 index 00000000..9bab4c61 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/usercomments/create.liquid @@ -0,0 +1,40 @@ +{% comment %} + modules/accela_construct/commands/records/usercomments/create + Wraps: POST /v4/records/{recordId}/usercomments + (Accela "Create Record User Comments" - DEPRECATED per Accela's docs; + kept here for completeness since the endpoint still exists, but prefer + an agency-supported alternative if one exists on your instance). + + Params: + record_id - Record id (required) + comment - optional hash of comment fields; Accela documents no + required body fields for this endpoint. Sent as `{}` if + not provided. + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + create/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/usercomments/create', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "comment": comment } + function object = 'modules/accela_construct/commands/records/usercomments/create/build', object: object + function object = 'modules/accela_construct/commands/records/usercomments/create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/usercomments/create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/usercomments/create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/usercomments/create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/usercomments/create/build.liquid new file mode 100644 index 00000000..8101e3aa --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/usercomments/create/build.liquid @@ -0,0 +1,21 @@ +{% comment %} + modules/accela_construct/commands/records/usercomments/create/build + + Normalizes input and prepares the request for POST + /v4/records/{recordId}/usercomments: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id) and the JSON-serialized body + (empty object if no `comment` hash was given). + + Params: + object - Hash with `record_id` and optional `comment` (see + records/usercomments/create.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/usercomments" + assign body = object.comment | default: {} + assign object.payload = body | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/usercomments/create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/usercomments/create/check.liquid new file mode 100644 index 00000000..70ad9bf7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/usercomments/create/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/records/usercomments/create/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/votes/create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/votes/create.liquid new file mode 100644 index 00000000..bfdfdb44 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/votes/create.liquid @@ -0,0 +1,37 @@ +{% comment %} + modules/accela_construct/commands/records/votes/create + Wraps: POST /v4/records/{recordId}/votes (Accela "Create Record Votes") + + Params: + record_id - Record id (required) + vote - optional hash of vote fields; Accela documents no + required body fields for this endpoint. Sent as `{}` if + not provided. + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check/execute command pattern (see + create/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/votes/create', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "vote": vote } + function object = 'modules/accela_construct/commands/records/votes/create/build', object: object + function object = 'modules/accela_construct/commands/records/votes/create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/votes/create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/votes/create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/votes/create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/votes/create/build.liquid new file mode 100644 index 00000000..b7342649 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/votes/create/build.liquid @@ -0,0 +1,21 @@ +{% comment %} + modules/accela_construct/commands/records/votes/create/build + + Normalizes input and prepares the request for POST + /v4/records/{recordId}/votes: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record id) and the JSON-serialized body + (empty object if no `vote` hash was given). + + Params: + object - Hash with `record_id` and optional `vote` (see + records/votes/create.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/votes" + assign body = object.vote | default: {} + assign object.payload = body | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/votes/create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/votes/create/check.liquid new file mode 100644 index 00000000..b092e3b9 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/votes/create/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/commands/records/votes/create/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/workflow_tasks/update.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/workflow_tasks/update.liquid new file mode 100644 index 00000000..0ecea70b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/workflow_tasks/update.liquid @@ -0,0 +1,42 @@ +{% comment %} + modules/accela_construct/commands/records/workflow_tasks/update + Wraps: PUT /v4/records/{recordId}/workflowTasks/{id} (Accela "Update Task") + + Params: + record_id - Record id (required) + id - Workflow task id (required) + task - Hash of task fields to update, e.g. { "status": { "value": "Approved" } } + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + *** VERIFY BEFORE PRODUCTION USE *** + Accela's own field-level requirements for this endpoint's body were not + independently verified for this task - `task` is required only as this + module's own interface-level sanity check, not because Accela's schema + documents any body field as required. + + Follows the pos-module-core build/check/execute command pattern (see + update/{build,check}.liquid): build prepares the request path/body, + check validates required params, and this file executes the request + itself once valid (rather than delegating to a separate execute.liquid). + + Usage: + {% function result = 'modules/accela_construct/commands/records/workflow_tasks/update', record_id: record_id, id: task_id, task: changes %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "id": id, "task": task } + function object = 'modules/accela_construct/commands/records/workflow_tasks/update/build', object: object + function object = 'modules/accela_construct/commands/records/workflow_tasks/update/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'PUT', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/commands/records/workflow_tasks/update' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/commands/records/workflow_tasks/update' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/workflow_tasks/update/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/workflow_tasks/update/build.liquid new file mode 100644 index 00000000..dc14aba8 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/workflow_tasks/update/build.liquid @@ -0,0 +1,19 @@ +{% comment %} + modules/accela_construct/commands/records/workflow_tasks/update/build + + Normalizes input and prepares the request for PUT + /v4/records/{recordId}/workflowTasks/{id}: the request path (relative to + ACCELA_CONSTRUCT_BASE_URL, with the record and task ids) and the JSON-serialized + task body. + + Params: + object - Hash with `record_id`, `id`, `task` (see workflow_tasks/update.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/workflowTasks/{{ object.id | url_encode }}" + assign object.payload = object.task | json + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/workflow_tasks/update/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/workflow_tasks/update/check.liquid new file mode 100644 index 00000000..d0da409f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/commands/records/workflow_tasks/update/check.liquid @@ -0,0 +1,16 @@ +{% comment %} + modules/accela_construct/commands/records/workflow_tasks/update/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'task' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/events/accela_construct_request_succeeded.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/events/accela_construct_request_succeeded.liquid new file mode 100644 index 00000000..4054e88a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/events/accela_construct_request_succeeded.liquid @@ -0,0 +1,42 @@ +--- +metadata: + event: + caller + method + path + reference + request_id + response_id + attempt_number +--- +{% comment %} + modules/accela_construct/events/accela_construct_request_succeeded + + Validates the event lib/accela_client/send.liquid broadcasts (via + `modules/core/commands/events/publish`) after every successful Accela + attempt - see send.liquid's doc comment for the full field-by-field + rundown of what identifies "what request that was" and when + `request_id`/`response_id` are/aren't known yet. + + Params (the `event` object, per pos-module-core's event convention): + caller - the calling query/command's own module path (always present) + method - "GET" | "POST" | "PUT" | "DELETE" | "MULTIPART" (always present) + path - request path relative to ACCELA_CONSTRUCT_BASE_URL (always present) + reference - optional hash `{ "id", "table" }` this call was made on + behalf of - see send.liquid + request_id - the accela_request row id for this logical request, + blank only if that write itself failed - see send.liquid + response_id - the accela_request_response row id for this specific + attempt, blank only if that write itself failed - see send.liquid + attempt_number - 1-based attempt counter (always present) +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'caller' + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'method' + function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'path' + + return c +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_oauth_token/find.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_oauth_token/find.liquid new file mode 100644 index 00000000..4ceca94f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_oauth_token/find.liquid @@ -0,0 +1,16 @@ +{% comment %} + modules/accela_construct/queries/accela_oauth_token/find + + Returns the most recently created accela_oauth_token record, or nil if + none exists yet. Used by lib/accela_client/get_valid_token to check + whether a cached token is still valid before requesting a new one. + + Usage: + {% function token_record = 'modules/accela_construct/queries/accela_oauth_token/find' %} +{% endcomment %} + +{% liquid + graphql token_result = 'modules/accela_construct/accela_oauth_token/find_latest' + assign token_record = token_result.records.results.first + return token_record +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_request/get.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_request/get.liquid new file mode 100644 index 00000000..9e38c1e0 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_request/get.liquid @@ -0,0 +1,22 @@ +{% comment %} + modules/accela_construct/queries/accela_request/get + + Returns one accela_request row by id (method, path, request_payload), + or nil if it doesn't exist. Used by perform_retry_attempt.liquid to + look up the original request rather than carrying method/path/payload + through the retry chain as arguments - schedule_retry.liquid/ + perform_retry_attempt.liquid only ever pass around the accela_request + id (`request_id`) plus retry bookkeeping. + + Params: + id - accela_request row id (required) + + Usage: + {% function accela_request = 'modules/accela_construct/queries/accela_request/get', id: some_id %} +{% endcomment %} + +{% liquid + graphql get_result = 'modules/accela_construct/accela_request/get', id: id + assign accela_request = get_result.records.results.first + return accela_request +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_request/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_request/list.liquid new file mode 100644 index 00000000..9eebe84b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_request/list.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/queries/accela_request/list + + Lists accela_request rows (newest first) - one row per logical Accela + request this module has made, created once on that request's first + attempt (see lib/accela_client/log_request.liquid). Each request may + have multiple accela_request_response rows (one per attempt, including + retries) - see queries/accela_request_response/list; filter that query + by `request_id` and read its `total_entries` for "how many attempts so + far," rather than looking for a stored count here. Each row also + carries an optional `reference_id`/`reference_schema` polymorphic + association to whatever platformOS record triggered the request - see + send.liquid's `reference` param. + + Params (all optional): + method - exact match, e.g. "POST" + path - exact match, e.g. "/records" + reference - hash `{ "id", "table" }`, either or both given, to find + requests tied to one specific platformOS record (unlike + send.liquid's `reference` param, `table` is never + auto-resolved here if omitted - filtering by `id` alone + is already unambiguous within this table, so there's + nothing worth the extra round trip to look up) + limit - default 25 + page - default 1 + + Usage: + {% function requests = 'modules/accela_construct/queries/accela_request/list', reference: { "id": some_id } %} +{% endcomment %} + +{% liquid + assign limit = limit | default: 25 + assign page = page | default: 1 + + graphql list_result = 'modules/accela_construct/accela_request/list', method: method, path: path, reference_id: reference.id, reference_schema: reference.table, limit: limit, page: page + assign requests = list_result.records + return requests +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_request_response/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_request_response/list.liquid new file mode 100644 index 00000000..24125af1 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/accela_request_response/list.liquid @@ -0,0 +1,26 @@ +{% comment %} + modules/accela_construct/queries/accela_request_response/list + + Lists accela_request_response rows (newest first) - one row per attempt + (including background retry attempts) against an accela_request. Filter + by `request_id` to see every attempt/response for one logical request, + e.g. a full retry chain. + + Params (all optional): + request_id - id of an accela_request row + success - true|false + limit - default 25 + page - default 1 + + Usage: + {% function responses = 'modules/accela_construct/queries/accela_request_response/list', request_id: some_id %} +{% endcomment %} + +{% liquid + assign limit = limit | default: 25 + assign page = page | default: 1 + + graphql list_result = 'modules/accela_construct/accela_request_response/list', request_id: request_id, success: success, limit: limit, page: page + assign responses = list_result.records + return responses +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/documents/download.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/documents/download.liquid new file mode 100644 index 00000000..b5cbc1b6 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/documents/download.liquid @@ -0,0 +1,43 @@ +{% comment %} + modules/accela_construct/queries/documents/download + Wraps: GET /v4/documents/{documentId}/download (Accela "Download Document") + Response is a raw binary stream, not JSON. + + *** VERIFY BEFORE PRODUCTION USE *** + lib/accela_client/send.liquid assumes a JSON response body (it calls + `response.body | parse_json`). For binary documents this will fail/return + nil. Treat `result.raw` as the authoritative field for binary content and + confirm with a real sandbox call how platformOS's api_call_send response + object represents binary payloads (e.g. base64-encoded string) before + relying on this for real downloads. + + Params: + document_id - Document id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + download/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/documents/download', document_id: document_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "document_id": document_id } + function object = 'modules/accela_construct/queries/documents/download/build', object: object + function object = 'modules/accela_construct/queries/documents/download/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/documents/download' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/documents/download' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/documents/download/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/documents/download/build.liquid new file mode 100644 index 00000000..0b882ba7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/documents/download/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/documents/download/build + + Builds the request path for GET /v4/documents/{documentId}/download. + + Params: + object - Hash with `document_id` (see documents/download.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/documents/{{ object.document_id | url_encode }}/download" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/documents/download/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/documents/download/check.liquid new file mode 100644 index 00000000..a3ed70c5 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/documents/download/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/documents/download/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'document_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/all.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/all.liquid new file mode 100644 index 00000000..21ec9721 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/all.liquid @@ -0,0 +1,43 @@ +{% comment %} + modules/accela_construct/queries/inspections/all + Wraps: GET /v4/inspections (Accela "Get All Inspections") + + General filterable inspection listing, not scoped to a single record - + see lib/queries/records/inspections/list for GET /v4/records/{recordId}/inspections. + + Params (all optional): + module - string, filter by module + types - comma-separated inspection type values + scheduled_date_from - string date + scheduled_date_to - string date + inspector_ids - comma-separated inspector ids + district_ids - comma-separated district ids + offset, limit - pagination + with_retries - optional boolean, default false. When true, + retries a failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + all/{build,check}.liquid): build prepares the request path, check + validates required params (none for this endpoint - see check.liquid) + and this file executes the request itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/inspections/all', module: 'Building' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "module": module, "types": types, "scheduled_date_from": scheduled_date_from, "scheduled_date_to": scheduled_date_to, "inspector_ids": inspector_ids, "district_ids": district_ids, "offset": offset, "limit": limit } + function object = 'modules/accela_construct/queries/inspections/all/build', object: object + function object = 'modules/accela_construct/queries/inspections/all/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/inspections/all' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/inspections/all' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/all/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/all/build.liquid new file mode 100644 index 00000000..2ecf8d7a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/all/build.liquid @@ -0,0 +1,24 @@ +{% comment %} + modules/accela_construct/queries/inspections/all/build + + Builds the request path for GET /v4/inspections. + + Params: + object - Hash with `module`, `types`, `scheduled_date_from`, + `scheduled_date_to`, `inspector_ids`, `district_ids`, + `offset`, `limit` (see inspections/all.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign qs_params = { "module": object.module, "types": object.types, "scheduledDateFrom": object.scheduled_date_from, "scheduledDateTo": object.scheduled_date_to, "inspectorIds": object.inspector_ids, "districtIds": object.district_ids, "offset": object.offset, "limit": object.limit } + function qs = 'modules/accela_construct/accela_client/build_query_string', params: qs_params + + assign object.path = "/inspections" + if qs != blank + assign object.path = "{{ object.path }}?{{ qs }}" + endif + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/all/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/all/check.liquid new file mode 100644 index 00000000..af4369a4 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/all/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/inspections/all/check + No required params for this endpoint - every filter Accela documents + for "Get All Inspections" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/available_dates.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/available_dates.liquid new file mode 100644 index 00000000..58e84dba --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/available_dates.liquid @@ -0,0 +1,43 @@ +{% comment %} + modules/accela_construct/queries/inspections/available_dates + Wraps: GET /v4/inspections/availableDates (Accela "Get Available Dates") + + Params: + type_id - Long, inspection type id (required) + record_id - String, record id (required) + start_date - String date (required) + offset, limit - optional pagination + fields - optional comma-separated string + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + NOTE: unlike most Accela query params, Accela documents type_id/record_id/ + start_date as required for this endpoint even though they're sent as + query-string params, not path segments - check.liquid validates all + three are present before this ever reaches Accela. + + Follows the pos-module-core build/check command pattern (see + available_dates/{build,check}.liquid): build prepares the request + path, check validates required params, and this file executes the + request itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/inspections/available_dates', type_id: 173, record_id: record_id, start_date: '2026-08-01' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "type_id": type_id, "record_id": record_id, "start_date": start_date, "offset": offset, "limit": limit, "fields": fields } + function object = 'modules/accela_construct/queries/inspections/available_dates/build', object: object + function object = 'modules/accela_construct/queries/inspections/available_dates/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/inspections/available_dates' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/inspections/available_dates' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/available_dates/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/available_dates/build.liquid new file mode 100644 index 00000000..f64a5139 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/available_dates/build.liquid @@ -0,0 +1,23 @@ +{% comment %} + modules/accela_construct/queries/inspections/available_dates/build + + Builds the request path for GET /v4/inspections/availableDates. + + Params: + object - Hash with `type_id`, `record_id`, `start_date`, `offset`, + `limit`, `fields` (see inspections/available_dates.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign qs_params = { "typeId": object.type_id, "recordId": object.record_id, "startDate": object.start_date, "offset": object.offset, "limit": object.limit, "fields": object.fields } + function qs = 'modules/accela_construct/accela_client/build_query_string', params: qs_params + + assign object.path = "/inspections/availableDates" + if qs != blank + assign object.path = "{{ object.path }}?{{ qs }}" + endif + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/available_dates/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/available_dates/check.liquid new file mode 100644 index 00000000..68dd32f4 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/available_dates/check.liquid @@ -0,0 +1,18 @@ +{% comment %} + modules/accela_construct/queries/inspections/available_dates/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. type_id/record_id/ + start_date are Accela-required for this endpoint even though they're + query-string params rather than path segments. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'type_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'start_date' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/checklists/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/checklists/list.liquid new file mode 100644 index 00000000..e04db40a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/checklists/list.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/inspections/checklists/list + Wraps: GET /v4/inspections/{inspectionId}/checklists (Accela "Get All Checklists") + + Params: + inspection_id - Inspection id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + list/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/inspections/checklists/list', inspection_id: inspection_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "inspection_id": inspection_id } + function object = 'modules/accela_construct/queries/inspections/checklists/list/build', object: object + function object = 'modules/accela_construct/queries/inspections/checklists/list/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/inspections/checklists/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/inspections/checklists/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/checklists/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/checklists/list/build.liquid new file mode 100644 index 00000000..184faf5e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/checklists/list/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/inspections/checklists/list/build + + Builds the request path for GET /v4/inspections/{inspectionId}/checklists. + + Params: + object - Hash with `inspection_id` (see inspections/checklists/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.inspection_id | url_encode }}/checklists" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/checklists/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/checklists/list/check.liquid new file mode 100644 index 00000000..61652737 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/checklists/list/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/inspections/checklists/list/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/get.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/get.liquid new file mode 100644 index 00000000..97f94aed --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/get.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/queries/inspections/conditions/get + Wraps: GET /v4/inspections/{inspectionId}/conditions/{id} (Accela "Get Inspection Condition") + + Params: + inspection_id - Inspection id (required) + id - Condition id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + get/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/inspections/conditions/get', inspection_id: inspection_id, id: condition_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "inspection_id": inspection_id, "id": id } + function object = 'modules/accela_construct/queries/inspections/conditions/get/build', object: object + function object = 'modules/accela_construct/queries/inspections/conditions/get/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/inspections/conditions/get' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/inspections/conditions/get' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/get/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/get/build.liquid new file mode 100644 index 00000000..72a85274 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/get/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/inspections/conditions/get/build + + Builds the request path for GET /v4/inspections/{inspectionId}/conditions/{id}. + + Params: + object - Hash with `inspection_id`, `id` (see inspections/conditions/get.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.inspection_id | url_encode }}/conditions/{{ object.id | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/get/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/get/check.liquid new file mode 100644 index 00000000..0b2aff7a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/get/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/inspections/conditions/get/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/histories.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/histories.liquid new file mode 100644 index 00000000..aa387455 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/histories.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/queries/inspections/conditions/histories + Wraps: GET /v4/inspections/{inspectionId}/conditions/{id}/histories (Accela "Get Condition History") + + Params: + inspection_id - Inspection id (required) + id - Condition id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + histories/{build,check}.liquid): build prepares the request path, + check validates required params, and this file executes the request + itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/inspections/conditions/histories', inspection_id: inspection_id, id: condition_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "inspection_id": inspection_id, "id": id } + function object = 'modules/accela_construct/queries/inspections/conditions/histories/build', object: object + function object = 'modules/accela_construct/queries/inspections/conditions/histories/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/inspections/conditions/histories' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/inspections/conditions/histories' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/histories/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/histories/build.liquid new file mode 100644 index 00000000..19182c47 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/histories/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/inspections/conditions/histories/build + + Builds the request path for GET /v4/inspections/{inspectionId}/conditions/{id}/histories. + + Params: + object - Hash with `inspection_id`, `id` (see inspections/conditions/histories.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.inspection_id | url_encode }}/conditions/{{ object.id | url_encode }}/histories" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/histories/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/histories/check.liquid new file mode 100644 index 00000000..d62c7e9b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/histories/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/inspections/conditions/histories/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/list.liquid new file mode 100644 index 00000000..d0e419d8 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/list.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/inspections/conditions/list + Wraps: GET /v4/inspections/{inspectionId}/conditions (Accela "Get All Standard Conditions") + + Params: + inspection_id - Inspection id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + list/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/inspections/conditions/list', inspection_id: inspection_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "inspection_id": inspection_id } + function object = 'modules/accela_construct/queries/inspections/conditions/list/build', object: object + function object = 'modules/accela_construct/queries/inspections/conditions/list/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/inspections/conditions/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/inspections/conditions/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/list/build.liquid new file mode 100644 index 00000000..420bea86 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/list/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/inspections/conditions/list/build + + Builds the request path for GET /v4/inspections/{inspectionId}/conditions. + + Params: + object - Hash with `inspection_id` (see inspections/conditions/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.inspection_id | url_encode }}/conditions" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/list/check.liquid new file mode 100644 index 00000000..8b729b17 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/conditions/list/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/inspections/conditions/list/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/get.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/get.liquid new file mode 100644 index 00000000..9975b369 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/get.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/queries/inspections/get + Wraps: GET /v4/inspections/{ids} (Accela "Get Inspections") + + Params: + ids - String, comma-separated inspection id(s) (required) + fields - optional comma-separated string + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + get/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/inspections/get', ids: inspection_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "ids": ids, "fields": fields } + function object = 'modules/accela_construct/queries/inspections/get/build', object: object + function object = 'modules/accela_construct/queries/inspections/get/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/inspections/get' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/inspections/get' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/get/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/get/build.liquid new file mode 100644 index 00000000..e5d20ea1 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/get/build.liquid @@ -0,0 +1,22 @@ +{% comment %} + modules/accela_construct/queries/inspections/get/build + + Builds the request path for GET /v4/inspections/{ids}. + + Params: + object - Hash with `ids`, `fields` (see inspections/get.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign qs_params = { "fields": object.fields } + function qs = 'modules/accela_construct/accela_client/build_query_string', params: qs_params + + assign object.path = "/inspections/{{ object.ids | url_encode }}" + if qs != blank + assign object.path = "{{ object.path }}?{{ qs }}" + endif + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/get/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/get/check.liquid new file mode 100644 index 00000000..086bdb44 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/get/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/inspections/get/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/histories.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/histories.liquid new file mode 100644 index 00000000..74fec15a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/histories.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/inspections/histories + Wraps: GET /v4/inspections/{inspectionIds}/histories (Accela "Get Inspection History") + + Params: + inspection_ids - String, comma-separated inspection id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + histories/{build,check}.liquid): build prepares the request path, + check validates required params, and this file executes the request + itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/inspections/histories', inspection_ids: inspection_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "inspection_ids": inspection_ids } + function object = 'modules/accela_construct/queries/inspections/histories/build', object: object + function object = 'modules/accela_construct/queries/inspections/histories/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/inspections/histories' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/inspections/histories' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/histories/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/histories/build.liquid new file mode 100644 index 00000000..e5491065 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/histories/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/inspections/histories/build + + Builds the request path for GET /v4/inspections/{inspectionIds}/histories. + + Params: + object - Hash with `inspection_ids` (see inspections/histories.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.inspection_ids | url_encode }}/histories" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/histories/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/histories/check.liquid new file mode 100644 index 00000000..601dad90 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/histories/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/inspections/histories/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'inspection_ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/related.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/related.liquid new file mode 100644 index 00000000..1c4b40c9 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/related.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/inspections/related + Wraps: GET /v4/inspections/{id}/related (Accela "Get Related Inspections") + + Params: + id - Inspection id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + related/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/inspections/related', id: inspection_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "id": id } + function object = 'modules/accela_construct/queries/inspections/related/build', object: object + function object = 'modules/accela_construct/queries/inspections/related/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/inspections/related' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/inspections/related' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/related/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/related/build.liquid new file mode 100644 index 00000000..72778123 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/related/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/inspections/related/build + + Builds the request path for GET /v4/inspections/{id}/related. + + Params: + object - Hash with `id` (see inspections/related.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/inspections/{{ object.id | url_encode }}/related" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/related/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/related/check.liquid new file mode 100644 index 00000000..fb56d167 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/inspections/related/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/inspections/related/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/additional.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/additional.liquid new file mode 100644 index 00000000..f46b05ee --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/additional.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/records/additional + Wraps: GET /v4/records/{recordId}/additional (Accela "Get Additional Details") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + additional/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/additional', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/additional/build', object: object + function object = 'modules/accela_construct/queries/records/additional/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/additional' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/additional' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/additional/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/additional/build.liquid new file mode 100644 index 00000000..f4e668a4 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/additional/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/additional/build + + Builds the request path for GET /v4/records/{recordId}/additional. + + Params: + object - Hash with `record_id` (see records/additional.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/additional" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/additional/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/additional/check.liquid new file mode 100644 index 00000000..f4a5aaec --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/additional/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/additional/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/addresses/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/addresses/list.liquid new file mode 100644 index 00000000..603ceb13 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/addresses/list.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/records/addresses/list + Wraps: GET /v4/records/{recordId}/addresses (Accela "Get All Addresses") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + list/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/addresses/list', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/addresses/list/build', object: object + function object = 'modules/accela_construct/queries/records/addresses/list/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/addresses/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/addresses/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/addresses/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/addresses/list/build.liquid new file mode 100644 index 00000000..46bc65c6 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/addresses/list/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/addresses/list/build + + Builds the request path for GET /v4/records/{recordId}/addresses. + + Params: + object - Hash with `record_id` (see records/addresses/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/addresses" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/addresses/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/addresses/list/check.liquid new file mode 100644 index 00000000..6c954481 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/addresses/list/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/addresses/list/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/get.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/get.liquid new file mode 100644 index 00000000..bce933df --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/get.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/queries/records/conditions/get + Wraps: GET /v4/records/{recordId}/conditions/{id} (Accela "Get Record Condition") + + Params: + record_id - Record id (required) + id - Condition id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + get/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/conditions/get', record_id: record_id, id: condition_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "id": id } + function object = 'modules/accela_construct/queries/records/conditions/get/build', object: object + function object = 'modules/accela_construct/queries/records/conditions/get/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/conditions/get' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/conditions/get' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/get/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/get/build.liquid new file mode 100644 index 00000000..bcba1596 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/get/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/conditions/get/build + + Builds the request path for GET /v4/records/{recordId}/conditions/{id}. + + Params: + object - Hash with `record_id`, `id` (see records/conditions/get.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/conditions/{{ object.id | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/get/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/get/check.liquid new file mode 100644 index 00000000..5276c8b6 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/get/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/conditions/get/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/histories.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/histories.liquid new file mode 100644 index 00000000..313fdb5a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/histories.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/queries/records/conditions/histories + Wraps: GET /v4/records/{recordId}/conditions/{id}/histories (Accela "Get History") + + Params: + record_id - Record id (required) + id - Condition id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + histories/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/conditions/histories', record_id: record_id, id: condition_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "id": id } + function object = 'modules/accela_construct/queries/records/conditions/histories/build', object: object + function object = 'modules/accela_construct/queries/records/conditions/histories/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/conditions/histories' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/conditions/histories' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/histories/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/histories/build.liquid new file mode 100644 index 00000000..faadea0b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/histories/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/conditions/histories/build + + Builds the request path for GET /v4/records/{recordId}/conditions/{id}/histories. + + Params: + object - Hash with `record_id`, `id` (see records/conditions/histories.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/conditions/{{ object.id | url_encode }}/histories" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/histories/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/histories/check.liquid new file mode 100644 index 00000000..00d1eebe --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/histories/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/conditions/histories/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/list.liquid new file mode 100644 index 00000000..6924f742 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/list.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/records/conditions/list + Wraps: GET /v4/records/{recordId}/conditions (Accela "Get All Conditions") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + list/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/conditions/list', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/conditions/list/build', object: object + function object = 'modules/accela_construct/queries/records/conditions/list/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/conditions/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/conditions/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/list/build.liquid new file mode 100644 index 00000000..9ac85b2c --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/list/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/conditions/list/build + + Builds the request path for GET /v4/records/{recordId}/conditions. + + Params: + object - Hash with `record_id` (see records/conditions/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/conditions" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/list/check.liquid new file mode 100644 index 00000000..7b7fd194 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/conditions/list/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/conditions/list/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/describe_create.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/describe_create.liquid new file mode 100644 index 00000000..9e21d4c7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/describe_create.liquid @@ -0,0 +1,37 @@ +{% comment %} + modules/accela_construct/queries/records/describe_create + Wraps: GET /v4/records/describe/create?type={type} + (Accela "Describe Required Record Attributes") - the authoritative, + per-agency, per-record-type list of required fields/elements. Call this + before records/create to build a valid payload. + + Params: + type - record type string, e.g. "Building/Residential/Alteration/NA" (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + describe_create/{build,check}.liquid): build prepares the request path, + check validates required params, and this file executes the request + itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/describe_create', type: 'Building/Residential/Alteration/NA' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "type": type } + function object = 'modules/accela_construct/queries/records/describe_create/build', object: object + function object = 'modules/accela_construct/queries/records/describe_create/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/describe_create' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/describe_create' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/describe_create/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/describe_create/build.liquid new file mode 100644 index 00000000..5a36e5b6 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/describe_create/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/describe_create/build + + Builds the request path for GET /v4/records/describe/create?type={type}. + + Params: + object - Hash with `type` (see records/describe_create.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/describe/create?type={{ object.type | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/describe_create/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/describe_create/check.liquid new file mode 100644 index 00000000..6a5868a5 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/describe_create/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/describe_create/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'type' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/categories.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/categories.liquid new file mode 100644 index 00000000..bbca36f5 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/categories.liquid @@ -0,0 +1,37 @@ +{% comment %} + modules/accela_construct/queries/records/documents/categories + Wraps: GET /v4/records/{recordId}/documentCategories + (Accela "Get Document Categories for Record") - document categories are + agency-configured, not a fixed enum; look them up before uploading so + fileInfo.category matches an accepted value. + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + categories/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/documents/categories', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/documents/categories/build', object: object + function object = 'modules/accela_construct/queries/records/documents/categories/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/documents/categories' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/documents/categories' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/categories/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/categories/build.liquid new file mode 100644 index 00000000..c1fc0f1d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/categories/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/documents/categories/build + + Builds the request path for GET /v4/records/{recordId}/documentCategories. + + Params: + object - Hash with `record_id` (see documents/categories.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/documentCategories" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/categories/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/categories/check.liquid new file mode 100644 index 00000000..90ca7b1e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/categories/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/documents/categories/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/list.liquid new file mode 100644 index 00000000..748ca889 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/list.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/queries/records/documents/list + Wraps: GET /v4/records/{recordId}/documents (Accela "Get All Documents for Record") + + Params: + record_id - Record id (required) + fields - optional comma-separated string + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + list/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/documents/list', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "fields": fields } + function object = 'modules/accela_construct/queries/records/documents/list/build', object: object + function object = 'modules/accela_construct/queries/records/documents/list/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/documents/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/documents/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/list/build.liquid new file mode 100644 index 00000000..463e1c07 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/list/build.liquid @@ -0,0 +1,22 @@ +{% comment %} + modules/accela_construct/queries/records/documents/list/build + + Builds the request path for GET /v4/records/{recordId}/documents. + + Params: + object - Hash with `record_id`, `fields` (see documents/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign qs_params = { "fields": object.fields } + function qs = 'modules/accela_construct/accela_client/build_query_string', params: qs_params + + assign object.path = "/records/{{ object.record_id | url_encode }}/documents" + if qs != blank + assign object.path = "{{ object.path }}?{{ qs }}" + endif + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/list/check.liquid new file mode 100644 index 00000000..78e521be --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/documents/list/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/documents/list/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/get.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/get.liquid new file mode 100644 index 00000000..2e6caf36 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/get.liquid @@ -0,0 +1,36 @@ +{% comment %} + modules/accela_construct/queries/records/get + Wraps: GET /v4/records/{ids} (Accela "Get Records by id(s)/customId") + + Params: + ids - String, comma-separated record id(s)/customId(s) (required) + expand - optional comma-separated string, e.g. "addresses,parcels,professionals,contacts,owners,customForms,customTables,assets,conditions" + fields - optional comma-separated string + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + get/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/get', ids: '12CAP-00000-00001' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "ids": ids, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/records/get/build', object: object + function object = 'modules/accela_construct/queries/records/get/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/get' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/get' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/get/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/get/build.liquid new file mode 100644 index 00000000..d2779995 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/get/build.liquid @@ -0,0 +1,22 @@ +{% comment %} + modules/accela_construct/queries/records/get/build + + Builds the request path for GET /v4/records/{ids}. + + Params: + object - Hash with `ids`, `expand`, `fields` (see records/get.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign qs_params = { "expand": object.expand, "fields": object.fields } + function qs = 'modules/accela_construct/accela_client/build_query_string', params: qs_params + + assign object.path = "/records/{{ object.ids | url_encode }}" + if qs != blank + assign object.path = "{{ object.path }}?{{ qs }}" + endif + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/get/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/get/check.liquid new file mode 100644 index 00000000..8eec2445 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/get/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/get/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspection_types/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspection_types/list.liquid new file mode 100644 index 00000000..f23786ce --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspection_types/list.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/queries/records/inspection_types/list + Wraps: GET /v4/records/{recordIds}/inspectionTypes + (Accela "Get All Inspection Types for Record") - returns each type's + numeric `id`, used as `type.id` when scheduling. + + Params: + record_ids - String, comma-separated record id(s) (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + types/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/inspection_types/list', record_ids: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_ids": record_ids } + function object = 'modules/accela_construct/queries/records/inspection_types/list/build', object: object + function object = 'modules/accela_construct/queries/records/inspection_types/list/check', object: object + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/inspection_types/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/inspection_types/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspection_types/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspection_types/list/build.liquid new file mode 100644 index 00000000..3ace86a7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspection_types/list/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/inspection_types/list/build + + Builds the request path for GET /v4/records/{recordIds}/inspectionTypes. + + Params: + object - Hash with `record_ids` (see inspection_types/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_ids | url_encode }}/inspectionTypes" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspection_types/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspection_types/list/check.liquid new file mode 100644 index 00000000..96ff9eea --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspection_types/list/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/inspection_types/list/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_ids' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspections/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspections/list.liquid new file mode 100644 index 00000000..69e71097 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspections/list.liquid @@ -0,0 +1,36 @@ +{% comment %} + modules/accela_construct/queries/records/inspections/list + Wraps: GET /v4/records/{recordId}/inspections (Accela "Get All Inspections for Record") + + Params: + record_id - Record id (required) + offset, limit - optional pagination (Accela default limit 25, max 1000) + fields - optional comma-separated string + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + list/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/inspections/list', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "offset": offset, "limit": limit, "fields": fields } + function object = 'modules/accela_construct/queries/records/inspections/list/build', object: object + function object = 'modules/accela_construct/queries/records/inspections/list/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/inspections/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/inspections/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspections/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspections/list/build.liquid new file mode 100644 index 00000000..bf9c43a5 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspections/list/build.liquid @@ -0,0 +1,23 @@ +{% comment %} + modules/accela_construct/queries/records/inspections/list/build + + Builds the request path for GET /v4/records/{recordId}/inspections. + + Params: + object - Hash with `record_id`, `offset`, `limit`, `fields` + (see inspections/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.offset = object.offset | default: 0 + assign object.limit = object.limit | default: 25 + + assign qs_params = { "offset": object.offset, "limit": object.limit, "fields": object.fields } + function qs = 'modules/accela_construct/accela_client/build_query_string', params: qs_params + + assign object.path = "/records/{{ object.record_id | url_encode }}/inspections?{{ qs }}" + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspections/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspections/list/check.liquid new file mode 100644 index 00000000..c549f37b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/inspections/list/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/inspections/list/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/list.liquid new file mode 100644 index 00000000..0f2a277e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/list.liquid @@ -0,0 +1,38 @@ +{% comment %} + modules/accela_construct/queries/records/list + Wraps: GET /v4/records (Accela "Get All Records") + + Params (all optional): offset, limit, fields, module, status. + Accela documents roughly 25 optional filters on this endpoint + (assignedDateFrom/To, closedDateFrom/To, customId, recordClass, + openedDateFrom/To, type, updateDateFrom/To, etc.) - only the most + common ones are wired up here; add more the same way via `qs_params` + if you need them. + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + list/{build,check}.liquid): build prepares the request path, check + validates required params (none for this endpoint - see check.liquid) + and this file executes the request itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/list', module: 'Building', limit: 25 %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "offset": offset, "limit": limit, "fields": fields, "module": module, "status": status } + function object = 'modules/accela_construct/queries/records/list/build', object: object + function object = 'modules/accela_construct/queries/records/list/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/list/build.liquid new file mode 100644 index 00000000..f2938857 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/list/build.liquid @@ -0,0 +1,23 @@ +{% comment %} + modules/accela_construct/queries/records/list/build + + Builds the request path for GET /v4/records. + + Params: + object - Hash with `offset`, `limit`, `fields`, `module`, `status` + (see records/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign qs_params = { "offset": object.offset, "limit": object.limit, "fields": object.fields, "module": object.module, "status": object.status } + function qs = 'modules/accela_construct/accela_client/build_query_string', params: qs_params + + assign object.path = '/records' + if qs != blank + assign object.path = "{{ object.path }}?{{ qs }}" + endif + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/list/check.liquid new file mode 100644 index 00000000..bfdbc199 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/list/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/records/list/check + No required params for this endpoint - every filter Accela documents + for "Get All Records" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/mine.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/mine.liquid new file mode 100644 index 00000000..fa4bb2db --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/mine.liquid @@ -0,0 +1,33 @@ +{% comment %} + modules/accela_construct/queries/records/mine + Wraps: GET /v4/records/mine (Accela "Get My Records") + + Params (all optional): offset, limit, fields. + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + mine/{build,check}.liquid): build prepares the request path, check + validates required params (none for this endpoint - see check.liquid) + and this file executes the request itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/mine' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "offset": offset, "limit": limit, "fields": fields } + function object = 'modules/accela_construct/queries/records/mine/build', object: object + function object = 'modules/accela_construct/queries/records/mine/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/mine' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/mine' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/mine/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/mine/build.liquid new file mode 100644 index 00000000..7ce19d0d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/mine/build.liquid @@ -0,0 +1,22 @@ +{% comment %} + modules/accela_construct/queries/records/mine/build + + Builds the request path for GET /v4/records/mine. + + Params: + object - Hash with `offset`, `limit`, `fields` (see records/mine.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign qs_params = { "offset": object.offset, "limit": object.limit, "fields": object.fields } + function qs = 'modules/accela_construct/accela_client/build_query_string', params: qs_params + + assign object.path = '/records/mine' + if qs != blank + assign object.path = "{{ object.path }}?{{ qs }}" + endif + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/mine/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/mine/check.liquid new file mode 100644 index 00000000..47285224 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/mine/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/records/mine/check + No required params for this endpoint - offset/limit/fields are all + optional. Kept for structural consistency with the build/check split + used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/owners/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/owners/list.liquid new file mode 100644 index 00000000..31e90532 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/owners/list.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/records/owners/list + Wraps: GET /v4/records/{recordId}/owners (Accela "Get All Owners") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + list/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/owners/list', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/owners/list/build', object: object + function object = 'modules/accela_construct/queries/records/owners/list/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/owners/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/owners/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/owners/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/owners/list/build.liquid new file mode 100644 index 00000000..0ee3e191 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/owners/list/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/owners/list/build + + Builds the request path for GET /v4/records/{recordId}/owners. + + Params: + object - Hash with `record_id` (see records/owners/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/owners" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/owners/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/owners/list/check.liquid new file mode 100644 index 00000000..25263ea4 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/owners/list/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/owners/list/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/parcels/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/parcels/list.liquid new file mode 100644 index 00000000..7df4849b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/parcels/list.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/records/parcels/list + Wraps: GET /v4/records/{recordId}/parcels (Accela "Get All Parcels") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + list/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/parcels/list', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/parcels/list/build', object: object + function object = 'modules/accela_construct/queries/records/parcels/list/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/parcels/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/parcels/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/parcels/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/parcels/list/build.liquid new file mode 100644 index 00000000..a2bb554f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/parcels/list/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/parcels/list/build + + Builds the request path for GET /v4/records/{recordId}/parcels. + + Params: + object - Hash with `record_id` (see records/parcels/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/parcels" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/parcels/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/parcels/list/check.liquid new file mode 100644 index 00000000..46c9921d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/parcels/list/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/parcels/list/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/get.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/get.liquid new file mode 100644 index 00000000..98f9a80b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/get.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/queries/records/payments/get + Wraps: GET /v4/records/{recordId}/payments/{paymentId} (Accela "Get Payment") + + Params: + record_id - Record id (required) + payment_id - Payment id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + get/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/payments/get', record_id: record_id, payment_id: payment_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "payment_id": payment_id } + function object = 'modules/accela_construct/queries/records/payments/get/build', object: object + function object = 'modules/accela_construct/queries/records/payments/get/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/payments/get' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/payments/get' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/get/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/get/build.liquid new file mode 100644 index 00000000..2e4cf65b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/get/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/payments/get/build + + Builds the request path for GET /v4/records/{recordId}/payments/{paymentId}. + + Params: + object - Hash with `record_id`, `payment_id` (see records/payments/get.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/payments/{{ object.payment_id | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/get/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/get/check.liquid new file mode 100644 index 00000000..784a06ed --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/get/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/payments/get/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'payment_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/list.liquid new file mode 100644 index 00000000..53c280ab --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/list.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/records/payments/list + Wraps: GET /v4/records/{recordId}/payments (Accela "Get All Payments for Record") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + list/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/payments/list', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/payments/list/build', object: object + function object = 'modules/accela_construct/queries/records/payments/list/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/payments/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/payments/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/list/build.liquid new file mode 100644 index 00000000..f1c8aa8a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/list/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/payments/list/build + + Builds the request path for GET /v4/records/{recordId}/payments. + + Params: + object - Hash with `record_id` (see records/payments/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/payments" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/list/check.liquid new file mode 100644 index 00000000..2596ca58 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/payments/list/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/payments/list/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/related.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/related.liquid new file mode 100644 index 00000000..bcb0f5a9 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/related.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/records/related + Wraps: GET /v4/records/{recordId}/related (Accela "Get All Related Details") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + related/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/related', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/related/build', object: object + function object = 'modules/accela_construct/queries/records/related/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/related' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/related' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/related/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/related/build.liquid new file mode 100644 index 00000000..44b3ac54 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/related/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/related/build + + Builds the request path for GET /v4/records/{recordId}/related. + + Params: + object - Hash with `record_id` (see records/related.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/related" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/related/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/related/check.liquid new file mode 100644 index 00000000..57439b8d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/related/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/related/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/search.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/search.liquid new file mode 100644 index 00000000..0947b44a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/search.liquid @@ -0,0 +1,45 @@ +{% comment %} + modules/accela_construct/queries/records/search + Wraps: POST /v4/search/records (Accela "Search Records") + + Params: + criteria - Hash of search criteria, e.g. + { "module": "Building", "type": { "value": "Building/Commercial/Addition/NA" }, + "openedDateFrom": "2013-01-01 00:00:00", "openedDateTo": "2013-06-30 00:00:00" } + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string, e.g. "addresses,parcels,owners" + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + search/{build,check}.liquid): build prepares the request path and + payload, check validates required params (none for this endpoint - + see check.liquid) and this file executes the request itself once + valid. + + Usage: + {% assign criteria = { "module": "Building" } %} + {% function result = 'modules/accela_construct/queries/records/search', criteria: criteria, limit: 25 %} + + Returns the normalized result hash from lib/accela_client/send (result.body.result + is the array of matching records on success). +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "criteria": criteria, "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/records/search/build', object: object + function object = 'modules/accela_construct/queries/records/search/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'POST', path: object.path, payload: object.payload, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/search' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/search' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/search/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/search/build.liquid new file mode 100644 index 00000000..86d34616 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/search/build.liquid @@ -0,0 +1,24 @@ +{% comment %} + modules/accela_construct/queries/records/search/build + + Builds the request path and payload for POST /v4/search/records. + + Params: + object - Hash with `criteria`, `offset`, `limit`, `expand`, `fields` + (see records/search.liquid) + + Returns object with `path` and `payload` added. +{% endcomment %} + +{% liquid + assign object.offset = object.offset | default: 0 + assign object.limit = object.limit | default: 25 + + assign qs_params = { "offset": object.offset, "limit": object.limit, "expand": object.expand, "fields": object.fields } + function qs = 'modules/accela_construct/accela_client/build_query_string', params: qs_params + + assign object.path = "/search/records?{{ qs }}" + assign object.payload = null | hash_merge: object.criteria | json + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/search/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/search/check.liquid new file mode 100644 index 00000000..5ac8a062 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/search/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/records/search/check + No required params for this endpoint - Accela documents no required + search criteria field for "Search Records". Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/usercomments.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/usercomments.liquid new file mode 100644 index 00000000..cfd1678b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/usercomments.liquid @@ -0,0 +1,36 @@ +{% comment %} + modules/accela_construct/queries/records/usercomments + Wraps: GET /v4/records/{recordId}/usercomments + (Accela "Get All User Comments" - DEPRECATED per Accela's docs; kept + here for completeness since the endpoint still exists). + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + usercomments/{build,check}.liquid): build prepares the request path, + check validates required params, and this file executes the request + itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/usercomments', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/usercomments/build', object: object + function object = 'modules/accela_construct/queries/records/usercomments/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/usercomments' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/usercomments' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/usercomments/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/usercomments/build.liquid new file mode 100644 index 00000000..15c82d7c --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/usercomments/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/usercomments/build + + Builds the request path for GET /v4/records/{recordId}/usercomments. + + Params: + object - Hash with `record_id` (see records/usercomments.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/usercomments" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/usercomments/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/usercomments/check.liquid new file mode 100644 index 00000000..520b304c --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/usercomments/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/usercomments/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes.liquid new file mode 100644 index 00000000..006e76de --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/records/votes + Wraps: GET /v4/records/{recordId}/votes (Accela "Get All Votes") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + votes/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/votes', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/votes/build', object: object + function object = 'modules/accela_construct/queries/records/votes/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/votes' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/votes' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes/build.liquid new file mode 100644 index 00000000..73a232a5 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/votes/build + + Builds the request path for GET /v4/records/{recordId}/votes. + + Params: + object - Hash with `record_id` (see records/votes.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/votes" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes/check.liquid new file mode 100644 index 00000000..f0928967 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/votes/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes_summary.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes_summary.liquid new file mode 100644 index 00000000..ea368e09 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes_summary.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/records/votes_summary + Wraps: GET /v4/records/{recordId}/votes/summary (Accela "Get Record Votes Summary") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + votes_summary/{build,check}.liquid): build prepares the request path, + check validates required params, and this file executes the request + itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/votes_summary', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/votes_summary/build', object: object + function object = 'modules/accela_construct/queries/records/votes_summary/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/votes_summary' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/votes_summary' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes_summary/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes_summary/build.liquid new file mode 100644 index 00000000..c8a71340 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes_summary/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/votes_summary/build + + Builds the request path for GET /v4/records/{recordId}/votes/summary. + + Params: + object - Hash with `record_id` (see records/votes_summary.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/votes/summary" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes_summary/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes_summary/check.liquid new file mode 100644 index 00000000..445b8067 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/votes_summary/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/votes_summary/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/comments_histories.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/comments_histories.liquid new file mode 100644 index 00000000..dc045812 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/comments_histories.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/comments_histories + Wraps: GET /v4/records/{recordId}/workflowTasks/comments/histories + (Accela "Get Task Comment History List") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + comments_histories/{build,check}.liquid): build prepares the request + path, check validates required params, and this file executes the + request itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/workflow_tasks/comments_histories', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/workflow_tasks/comments_histories/build', object: object + function object = 'modules/accela_construct/queries/records/workflow_tasks/comments_histories/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/workflow_tasks/comments_histories' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/workflow_tasks/comments_histories' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/comments_histories/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/comments_histories/build.liquid new file mode 100644 index 00000000..7744f0d9 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/comments_histories/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/comments_histories/build + + Builds the request path for GET /v4/records/{recordId}/workflowTasks/comments/histories. + + Params: + object - Hash with `record_id` (see records/workflow_tasks/comments_histories.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/workflowTasks/comments/histories" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/comments_histories/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/comments_histories/check.liquid new file mode 100644 index 00000000..00d8b252 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/comments_histories/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/comments_histories/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/get.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/get.liquid new file mode 100644 index 00000000..1ab20005 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/get.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/get + Wraps: GET /v4/records/{recordId}/workflowTasks/{id} (Accela "Get Task") + + Params: + record_id - Record id (required) + id - Workflow task id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + get/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/workflow_tasks/get', record_id: record_id, id: task_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "id": id } + function object = 'modules/accela_construct/queries/records/workflow_tasks/get/build', object: object + function object = 'modules/accela_construct/queries/records/workflow_tasks/get/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/workflow_tasks/get' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/workflow_tasks/get' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/get/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/get/build.liquid new file mode 100644 index 00000000..0746b5be --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/get/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/get/build + + Builds the request path for GET /v4/records/{recordId}/workflowTasks/{id}. + + Params: + object - Hash with `record_id`, `id` (see records/workflow_tasks/get.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/workflowTasks/{{ object.id | url_encode }}" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/get/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/get/check.liquid new file mode 100644 index 00000000..1dd95d91 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/get/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/get/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/histories.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/histories.liquid new file mode 100644 index 00000000..0ee78248 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/histories.liquid @@ -0,0 +1,35 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/histories + Wraps: GET /v4/records/{recordId}/workflowTasks/histories + (Accela "Get Task History List") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + histories/{build,check}.liquid): build prepares the request path, + check validates required params, and this file executes the request + itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/workflow_tasks/histories', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/workflow_tasks/histories/build', object: object + function object = 'modules/accela_construct/queries/records/workflow_tasks/histories/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/workflow_tasks/histories' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/workflow_tasks/histories' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/histories/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/histories/build.liquid new file mode 100644 index 00000000..66ed2b75 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/histories/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/histories/build + + Builds the request path for GET /v4/records/{recordId}/workflowTasks/histories. + + Params: + object - Hash with `record_id` (see records/workflow_tasks/histories.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/workflowTasks/histories" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/histories/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/histories/check.liquid new file mode 100644 index 00000000..f456f421 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/histories/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/histories/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/list.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/list.liquid new file mode 100644 index 00000000..ee9f081d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/list.liquid @@ -0,0 +1,34 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/list + Wraps: GET /v4/records/{recordId}/workflowTasks (Accela "Get All Tasks for Record") + + Params: + record_id - Record id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + list/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/workflow_tasks/list', record_id: record_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id } + function object = 'modules/accela_construct/queries/records/workflow_tasks/list/build', object: object + function object = 'modules/accela_construct/queries/records/workflow_tasks/list/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/workflow_tasks/list' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/workflow_tasks/list' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/list/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/list/build.liquid new file mode 100644 index 00000000..c8cdbd73 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/list/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/list/build + + Builds the request path for GET /v4/records/{recordId}/workflowTasks. + + Params: + object - Hash with `record_id` (see records/workflow_tasks/list.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/workflowTasks" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/list/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/list/check.liquid new file mode 100644 index 00000000..9bf60c71 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/list/check.liquid @@ -0,0 +1,14 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/list/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/statuses.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/statuses.liquid new file mode 100644 index 00000000..eba90962 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/statuses.liquid @@ -0,0 +1,36 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/statuses + Wraps: GET /v4/records/{recordId}/workflowTasks/{id}/statuses + (Accela "Get All Available Statuses for Task") + + Params: + record_id - Record id (required) + id - Workflow task id (required) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - see + lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + statuses/{build,check}.liquid): build prepares the request path, check + validates required params, and this file executes the request itself + once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/records/workflow_tasks/statuses', record_id: record_id, id: task_id %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "record_id": record_id, "id": id } + function object = 'modules/accela_construct/queries/records/workflow_tasks/statuses/build', object: object + function object = 'modules/accela_construct/queries/records/workflow_tasks/statuses/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/records/workflow_tasks/statuses' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/records/workflow_tasks/statuses' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/statuses/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/statuses/build.liquid new file mode 100644 index 00000000..169362d8 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/statuses/build.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/statuses/build + + Builds the request path for GET /v4/records/{recordId}/workflowTasks/{id}/statuses. + + Params: + object - Hash with `record_id`, `id` (see records/workflow_tasks/statuses.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.path = "/records/{{ object.record_id | url_encode }}/workflowTasks/{{ object.id | url_encode }}/statuses" + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/statuses/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/statuses/check.liquid new file mode 100644 index 00000000..6f939c7a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/records/workflow_tasks/statuses/check.liquid @@ -0,0 +1,15 @@ +{% comment %} + modules/accela_construct/queries/records/workflow_tasks/statuses/check + Validates the object built by build.liquid before it's sent to Accela, + using pos-module-core's validation contract convention. +{% endcomment %} + +{% liquid + assign c = { "errors": {}, "valid": true } + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'record_id' + function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id' + + assign object.valid = c.valid + assign object.errors = c.errors + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/addresses.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/addresses.liquid new file mode 100644 index 00000000..70dc747a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/addresses.liquid @@ -0,0 +1,42 @@ +{% comment %} + modules/accela_construct/queries/searches/addresses + Wraps: POST /v4/search/addresses (Accela "Search Addresses") + + Params: + criteria - Hash of search criteria (all fields Accela documents for + this endpoint are individually optional) + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + addresses/{build,check}.liquid) for consistency with every other query, + even though there's nothing to build here - the actual path/body + construction lives in the shared lib/accela_client/post_search.liquid - + and nothing to check, since every field Accela documents for this + endpoint is optional. + + Usage: + {% assign criteria = { "streetName": "Main Street" } %} + {% function result = 'modules/accela_construct/queries/searches/addresses', criteria: criteria %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "criteria": criteria, "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/searches/addresses/build', object: object + function object = 'modules/accela_construct/queries/searches/addresses/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/post_search', resource: 'addresses', criteria: object.criteria, offset: object.offset, limit: object.limit, expand: object.expand, fields: object.fields, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/searches/addresses' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/searches/addresses' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/addresses/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/addresses/build.liquid new file mode 100644 index 00000000..cd3252e8 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/addresses/build.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/addresses/build + + No-op for this endpoint - lib/accela_client/post_search.liquid builds + the actual request path/body itself from `object.criteria`/offset/limit/ + expand/fields. Present only for structural consistency with the + build/check split used across all queries. +{% endcomment %} + +{% liquid + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/addresses/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/addresses/check.liquid new file mode 100644 index 00000000..e05d65e9 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/addresses/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/addresses/check + No required params for this endpoint - every field Accela documents + for "Search Addresses" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/agencies.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/agencies.liquid new file mode 100644 index 00000000..465ffa3e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/agencies.liquid @@ -0,0 +1,42 @@ +{% comment %} + modules/accela_construct/queries/searches/agencies + Wraps: POST /v4/search/agencies (Accela "Search Agencies") + + Params: + criteria - Hash of search criteria (all fields Accela documents for + this endpoint are individually optional) + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + agencies/{build,check}.liquid) for consistency with every other query, + even though there's nothing to build here - the actual path/body + construction lives in the shared lib/accela_client/post_search.liquid - + and nothing to check, since every field Accela documents for this + endpoint is optional. + + Usage: + {% assign criteria = { "name": "Nullisland" } %} + {% function result = 'modules/accela_construct/queries/searches/agencies', criteria: criteria %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "criteria": criteria, "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/searches/agencies/build', object: object + function object = 'modules/accela_construct/queries/searches/agencies/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/post_search', resource: 'agencies', criteria: object.criteria, offset: object.offset, limit: object.limit, expand: object.expand, fields: object.fields, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/searches/agencies' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/searches/agencies' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/agencies/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/agencies/build.liquid new file mode 100644 index 00000000..bd1e5e84 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/agencies/build.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/agencies/build + + No-op for this endpoint - lib/accela_client/post_search.liquid builds + the actual request path/body itself from `object.criteria`/offset/limit/ + expand/fields. Present only for structural consistency with the + build/check split used across all queries. +{% endcomment %} + +{% liquid + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/agencies/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/agencies/check.liquid new file mode 100644 index 00000000..8de5c273 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/agencies/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/agencies/check + No required params for this endpoint - every field Accela documents + for "Search Agencies" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/assessments.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/assessments.liquid new file mode 100644 index 00000000..fa7df86b --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/assessments.liquid @@ -0,0 +1,41 @@ +{% comment %} + modules/accela_construct/queries/searches/assessments + Wraps: POST /v4/search/assessments (Accela "Search Assessments") + + Params: + criteria - Hash of search criteria (all fields Accela documents for + this endpoint are individually optional) + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + assessments/{build,check}.liquid) for consistency with every other query, + even though there's nothing to build here - the actual path/body + construction lives in the shared lib/accela_client/post_search.liquid - + and nothing to check, since every field Accela documents for this + endpoint is optional. + + Usage: + {% function result = 'modules/accela_construct/queries/searches/assessments', criteria: criteria %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "criteria": criteria, "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/searches/assessments/build', object: object + function object = 'modules/accela_construct/queries/searches/assessments/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/post_search', resource: 'assessments', criteria: object.criteria, offset: object.offset, limit: object.limit, expand: object.expand, fields: object.fields, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/searches/assessments' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/searches/assessments' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/assessments/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/assessments/build.liquid new file mode 100644 index 00000000..a08c21a2 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/assessments/build.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/assessments/build + + No-op for this endpoint - lib/accela_client/post_search.liquid builds + the actual request path/body itself from `object.criteria`/offset/limit/ + expand/fields. Present only for structural consistency with the + build/check split used across all queries. +{% endcomment %} + +{% liquid + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/assessments/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/assessments/check.liquid new file mode 100644 index 00000000..278e523e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/assessments/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/assessments/check + No required params for this endpoint - every field Accela documents + for "Search Assessments" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/contacts.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/contacts.liquid new file mode 100644 index 00000000..cabd2236 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/contacts.liquid @@ -0,0 +1,41 @@ +{% comment %} + modules/accela_construct/queries/searches/contacts + Wraps: POST /v4/search/contacts (Accela "Search Contacts") + + Params: + criteria - Hash of search criteria (all fields Accela documents for + this endpoint are individually optional) + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + contacts/{build,check}.liquid) for consistency with every other query, + even though there's nothing to build here - the actual path/body + construction lives in the shared lib/accela_client/post_search.liquid - + and nothing to check, since every field Accela documents for this + endpoint is optional. + + Usage: + {% function result = 'modules/accela_construct/queries/searches/contacts', criteria: criteria %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "criteria": criteria, "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/searches/contacts/build', object: object + function object = 'modules/accela_construct/queries/searches/contacts/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/post_search', resource: 'contacts', criteria: object.criteria, offset: object.offset, limit: object.limit, expand: object.expand, fields: object.fields, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/searches/contacts' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/searches/contacts' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/contacts/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/contacts/build.liquid new file mode 100644 index 00000000..6c339122 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/contacts/build.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/contacts/build + + No-op for this endpoint - lib/accela_client/post_search.liquid builds + the actual request path/body itself from `object.criteria`/offset/limit/ + expand/fields. Present only for structural consistency with the + build/check split used across all queries. +{% endcomment %} + +{% liquid + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/contacts/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/contacts/check.liquid new file mode 100644 index 00000000..9b4b9b26 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/contacts/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/contacts/check + No required params for this endpoint - every field Accela documents + for "Search Contacts" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/costs.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/costs.liquid new file mode 100644 index 00000000..b4f9bab3 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/costs.liquid @@ -0,0 +1,41 @@ +{% comment %} + modules/accela_construct/queries/searches/costs + Wraps: POST /v4/search/costs (Accela "Search Costs") + + Params: + criteria - Hash of search criteria (all fields Accela documents for + this endpoint are individually optional) + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + costs/{build,check}.liquid) for consistency with every other query, + even though there's nothing to build here - the actual path/body + construction lives in the shared lib/accela_client/post_search.liquid - + and nothing to check, since every field Accela documents for this + endpoint is optional. + + Usage: + {% function result = 'modules/accela_construct/queries/searches/costs', criteria: criteria %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "criteria": criteria, "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/searches/costs/build', object: object + function object = 'modules/accela_construct/queries/searches/costs/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/post_search', resource: 'costs', criteria: object.criteria, offset: object.offset, limit: object.limit, expand: object.expand, fields: object.fields, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/searches/costs' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/searches/costs' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/costs/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/costs/build.liquid new file mode 100644 index 00000000..1a0eb9e7 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/costs/build.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/costs/build + + No-op for this endpoint - lib/accela_client/post_search.liquid builds + the actual request path/body itself from `object.criteria`/offset/limit/ + expand/fields. Present only for structural consistency with the + build/check split used across all queries. +{% endcomment %} + +{% liquid + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/costs/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/costs/check.liquid new file mode 100644 index 00000000..f1b4b2de --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/costs/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/costs/check + No required params for this endpoint - every field Accela documents + for "Search Costs" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/global.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/global.liquid new file mode 100644 index 00000000..ff9c0e9f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/global.liquid @@ -0,0 +1,43 @@ +{% comment %} + modules/accela_construct/queries/searches/global + Wraps: GET /v4/search/global (Accela "Search All") + Unlike the other searches/* queries, this one is a plain GET with + query-string params only - Accela documents no request body for it. + + Params: + query - optional search term + type - optional, the type of entity to query + modules - optional comma-separated string, confines the search to + specific modules + offset - optional, default 0 + limit - optional, default 25 + sort - optional, field name to sort by + direction - optional, "ASC" or "DESC" (Accela default is ASC) + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + global/{build,check}.liquid): build prepares the request path, check + validates required params (none for this endpoint - see check.liquid) + and this file executes the request itself once valid. + + Usage: + {% function result = 'modules/accela_construct/queries/searches/global', query: 'main street' %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "query": query, "type": type, "modules": modules, "offset": offset, "limit": limit, "sort": sort, "direction": direction } + function object = 'modules/accela_construct/queries/searches/global/build', object: object + function object = 'modules/accela_construct/queries/searches/global/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/send', method: 'GET', path: object.path, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/searches/global' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/searches/global' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/global/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/global/build.liquid new file mode 100644 index 00000000..aea2e16e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/global/build.liquid @@ -0,0 +1,23 @@ +{% comment %} + modules/accela_construct/queries/searches/global/build + + Builds the request path for GET /v4/search/global. + + Params: + object - Hash with `query`, `type`, `modules`, `offset`, `limit`, + `sort`, `direction` (see searches/global.liquid) + + Returns object with `path` added. +{% endcomment %} + +{% liquid + assign object.offset = object.offset | default: 0 + assign object.limit = object.limit | default: 25 + + assign qs_params = { "query": object.query, "type": object.type, "modules": object.modules, "offset": object.offset, "limit": object.limit, "sort": object.sort, "direction": object.direction } + function qs = 'modules/accela_construct/accela_client/build_query_string', params: qs_params + + assign object.path = "/search/global?{{ qs }}" + + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/global/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/global/check.liquid new file mode 100644 index 00000000..ec0837f6 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/global/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/global/check + No required params for this endpoint - every field Accela documents + for "Search All" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/inspections.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/inspections.liquid new file mode 100644 index 00000000..6a8fd7ef --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/inspections.liquid @@ -0,0 +1,43 @@ +{% comment %} + modules/accela_construct/queries/searches/inspections + Wraps: POST /v4/search/inspections (Accela "Search Inspections") + Distinct from `lib/queries/inspections/all` (GET /v4/inspections, plain + query-string filters) - this one takes a JSON search criteria body. + + Params: + criteria - Hash of search criteria (all fields Accela documents for + this endpoint are individually optional) + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + inspections/{build,check}.liquid) for consistency with every other query, + even though there's nothing to build here - the actual path/body + construction lives in the shared lib/accela_client/post_search.liquid - + and nothing to check, since every field Accela documents for this + endpoint is optional. + + Usage: + {% function result = 'modules/accela_construct/queries/searches/inspections', criteria: criteria %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "criteria": criteria, "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/searches/inspections/build', object: object + function object = 'modules/accela_construct/queries/searches/inspections/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/post_search', resource: 'inspections', criteria: object.criteria, offset: object.offset, limit: object.limit, expand: object.expand, fields: object.fields, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/searches/inspections' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/searches/inspections' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/inspections/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/inspections/build.liquid new file mode 100644 index 00000000..575d9dfd --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/inspections/build.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/inspections/build + + No-op for this endpoint - lib/accela_client/post_search.liquid builds + the actual request path/body itself from `object.criteria`/offset/limit/ + expand/fields. Present only for structural consistency with the + build/check split used across all queries. +{% endcomment %} + +{% liquid + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/inspections/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/inspections/check.liquid new file mode 100644 index 00000000..d42f42a5 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/inspections/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/inspections/check + No required params for this endpoint - every field Accela documents + for "Search Inspections" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/owners.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/owners.liquid new file mode 100644 index 00000000..be2817f2 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/owners.liquid @@ -0,0 +1,41 @@ +{% comment %} + modules/accela_construct/queries/searches/owners + Wraps: POST /v4/search/owners (Accela "Search Owners") + + Params: + criteria - Hash of search criteria (all fields Accela documents for + this endpoint are individually optional) + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + owners/{build,check}.liquid) for consistency with every other query, + even though there's nothing to build here - the actual path/body + construction lives in the shared lib/accela_client/post_search.liquid - + and nothing to check, since every field Accela documents for this + endpoint is optional. + + Usage: + {% function result = 'modules/accela_construct/queries/searches/owners', criteria: criteria %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "criteria": criteria, "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/searches/owners/build', object: object + function object = 'modules/accela_construct/queries/searches/owners/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/post_search', resource: 'owners', criteria: object.criteria, offset: object.offset, limit: object.limit, expand: object.expand, fields: object.fields, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/searches/owners' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/searches/owners' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/owners/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/owners/build.liquid new file mode 100644 index 00000000..c987df7c --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/owners/build.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/owners/build + + No-op for this endpoint - lib/accela_client/post_search.liquid builds + the actual request path/body itself from `object.criteria`/offset/limit/ + expand/fields. Present only for structural consistency with the + build/check split used across all queries. +{% endcomment %} + +{% liquid + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/owners/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/owners/check.liquid new file mode 100644 index 00000000..99e53601 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/owners/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/owners/check + No required params for this endpoint - every field Accela documents + for "Search Owners" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parcels.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parcels.liquid new file mode 100644 index 00000000..8f1e2cc0 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parcels.liquid @@ -0,0 +1,41 @@ +{% comment %} + modules/accela_construct/queries/searches/parcels + Wraps: POST /v4/search/parcels (Accela "Search Parcels") + + Params: + criteria - Hash of search criteria (all fields Accela documents for + this endpoint are individually optional) + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + parcels/{build,check}.liquid) for consistency with every other query, + even though there's nothing to build here - the actual path/body + construction lives in the shared lib/accela_client/post_search.liquid - + and nothing to check, since every field Accela documents for this + endpoint is optional. + + Usage: + {% function result = 'modules/accela_construct/queries/searches/parcels', criteria: criteria %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "criteria": criteria, "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/searches/parcels/build', object: object + function object = 'modules/accela_construct/queries/searches/parcels/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/post_search', resource: 'parcels', criteria: object.criteria, offset: object.offset, limit: object.limit, expand: object.expand, fields: object.fields, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/searches/parcels' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/searches/parcels' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parcels/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parcels/build.liquid new file mode 100644 index 00000000..9806ab09 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parcels/build.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/parcels/build + + No-op for this endpoint - lib/accela_client/post_search.liquid builds + the actual request path/body itself from `object.criteria`/offset/limit/ + expand/fields. Present only for structural consistency with the + build/check split used across all queries. +{% endcomment %} + +{% liquid + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parcels/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parcels/check.liquid new file mode 100644 index 00000000..40644931 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parcels/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/parcels/check + No required params for this endpoint - every field Accela documents + for "Search Parcels" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parts.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parts.liquid new file mode 100644 index 00000000..94111dc0 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parts.liquid @@ -0,0 +1,41 @@ +{% comment %} + modules/accela_construct/queries/searches/parts + Wraps: POST /v4/search/parts (Accela "Search Parts") + + Params: + criteria - Hash of search criteria (all fields Accela documents for + this endpoint are individually optional) + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + parts/{build,check}.liquid) for consistency with every other query, + even though there's nothing to build here - the actual path/body + construction lives in the shared lib/accela_client/post_search.liquid - + and nothing to check, since every field Accela documents for this + endpoint is optional. + + Usage: + {% function result = 'modules/accela_construct/queries/searches/parts', criteria: criteria %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "criteria": criteria, "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/searches/parts/build', object: object + function object = 'modules/accela_construct/queries/searches/parts/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/post_search', resource: 'parts', criteria: object.criteria, offset: object.offset, limit: object.limit, expand: object.expand, fields: object.fields, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/searches/parts' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/searches/parts' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parts/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parts/build.liquid new file mode 100644 index 00000000..05128fcb --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parts/build.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/parts/build + + No-op for this endpoint - lib/accela_client/post_search.liquid builds + the actual request path/body itself from `object.criteria`/offset/limit/ + expand/fields. Present only for structural consistency with the + build/check split used across all queries. +{% endcomment %} + +{% liquid + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parts/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parts/check.liquid new file mode 100644 index 00000000..c14d373f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/parts/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/parts/check + No required params for this endpoint - every field Accela documents + for "Search Parts" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/professionals.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/professionals.liquid new file mode 100644 index 00000000..bdf82a5f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/professionals.liquid @@ -0,0 +1,41 @@ +{% comment %} + modules/accela_construct/queries/searches/professionals + Wraps: POST /v4/search/professionals (Accela "Search Professionals") + + Params: + criteria - Hash of search criteria (all fields Accela documents for + this endpoint are individually optional) + offset - optional, default 0 + limit - optional, default 25 (Accela max 1000) + expand - optional comma-separated string + fields - optional comma-separated string to limit returned fields + with_retries - optional boolean, default false. When true, retries a + failed attempt in the background with increasing delay - + see lib/accela_client/send.liquid. + reference - optional hash `{ "id", "table" }` forwarded + to send.liquid - see send.liquid. + + Follows the pos-module-core build/check command pattern (see + professionals/{build,check}.liquid) for consistency with every other + query, even though there's nothing to build here - the actual path/body + construction lives in the shared lib/accela_client/post_search.liquid - + and nothing to check, since every field Accela documents for this + endpoint is optional. + + Usage: + {% function result = 'modules/accela_construct/queries/searches/professionals', criteria: criteria %} +{% endcomment %} + +{% liquid + assign object = { "errors": {}, "valid": true, "criteria": criteria, "offset": offset, "limit": limit, "expand": expand, "fields": fields } + function object = 'modules/accela_construct/queries/searches/professionals/build', object: object + function object = 'modules/accela_construct/queries/searches/professionals/check', object: object + + if object.valid + function result = 'modules/accela_construct/accela_client/post_search', resource: 'professionals', criteria: object.criteria, offset: object.offset, limit: object.limit, expand: object.expand, fields: object.fields, with_retries: with_retries, reference: reference, caller: 'modules/accela_construct/queries/searches/professionals' + else + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: object.errors, caller: 'modules/accela_construct/queries/searches/professionals' + endif + + return result +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/professionals/build.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/professionals/build.liquid new file mode 100644 index 00000000..3c592244 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/professionals/build.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/professionals/build + + No-op for this endpoint - lib/accela_client/post_search.liquid builds + the actual request path/body itself from `object.criteria`/offset/limit/ + expand/fields. Present only for structural consistency with the + build/check split used across all queries. +{% endcomment %} + +{% liquid + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/professionals/check.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/professionals/check.liquid new file mode 100644 index 00000000..196fa110 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/queries/searches/professionals/check.liquid @@ -0,0 +1,12 @@ +{% comment %} + modules/accela_construct/queries/searches/professionals/check + No required params for this endpoint - every field Accela documents + for "Search Professionals" is individually optional. Kept for structural + consistency with the build/check split used across all queries. +{% endcomment %} + +{% liquid + assign object.valid = true + assign object.errors = {} + return object +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/accela_client_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/accela_client_test.liquid new file mode 100644 index 00000000..9a897303 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/accela_client_test.liquid @@ -0,0 +1,49 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% liquid + # modules/accela_construct/accela_client/error_result + + function result = 'modules/accela_construct/accela_client/error_result', error: 'accela_something_failed' + function contract = 'modules/tests/assertions/not_true', contract: contract, value: result.success, field_name: 'error_result_without_errors_success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: result.status, expected: null, field_name: 'error_result_without_errors_status' + function contract = 'modules/tests/assertions/equal', contract: contract, given: result.error, expected: 'accela_something_failed', field_name: 'error_result_without_errors_message' + function contract = 'modules/tests/assertions/not_presence', contract: contract, object: result, field_name: 'errors' + + assign field_errors = { "record": ["cannot be blank"] } + function result_with_errors = 'modules/accela_construct/accela_client/error_result', error: 'accela_validation_failed', errors: field_errors + function contract = 'modules/tests/assertions/presence', contract: contract, object: result_with_errors, field_name: 'errors' + function contract = 'modules/tests/assertions/object_contains_object', contract: contract, given: result_with_errors, contains: { "success": false, "error": "accela_validation_failed" }, field_name: 'error_result_with_errors_shape' + function contract = 'modules/tests/assertions/equal', contract: contract, given: result_with_errors.errors.record.first, expected: 'cannot be blank', field_name: 'error_result_with_errors_content' + + # caller is log-only (see error_result.liquid's {% log %} call) - it + # never appears in the returned envelope, so this only asserts that + # passing it doesn't change the envelope shape, not that logging happened + function result_with_caller = 'modules/accela_construct/accela_client/error_result', error: 'accela_something_failed', caller: 'modules/accela_construct/queries/records/get' + function contract = 'modules/tests/assertions/equal', contract: contract, given: result_with_caller.error, expected: 'accela_something_failed', field_name: 'error_result_with_caller_unchanged_envelope' + function contract = 'modules/tests/assertions/not_presence', contract: contract, object: result_with_caller, field_name: 'caller' + + # modules/accela_construct/accela_client/build_query_string + + assign all_blank_params = { "offset": null, "fields": "" } + function qs_blank = 'modules/accela_construct/accela_client/build_query_string', params: all_blank_params + function contract = 'modules/tests/assertions/equal', contract: contract, given: qs_blank, expected: '', field_name: 'build_query_string_all_blank_returns_empty' + + assign single_param = { "offset": 0, "limit": null } + function qs_single = 'modules/accela_construct/accela_client/build_query_string', params: single_param + function contract = 'modules/tests/assertions/equal', contract: contract, given: qs_single, expected: 'offset=0', field_name: 'build_query_string_single_param_no_ampersand' + + assign multi_params = { "offset": 0, "limit": 25, "fields": null } + function qs_multi = 'modules/accela_construct/accela_client/build_query_string', params: multi_params + function contract = 'modules/tests/assertions/equal', contract: contract, given: qs_multi, expected: 'offset=0&limit=25', field_name: 'build_query_string_skips_blank_joins_present' + + # compares against the `url_encode` filter's own output rather than a + # hardcoded escape sequence, since the exact percent-encoding of spaces + # vs "+" isn't something this module asserts an opinion on elsewhere + assign raw_value = 'name,type description' + assign expected_encoded_value = raw_value | url_encode + assign encode_params = { "fields": raw_value } + function qs_encoded = 'modules/accela_construct/accela_client/build_query_string', params: encode_params + assign expected_qs = "fields={{ expected_encoded_value }}" + function contract = 'modules/tests/assertions/equal', contract: contract, given: qs_encoded, expected: expected_qs, field_name: 'build_query_string_url_encodes_values' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/documents_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/documents_test.liquid new file mode 100644 index 00000000..75b1cdd3 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/documents_test.liquid @@ -0,0 +1,47 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% liquid + # modules/accela_construct/commands/records/documents/upload + + assign upload_missing = { "errors": {}, "valid": true, "file_field": "binary-data", "file_name": "plan.pdf", "content_type": "application/pdf" } + function upload_missing = 'modules/accela_construct/commands/records/documents/upload/check', object: upload_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: upload_missing, field_name: 'documents_upload_check_invalid_without_record_id' + + assign upload_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "file_field": "binary-data", "file_name": "plan.pdf", "content_type": "application/pdf" } + function upload_ok = 'modules/accela_construct/commands/records/documents/upload/check', object: upload_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: upload_ok, field_name: 'documents_upload_check_valid_with_all_required' + + assign upload_build_input = { "record_id": "TEST-0000-00001", "file_field": "binary-data", "file_name": "plan.pdf", "content_type": "application/pdf", "category": "Plans" } + function upload_built = 'modules/accela_construct/commands/records/documents/upload/build', object: upload_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: upload_built.path, expected: '/records/TEST-0000-00001/documents', field_name: 'documents_upload_build_path' + function contract = 'modules/tests/assertions/presence', contract: contract, object: upload_built, field_name: 'file_info' + assign upload_file_info = upload_built.file_info | parse_json + function contract = 'modules/tests/assertions/equal', contract: contract, given: upload_file_info.size, expected: 1, field_name: 'documents_upload_build_file_info_is_single_item_array' + function contract = 'modules/tests/assertions/equal', contract: contract, given: upload_file_info.first.fileName, expected: 'plan.pdf', field_name: 'documents_upload_build_file_info_file_name' + function contract = 'modules/tests/assertions/equal', contract: contract, given: upload_file_info.first.type, expected: 'application/pdf', field_name: 'documents_upload_build_file_info_content_type' + function contract = 'modules/tests/assertions/equal', contract: contract, given: upload_file_info.first.category, expected: 'Plans', field_name: 'documents_upload_build_file_info_category' + + function upload_result = 'modules/accela_construct/commands/records/documents/upload', file_field: 'binary-data', file_name: 'plan.pdf', content_type: 'application/pdf' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: upload_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: upload_result.error, expected: 'accela_validation_failed', field_name: 'documents_upload_without_record_id_returns_validation_failed' + + # modules/accela_construct/commands/records/documents/delete + + assign delete_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function delete_missing = 'modules/accela_construct/commands/records/documents/delete/check', object: delete_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: delete_missing, field_name: 'documents_delete_check_invalid_without_document_ids' + + assign delete_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "document_ids": "9001" } + function delete_ok = 'modules/accela_construct/commands/records/documents/delete/check', object: delete_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: delete_ok, field_name: 'documents_delete_check_valid_with_all_required' + + assign delete_build_input = { "record_id": "TEST-0000-00001", "document_ids": "9001" } + function delete_built = 'modules/accela_construct/commands/records/documents/delete/build', object: delete_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: delete_built.path, expected: '/records/TEST-0000-00001/documents/9001', field_name: 'documents_delete_build_path' + function contract = 'modules/tests/assertions/not_presence', contract: contract, object: delete_built, field_name: 'payload' + + function delete_result = 'modules/accela_construct/commands/records/documents/delete', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: delete_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: delete_result.error, expected: 'accela_validation_failed', field_name: 'documents_delete_without_document_ids_returns_validation_failed' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/inspections_checklists_conditions_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/inspections_checklists_conditions_test.liquid new file mode 100644 index 00000000..ac0d778a --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/inspections_checklists_conditions_test.liquid @@ -0,0 +1,95 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% liquid + # modules/accela_construct/commands/inspections/checklists/create + + assign checklist_create_missing = { "errors": {}, "valid": true, "inspection_id": "1001" } + function checklist_create_missing = 'modules/accela_construct/commands/inspections/checklists/create/check', object: checklist_create_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: checklist_create_missing, field_name: 'inspections_checklists_create_check_invalid_without_checklist' + + assign checklist_create_ok = { "errors": {}, "valid": true, "inspection_id": "1001", "checklist": { "name": "Site Visit" } } + function checklist_create_ok = 'modules/accela_construct/commands/inspections/checklists/create/check', object: checklist_create_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: checklist_create_ok, field_name: 'inspections_checklists_create_check_valid_with_all_required' + + assign checklist_create_build_input = { "inspection_id": "1001", "checklist": { "name": "Site Visit" } } + function checklist_create_built = 'modules/accela_construct/commands/inspections/checklists/create/build', object: checklist_create_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: checklist_create_built.path, expected: '/inspections/1001/checklists', field_name: 'inspections_checklists_create_build_path' + function contract = 'modules/tests/assertions/presence', contract: contract, object: checklist_create_built, field_name: 'payload' + + function checklist_create_result = 'modules/accela_construct/commands/inspections/checklists/create', inspection_id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: checklist_create_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: checklist_create_result.error, expected: 'accela_validation_failed', field_name: 'inspections_checklists_create_without_checklist_returns_validation_failed' + + # modules/accela_construct/commands/inspections/checklists/delete + + assign checklist_delete_missing = { "errors": {}, "valid": true, "inspection_id": "1001" } + function checklist_delete_missing = 'modules/accela_construct/commands/inspections/checklists/delete/check', object: checklist_delete_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: checklist_delete_missing, field_name: 'inspections_checklists_delete_check_invalid_without_ids' + + assign checklist_delete_ok = { "errors": {}, "valid": true, "inspection_id": "1001", "ids": "3001" } + function checklist_delete_ok = 'modules/accela_construct/commands/inspections/checklists/delete/check', object: checklist_delete_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: checklist_delete_ok, field_name: 'inspections_checklists_delete_check_valid_with_all_required' + + assign checklist_delete_build_input = { "inspection_id": "1001", "ids": "3001" } + function checklist_delete_built = 'modules/accela_construct/commands/inspections/checklists/delete/build', object: checklist_delete_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: checklist_delete_built.path, expected: '/inspections/1001/checklists/3001', field_name: 'inspections_checklists_delete_build_path' + + function checklist_delete_result = 'modules/accela_construct/commands/inspections/checklists/delete', inspection_id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: checklist_delete_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: checklist_delete_result.error, expected: 'accela_validation_failed', field_name: 'inspections_checklists_delete_without_ids_returns_validation_failed' + + # modules/accela_construct/commands/inspections/conditions/create + + assign inspection_condition_create_missing = { "errors": {}, "valid": true, "inspection_id": "1001" } + function inspection_condition_create_missing = 'modules/accela_construct/commands/inspections/conditions/create/check', object: inspection_condition_create_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: inspection_condition_create_missing, field_name: 'inspections_conditions_create_check_invalid_without_condition' + + assign inspection_condition_create_ok = { "errors": {}, "valid": true, "inspection_id": "1001", "condition": { "description": "Must fix wiring" } } + function inspection_condition_create_ok = 'modules/accela_construct/commands/inspections/conditions/create/check', object: inspection_condition_create_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: inspection_condition_create_ok, field_name: 'inspections_conditions_create_check_valid_with_all_required' + + assign inspection_condition_create_build_input = { "inspection_id": "1001", "condition": { "description": "Must fix wiring" } } + function inspection_condition_create_built = 'modules/accela_construct/commands/inspections/conditions/create/build', object: inspection_condition_create_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspection_condition_create_built.path, expected: '/inspections/1001/conditions', field_name: 'inspections_conditions_create_build_path' + + function inspection_condition_create_result = 'modules/accela_construct/commands/inspections/conditions/create', inspection_id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: inspection_condition_create_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspection_condition_create_result.error, expected: 'accela_validation_failed', field_name: 'inspections_conditions_create_without_condition_returns_validation_failed' + + # modules/accela_construct/commands/inspections/conditions/update + + assign inspection_condition_update_missing = { "errors": {}, "valid": true, "inspection_id": "1001", "id": "5001" } + function inspection_condition_update_missing = 'modules/accela_construct/commands/inspections/conditions/update/check', object: inspection_condition_update_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: inspection_condition_update_missing, field_name: 'inspections_conditions_update_check_invalid_without_condition' + + assign inspection_condition_update_ok = { "errors": {}, "valid": true, "inspection_id": "1001", "id": "5001", "condition": { "description": "Fixed" } } + function inspection_condition_update_ok = 'modules/accela_construct/commands/inspections/conditions/update/check', object: inspection_condition_update_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: inspection_condition_update_ok, field_name: 'inspections_conditions_update_check_valid_with_all_required' + + assign inspection_condition_update_build_input = { "inspection_id": "1001", "id": "5001", "condition": { "description": "Fixed" } } + function inspection_condition_update_built = 'modules/accela_construct/commands/inspections/conditions/update/build', object: inspection_condition_update_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspection_condition_update_built.path, expected: '/inspections/1001/conditions/5001', field_name: 'inspections_conditions_update_build_path' + + function inspection_condition_update_result = 'modules/accela_construct/commands/inspections/conditions/update', inspection_id: '1001', id: '5001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: inspection_condition_update_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspection_condition_update_result.error, expected: 'accela_validation_failed', field_name: 'inspections_conditions_update_without_condition_returns_validation_failed' + + # modules/accela_construct/commands/inspections/conditions/delete + + assign inspection_condition_delete_missing = { "errors": {}, "valid": true, "inspection_id": "1001" } + function inspection_condition_delete_missing = 'modules/accela_construct/commands/inspections/conditions/delete/check', object: inspection_condition_delete_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: inspection_condition_delete_missing, field_name: 'inspections_conditions_delete_check_invalid_without_ids' + + assign inspection_condition_delete_ok = { "errors": {}, "valid": true, "inspection_id": "1001", "ids": "5001" } + function inspection_condition_delete_ok = 'modules/accela_construct/commands/inspections/conditions/delete/check', object: inspection_condition_delete_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: inspection_condition_delete_ok, field_name: 'inspections_conditions_delete_check_valid_with_all_required' + + assign inspection_condition_delete_build_input = { "inspection_id": "1001", "ids": "5001" } + function inspection_condition_delete_built = 'modules/accela_construct/commands/inspections/conditions/delete/build', object: inspection_condition_delete_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspection_condition_delete_built.path, expected: '/inspections/1001/conditions/5001', field_name: 'inspections_conditions_delete_build_path' + + function inspection_condition_delete_result = 'modules/accela_construct/commands/inspections/conditions/delete', inspection_id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: inspection_condition_delete_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspection_condition_delete_result.error, expected: 'accela_validation_failed', field_name: 'inspections_conditions_delete_without_ids_returns_validation_failed' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/inspections_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/inspections_test.liquid new file mode 100644 index 00000000..a28687c6 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/inspections_test.liquid @@ -0,0 +1,191 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% liquid + # modules/accela_construct/commands/inspections/schedule + + assign schedule_missing = { "errors": {}, "valid": true } + function schedule_missing = 'modules/accela_construct/commands/inspections/schedule/check', object: schedule_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: schedule_missing, field_name: 'inspections_schedule_check_invalid_without_inspection' + + assign schedule_ok = { "errors": {}, "valid": true, "inspection": { "inspectorId": "MINSPECTOR" } } + function schedule_ok = 'modules/accela_construct/commands/inspections/schedule/check', object: schedule_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: schedule_ok, field_name: 'inspections_schedule_check_valid_with_inspection' + + assign schedule_build_input = { "inspection": { "inspectorId": "MINSPECTOR", "type": { "id": 173 } } } + function schedule_built = 'modules/accela_construct/commands/inspections/schedule/build', object: schedule_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: schedule_built.path, expected: '/inspections/schedule', field_name: 'inspections_schedule_build_path' + assign schedule_payload = schedule_built.payload | parse_json + function contract = 'modules/tests/assertions/equal', contract: contract, given: schedule_payload.inspectorId, expected: 'MINSPECTOR', field_name: 'inspections_schedule_build_payload_content' + + function schedule_result = 'modules/accela_construct/commands/inspections/schedule', inspection: null + function contract = 'modules/tests/assertions/not_true', contract: contract, object: schedule_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: schedule_result.error, expected: 'accela_validation_failed', field_name: 'inspections_schedule_without_inspection_returns_validation_failed' + + # modules/accela_construct/commands/inspections/set_schedule + + assign set_schedule_missing = { "errors": {}, "valid": true, "inspection": { "scheduleDate": "2026-08-05" } } + function set_schedule_missing = 'modules/accela_construct/commands/inspections/set_schedule/check', object: set_schedule_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: set_schedule_missing, field_name: 'inspections_set_schedule_check_invalid_without_id' + + assign set_schedule_ok = { "errors": {}, "valid": true, "id": "1001", "inspection": { "scheduleDate": "2026-08-05" } } + function set_schedule_ok = 'modules/accela_construct/commands/inspections/set_schedule/check', object: set_schedule_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: set_schedule_ok, field_name: 'inspections_set_schedule_check_valid_with_all_required' + + assign set_schedule_build_input = { "id": "1001", "inspection": { "scheduleDate": "2026-08-05" } } + function set_schedule_built = 'modules/accela_construct/commands/inspections/set_schedule/build', object: set_schedule_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: set_schedule_built.path, expected: '/inspections/1001/schedule', field_name: 'inspections_set_schedule_build_path' + function contract = 'modules/tests/assertions/presence', contract: contract, object: set_schedule_built, field_name: 'payload' + + function set_schedule_result = 'modules/accela_construct/commands/inspections/set_schedule', inspection: { "scheduleDate": "2026-08-05" } + function contract = 'modules/tests/assertions/not_true', contract: contract, object: set_schedule_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: set_schedule_result.error, expected: 'accela_validation_failed', field_name: 'inspections_set_schedule_without_id_returns_validation_failed' + + # modules/accela_construct/commands/inspections/reschedule + + assign reschedule_missing = { "errors": {}, "valid": true, "id": "1001" } + function reschedule_missing = 'modules/accela_construct/commands/inspections/reschedule/check', object: reschedule_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: reschedule_missing, field_name: 'inspections_reschedule_check_invalid_without_changes' + + assign reschedule_ok = { "errors": {}, "valid": true, "id": "1001", "changes": { "scheduleDate": "2026-08-06" } } + function reschedule_ok = 'modules/accela_construct/commands/inspections/reschedule/check', object: reschedule_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: reschedule_ok, field_name: 'inspections_reschedule_check_valid_with_all_required' + + assign reschedule_build_input = { "id": "1001", "changes": { "scheduleDate": "2026-08-06" } } + function reschedule_built = 'modules/accela_construct/commands/inspections/reschedule/build', object: reschedule_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: reschedule_built.path, expected: '/inspections/1001/reschedule', field_name: 'inspections_reschedule_build_path' + + function reschedule_result = 'modules/accela_construct/commands/inspections/reschedule', id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: reschedule_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: reschedule_result.error, expected: 'accela_validation_failed', field_name: 'inspections_reschedule_without_changes_returns_validation_failed' + + # modules/accela_construct/commands/inspections/result + + assign result_missing = { "errors": {}, "valid": true, "id": "1001" } + function result_missing = 'modules/accela_construct/commands/inspections/result/check', object: result_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: result_missing, field_name: 'inspections_result_check_invalid_without_inspection_result' + + assign result_ok = { "errors": {}, "valid": true, "id": "1001", "inspection_result": { "status": { "value": "Passed" } } } + function result_ok = 'modules/accela_construct/commands/inspections/result/check', object: result_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: result_ok, field_name: 'inspections_result_check_valid_with_all_required' + + assign result_build_input = { "id": "1001", "inspection_result": { "status": { "value": "Passed" } } } + function result_built = 'modules/accela_construct/commands/inspections/result/build', object: result_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: result_built.path, expected: '/inspections/1001/result', field_name: 'inspections_result_build_path' + + function inspection_result_result = 'modules/accela_construct/commands/inspections/result', id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: inspection_result_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspection_result_result.error, expected: 'accela_validation_failed', field_name: 'inspections_result_without_inspection_result_returns_validation_failed' + + # modules/accela_construct/commands/inspections/update + + assign inspections_update_missing = { "errors": {}, "valid": true, "id": "1001" } + function inspections_update_missing = 'modules/accela_construct/commands/inspections/update/check', object: inspections_update_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: inspections_update_missing, field_name: 'inspections_update_check_invalid_without_inspection' + + assign inspections_update_ok = { "errors": {}, "valid": true, "id": "1001", "inspection": { "status": { "value": "Scheduled" } } } + function inspections_update_ok = 'modules/accela_construct/commands/inspections/update/check', object: inspections_update_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: inspections_update_ok, field_name: 'inspections_update_check_valid_with_all_required' + + assign inspections_update_build_input = { "id": "1001", "inspection": { "status": { "value": "Scheduled" } } } + function inspections_update_built = 'modules/accela_construct/commands/inspections/update/build', object: inspections_update_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspections_update_built.path, expected: '/inspections/1001', field_name: 'inspections_update_build_path' + + function inspections_update_result = 'modules/accela_construct/commands/inspections/update', id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: inspections_update_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspections_update_result.error, expected: 'accela_validation_failed', field_name: 'inspections_update_without_inspection_returns_validation_failed' + + # modules/accela_construct/commands/inspections/assign + + assign assign_missing = { "errors": {}, "valid": true, "ids": "1001" } + function assign_missing = 'modules/accela_construct/commands/inspections/assign/check', object: assign_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: assign_missing, field_name: 'inspections_assign_check_invalid_without_inspector_id' + + assign assign_ok = { "errors": {}, "valid": true, "ids": "1001", "inspector_id": "MINSPECTOR" } + function assign_ok = 'modules/accela_construct/commands/inspections/assign/check', object: assign_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: assign_ok, field_name: 'inspections_assign_check_valid_with_all_required' + + assign assign_build_input = { "ids": "1001", "inspector_id": "MINSPECTOR" } + function assign_built = 'modules/accela_construct/commands/inspections/assign/build', object: assign_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: assign_built.path, expected: '/inspections/1001/assign?inspectorId=MINSPECTOR', field_name: 'inspections_assign_build_path_includes_inspector_id_query_param' + function contract = 'modules/tests/assertions/not_presence', contract: contract, object: assign_built, field_name: 'payload' + + function assign_result = 'modules/accela_construct/commands/inspections/assign', ids: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: assign_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: assign_result.error, expected: 'accela_validation_failed', field_name: 'inspections_assign_without_inspector_id_returns_validation_failed' + + # modules/accela_construct/commands/inspections/cancel + + assign inspections_cancel_missing = { "errors": {}, "valid": true } + function inspections_cancel_missing = 'modules/accela_construct/commands/inspections/cancel/check', object: inspections_cancel_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: inspections_cancel_missing, field_name: 'inspections_cancel_check_invalid_without_ids' + + assign inspections_cancel_ok = { "errors": {}, "valid": true, "ids": "1001" } + function inspections_cancel_ok = 'modules/accela_construct/commands/inspections/cancel/check', object: inspections_cancel_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: inspections_cancel_ok, field_name: 'inspections_cancel_check_valid_with_ids' + + assign inspections_cancel_build_input = { "ids": "1001" } + function inspections_cancel_built = 'modules/accela_construct/commands/inspections/cancel/build', object: inspections_cancel_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspections_cancel_built.path, expected: '/inspections/1001/cancel', field_name: 'inspections_cancel_build_path' + + function inspections_cancel_result = 'modules/accela_construct/commands/inspections/cancel', ids: null + function contract = 'modules/tests/assertions/not_true', contract: contract, object: inspections_cancel_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspections_cancel_result.error, expected: 'accela_validation_failed', field_name: 'inspections_cancel_without_ids_returns_validation_failed' + + # modules/accela_construct/commands/inspections/delete + + assign inspections_delete_missing = { "errors": {}, "valid": true } + function inspections_delete_missing = 'modules/accela_construct/commands/inspections/delete/check', object: inspections_delete_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: inspections_delete_missing, field_name: 'inspections_delete_check_invalid_without_ids' + + assign inspections_delete_ok = { "errors": {}, "valid": true, "ids": "1001" } + function inspections_delete_ok = 'modules/accela_construct/commands/inspections/delete/check', object: inspections_delete_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: inspections_delete_ok, field_name: 'inspections_delete_check_valid_with_ids' + + assign inspections_delete_build_input = { "ids": "1001" } + function inspections_delete_built = 'modules/accela_construct/commands/inspections/delete/build', object: inspections_delete_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspections_delete_built.path, expected: '/inspections/1001', field_name: 'inspections_delete_build_path' + + function inspections_delete_result = 'modules/accela_construct/commands/inspections/delete', ids: null + function contract = 'modules/tests/assertions/not_true', contract: contract, object: inspections_delete_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: inspections_delete_result.error, expected: 'accela_validation_failed', field_name: 'inspections_delete_without_ids_returns_validation_failed' + + # modules/accela_construct/commands/inspections/related/create + + assign related_create_missing = { "errors": {}, "valid": true, "id": "1001" } + function related_create_missing = 'modules/accela_construct/commands/inspections/related/create/check', object: related_create_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: related_create_missing, field_name: 'inspections_related_create_check_invalid_without_related_inspection_ids' + + assign related_create_ok = { "errors": {}, "valid": true, "id": "1001", "related_inspection_ids": "2001,2002" } + function related_create_ok = 'modules/accela_construct/commands/inspections/related/create/check', object: related_create_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: related_create_ok, field_name: 'inspections_related_create_check_valid_with_all_required' + + assign related_create_build_input = { "id": "1001", "related_inspection_ids": "2001,2002" } + function related_create_built = 'modules/accela_construct/commands/inspections/related/create/build', object: related_create_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_create_built.path, expected: '/inspections/1001/related', field_name: 'inspections_related_create_build_path' + assign related_create_payload = related_create_built.payload | parse_json + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_create_payload.relatedInspectionIds.size, expected: 2, field_name: 'inspections_related_create_build_payload_array_size' + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_create_payload.relatedInspectionIds.first, expected: '2001', field_name: 'inspections_related_create_build_payload_first_id' + + function related_create_result = 'modules/accela_construct/commands/inspections/related/create', id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: related_create_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_create_result.error, expected: 'accela_validation_failed', field_name: 'inspections_related_create_without_related_inspection_ids_returns_validation_failed' + + # modules/accela_construct/commands/inspections/related/delete + + assign related_delete_missing = { "errors": {}, "valid": true, "id": "1001" } + function related_delete_missing = 'modules/accela_construct/commands/inspections/related/delete/check', object: related_delete_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: related_delete_missing, field_name: 'inspections_related_delete_check_invalid_without_child_ids' + + assign related_delete_ok = { "errors": {}, "valid": true, "id": "1001", "child_ids": "2001" } + function related_delete_ok = 'modules/accela_construct/commands/inspections/related/delete/check', object: related_delete_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: related_delete_ok, field_name: 'inspections_related_delete_check_valid_with_all_required' + + assign related_delete_build_input = { "id": "1001", "child_ids": "2001" } + function related_delete_built = 'modules/accela_construct/commands/inspections/related/delete/build', object: related_delete_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_delete_built.path, expected: '/inspections/1001/related/2001', field_name: 'inspections_related_delete_build_path' + + function related_delete_result = 'modules/accela_construct/commands/inspections/related/delete', id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: related_delete_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_delete_result.error, expected: 'accela_validation_failed', field_name: 'inspections_related_delete_without_child_ids_returns_validation_failed' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/records_conditions_workflow_tasks_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/records_conditions_workflow_tasks_test.liquid new file mode 100644 index 00000000..049cca0f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/records_conditions_workflow_tasks_test.liquid @@ -0,0 +1,82 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% liquid + # Only build.liquid/check.liquid are called directly, plus each + # orchestrator's validation-FAILURE path (missing a required param, which + # short-circuits before any network call) - never a full success call. + + # ============ records/conditions/{create,update,delete} ============ + + assign conditions_create_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function conditions_create_check_missing = 'modules/accela_construct/commands/records/conditions/create/check', object: conditions_create_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: conditions_create_check_missing, field_name: 'records_conditions_create_check_invalid_without_condition' + + assign conditions_create_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "condition": { "type": { "value": "Standard" } } } + function conditions_create_check_ok = 'modules/accela_construct/commands/records/conditions/create/check', object: conditions_create_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: conditions_create_check_ok, field_name: 'records_conditions_create_check_valid_with_condition' + + assign conditions_create_build_input = { "record_id": "TEST-0000-00001", "condition": { "type": { "value": "Standard" } } } + function conditions_create_build_output = 'modules/accela_construct/commands/records/conditions/create/build', object: conditions_create_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: conditions_create_build_output.path, expected: '/records/TEST-0000-00001/conditions', field_name: 'records_conditions_create_build_path' + function contract = 'modules/tests/assertions/presence', contract: contract, object: conditions_create_build_output, field_name: 'payload' + + function conditions_create_result = 'modules/accela_construct/commands/records/conditions/create', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: conditions_create_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: conditions_create_result.error, expected: 'accela_validation_failed', field_name: 'records_conditions_create_returns_validation_failed_without_condition' + + assign conditions_update_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "id": "1" } + function conditions_update_check_missing = 'modules/accela_construct/commands/records/conditions/update/check', object: conditions_update_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: conditions_update_check_missing, field_name: 'records_conditions_update_check_invalid_without_condition' + + assign conditions_update_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "id": "1", "condition": { "status": { "value": "Cleared" } } } + function conditions_update_check_ok = 'modules/accela_construct/commands/records/conditions/update/check', object: conditions_update_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: conditions_update_check_ok, field_name: 'records_conditions_update_check_valid_with_condition' + + assign conditions_update_build_input = { "record_id": "TEST-0000-00001", "id": "1", "condition": { "status": { "value": "Cleared" } } } + function conditions_update_build_output = 'modules/accela_construct/commands/records/conditions/update/build', object: conditions_update_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: conditions_update_build_output.path, expected: '/records/TEST-0000-00001/conditions/1', field_name: 'records_conditions_update_build_path' + + function conditions_update_result = 'modules/accela_construct/commands/records/conditions/update', record_id: 'TEST-0000-00001', id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: conditions_update_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: conditions_update_result.error, expected: 'accela_validation_failed', field_name: 'records_conditions_update_returns_validation_failed_without_condition' + + assign conditions_delete_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function conditions_delete_check_missing = 'modules/accela_construct/commands/records/conditions/delete/check', object: conditions_delete_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: conditions_delete_check_missing, field_name: 'records_conditions_delete_check_invalid_without_ids' + + assign conditions_delete_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "ids": "1" } + function conditions_delete_check_ok = 'modules/accela_construct/commands/records/conditions/delete/check', object: conditions_delete_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: conditions_delete_check_ok, field_name: 'records_conditions_delete_check_valid_with_ids' + + assign conditions_delete_build_input = { "record_id": "TEST-0000-00001", "ids": "1,2" } + function conditions_delete_build_output = 'modules/accela_construct/commands/records/conditions/delete/build', object: conditions_delete_build_input + # build.liquid url_encodes the ids, so compare against url_encode's own + # output rather than assuming the comma stays literal + assign conditions_delete_expected_ids = conditions_delete_build_input.ids | url_encode + assign conditions_delete_expected_path = "/records/TEST-0000-00001/conditions/{{ conditions_delete_expected_ids }}" + function contract = 'modules/tests/assertions/equal', contract: contract, given: conditions_delete_build_output.path, expected: conditions_delete_expected_path, field_name: 'records_conditions_delete_build_path' + + function conditions_delete_result = 'modules/accela_construct/commands/records/conditions/delete', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: conditions_delete_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: conditions_delete_result.error, expected: 'accela_validation_failed', field_name: 'records_conditions_delete_returns_validation_failed_without_ids' + + # ============ records/workflow_tasks/update ============ + + assign workflow_tasks_update_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "id": "1" } + function workflow_tasks_update_check_missing = 'modules/accela_construct/commands/records/workflow_tasks/update/check', object: workflow_tasks_update_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: workflow_tasks_update_check_missing, field_name: 'records_workflow_tasks_update_check_invalid_without_task' + + assign workflow_tasks_update_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "id": "1", "task": { "status": { "value": "Approved" } } } + function workflow_tasks_update_check_ok = 'modules/accela_construct/commands/records/workflow_tasks/update/check', object: workflow_tasks_update_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: workflow_tasks_update_check_ok, field_name: 'records_workflow_tasks_update_check_valid_with_task' + + assign workflow_tasks_update_build_input = { "record_id": "TEST-0000-00001", "id": "1", "task": { "status": { "value": "Approved" } } } + function workflow_tasks_update_build_output = 'modules/accela_construct/commands/records/workflow_tasks/update/build', object: workflow_tasks_update_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: workflow_tasks_update_build_output.path, expected: '/records/TEST-0000-00001/workflowTasks/1', field_name: 'records_workflow_tasks_update_build_path' + function contract = 'modules/tests/assertions/presence', contract: contract, object: workflow_tasks_update_build_output, field_name: 'payload' + + function workflow_tasks_update_result = 'modules/accela_construct/commands/records/workflow_tasks/update', record_id: 'TEST-0000-00001', id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: workflow_tasks_update_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: workflow_tasks_update_result.error, expected: 'accela_validation_failed', field_name: 'records_workflow_tasks_update_returns_validation_failed_without_task' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/records_parcels_owners_addresses_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/records_parcels_owners_addresses_test.liquid new file mode 100644 index 00000000..3aab95ab --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/records_parcels_owners_addresses_test.liquid @@ -0,0 +1,176 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% liquid + # records/{parcels,owners,addresses}/{create,update,delete} all share an + # identical shape (record_id + [+ id for update/delete]), so + # this file exercises all 9 commands with the same pattern per resource. + # Only build.liquid/check.liquid are called directly, plus each + # orchestrator's validation-FAILURE path (missing a required param, which + # short-circuits before any network call) - never a full success call. + + # ============ parcels (body param: parcel) ============ + + assign parcels_create_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function parcels_create_check_missing = 'modules/accela_construct/commands/records/parcels/create/check', object: parcels_create_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: parcels_create_check_missing, field_name: 'records_parcels_create_check_invalid_without_parcel' + + assign parcels_create_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "parcel": { "parcelNumber": "005020018" } } + function parcels_create_check_ok = 'modules/accela_construct/commands/records/parcels/create/check', object: parcels_create_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: parcels_create_check_ok, field_name: 'records_parcels_create_check_valid_with_parcel' + + assign parcels_create_build_input = { "record_id": "TEST-0000-00001", "parcel": { "parcelNumber": "005020018" } } + function parcels_create_build_output = 'modules/accela_construct/commands/records/parcels/create/build', object: parcels_create_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: parcels_create_build_output.path, expected: '/records/TEST-0000-00001/parcels', field_name: 'records_parcels_create_build_path' + function contract = 'modules/tests/assertions/presence', contract: contract, object: parcels_create_build_output, field_name: 'payload' + + function parcels_create_result = 'modules/accela_construct/commands/records/parcels/create', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: parcels_create_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: parcels_create_result.error, expected: 'accela_validation_failed', field_name: 'records_parcels_create_returns_validation_failed_without_parcel' + + assign parcels_update_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "id": "1" } + function parcels_update_check_missing = 'modules/accela_construct/commands/records/parcels/update/check', object: parcels_update_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: parcels_update_check_missing, field_name: 'records_parcels_update_check_invalid_without_parcel' + + assign parcels_update_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "id": "1", "parcel": { "isPrimary": "Y" } } + function parcels_update_check_ok = 'modules/accela_construct/commands/records/parcels/update/check', object: parcels_update_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: parcels_update_check_ok, field_name: 'records_parcels_update_check_valid_with_parcel' + + assign parcels_update_build_input = { "record_id": "TEST-0000-00001", "id": "1", "parcel": { "isPrimary": "Y" } } + function parcels_update_build_output = 'modules/accela_construct/commands/records/parcels/update/build', object: parcels_update_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: parcels_update_build_output.path, expected: '/records/TEST-0000-00001/parcels/1', field_name: 'records_parcels_update_build_path' + + function parcels_update_result = 'modules/accela_construct/commands/records/parcels/update', record_id: 'TEST-0000-00001', id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: parcels_update_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: parcels_update_result.error, expected: 'accela_validation_failed', field_name: 'records_parcels_update_returns_validation_failed_without_parcel' + + assign parcels_delete_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function parcels_delete_check_missing = 'modules/accela_construct/commands/records/parcels/delete/check', object: parcels_delete_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: parcels_delete_check_missing, field_name: 'records_parcels_delete_check_invalid_without_ids' + + assign parcels_delete_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "ids": "1" } + function parcels_delete_check_ok = 'modules/accela_construct/commands/records/parcels/delete/check', object: parcels_delete_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: parcels_delete_check_ok, field_name: 'records_parcels_delete_check_valid_with_ids' + + assign parcels_delete_build_input = { "record_id": "TEST-0000-00001", "ids": "1,2" } + function parcels_delete_build_output = 'modules/accela_construct/commands/records/parcels/delete/build', object: parcels_delete_build_input + # build.liquid url_encodes the ids, so compare against url_encode's own + # output rather than assuming the comma stays literal + assign parcels_delete_expected_ids = parcels_delete_build_input.ids | url_encode + assign parcels_delete_expected_path = "/records/TEST-0000-00001/parcels/{{ parcels_delete_expected_ids }}" + function contract = 'modules/tests/assertions/equal', contract: contract, given: parcels_delete_build_output.path, expected: parcels_delete_expected_path, field_name: 'records_parcels_delete_build_path' + + function parcels_delete_result = 'modules/accela_construct/commands/records/parcels/delete', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: parcels_delete_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: parcels_delete_result.error, expected: 'accela_validation_failed', field_name: 'records_parcels_delete_returns_validation_failed_without_ids' + + # ============ owners (body param: owner) ============ + + assign owners_create_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function owners_create_check_missing = 'modules/accela_construct/commands/records/owners/create/check', object: owners_create_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: owners_create_check_missing, field_name: 'records_owners_create_check_invalid_without_owner' + + assign owners_create_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "owner": { "lastName": "Smith" } } + function owners_create_check_ok = 'modules/accela_construct/commands/records/owners/create/check', object: owners_create_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: owners_create_check_ok, field_name: 'records_owners_create_check_valid_with_owner' + + assign owners_create_build_input = { "record_id": "TEST-0000-00001", "owner": { "lastName": "Smith" } } + function owners_create_build_output = 'modules/accela_construct/commands/records/owners/create/build', object: owners_create_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: owners_create_build_output.path, expected: '/records/TEST-0000-00001/owners', field_name: 'records_owners_create_build_path' + function contract = 'modules/tests/assertions/presence', contract: contract, object: owners_create_build_output, field_name: 'payload' + + function owners_create_result = 'modules/accela_construct/commands/records/owners/create', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: owners_create_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: owners_create_result.error, expected: 'accela_validation_failed', field_name: 'records_owners_create_returns_validation_failed_without_owner' + + assign owners_update_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "id": "1" } + function owners_update_check_missing = 'modules/accela_construct/commands/records/owners/update/check', object: owners_update_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: owners_update_check_missing, field_name: 'records_owners_update_check_invalid_without_owner' + + assign owners_update_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "id": "1", "owner": { "isPrimary": "Y" } } + function owners_update_check_ok = 'modules/accela_construct/commands/records/owners/update/check', object: owners_update_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: owners_update_check_ok, field_name: 'records_owners_update_check_valid_with_owner' + + assign owners_update_build_input = { "record_id": "TEST-0000-00001", "id": "1", "owner": { "isPrimary": "Y" } } + function owners_update_build_output = 'modules/accela_construct/commands/records/owners/update/build', object: owners_update_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: owners_update_build_output.path, expected: '/records/TEST-0000-00001/owners/1', field_name: 'records_owners_update_build_path' + + function owners_update_result = 'modules/accela_construct/commands/records/owners/update', record_id: 'TEST-0000-00001', id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: owners_update_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: owners_update_result.error, expected: 'accela_validation_failed', field_name: 'records_owners_update_returns_validation_failed_without_owner' + + assign owners_delete_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function owners_delete_check_missing = 'modules/accela_construct/commands/records/owners/delete/check', object: owners_delete_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: owners_delete_check_missing, field_name: 'records_owners_delete_check_invalid_without_ids' + + assign owners_delete_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "ids": "1" } + function owners_delete_check_ok = 'modules/accela_construct/commands/records/owners/delete/check', object: owners_delete_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: owners_delete_check_ok, field_name: 'records_owners_delete_check_valid_with_ids' + + assign owners_delete_build_input = { "record_id": "TEST-0000-00001", "ids": "1,2" } + function owners_delete_build_output = 'modules/accela_construct/commands/records/owners/delete/build', object: owners_delete_build_input + # build.liquid url_encodes the ids, so compare against url_encode's own + # output rather than assuming the comma stays literal + assign owners_delete_expected_ids = owners_delete_build_input.ids | url_encode + assign owners_delete_expected_path = "/records/TEST-0000-00001/owners/{{ owners_delete_expected_ids }}" + function contract = 'modules/tests/assertions/equal', contract: contract, given: owners_delete_build_output.path, expected: owners_delete_expected_path, field_name: 'records_owners_delete_build_path' + + function owners_delete_result = 'modules/accela_construct/commands/records/owners/delete', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: owners_delete_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: owners_delete_result.error, expected: 'accela_validation_failed', field_name: 'records_owners_delete_returns_validation_failed_without_ids' + + # ============ addresses (body param: address) ============ + + assign addresses_create_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function addresses_create_check_missing = 'modules/accela_construct/commands/records/addresses/create/check', object: addresses_create_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: addresses_create_check_missing, field_name: 'records_addresses_create_check_invalid_without_address' + + assign addresses_create_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "address": { "streetName": "Main St" } } + function addresses_create_check_ok = 'modules/accela_construct/commands/records/addresses/create/check', object: addresses_create_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: addresses_create_check_ok, field_name: 'records_addresses_create_check_valid_with_address' + + assign addresses_create_build_input = { "record_id": "TEST-0000-00001", "address": { "streetName": "Main St" } } + function addresses_create_build_output = 'modules/accela_construct/commands/records/addresses/create/build', object: addresses_create_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: addresses_create_build_output.path, expected: '/records/TEST-0000-00001/addresses', field_name: 'records_addresses_create_build_path' + function contract = 'modules/tests/assertions/presence', contract: contract, object: addresses_create_build_output, field_name: 'payload' + + function addresses_create_result = 'modules/accela_construct/commands/records/addresses/create', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: addresses_create_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: addresses_create_result.error, expected: 'accela_validation_failed', field_name: 'records_addresses_create_returns_validation_failed_without_address' + + assign addresses_update_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "id": "1" } + function addresses_update_check_missing = 'modules/accela_construct/commands/records/addresses/update/check', object: addresses_update_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: addresses_update_check_missing, field_name: 'records_addresses_update_check_invalid_without_address' + + assign addresses_update_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "id": "1", "address": { "city": "Pleasanton" } } + function addresses_update_check_ok = 'modules/accela_construct/commands/records/addresses/update/check', object: addresses_update_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: addresses_update_check_ok, field_name: 'records_addresses_update_check_valid_with_address' + + assign addresses_update_build_input = { "record_id": "TEST-0000-00001", "id": "1", "address": { "city": "Pleasanton" } } + function addresses_update_build_output = 'modules/accela_construct/commands/records/addresses/update/build', object: addresses_update_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: addresses_update_build_output.path, expected: '/records/TEST-0000-00001/addresses/1', field_name: 'records_addresses_update_build_path' + + function addresses_update_result = 'modules/accela_construct/commands/records/addresses/update', record_id: 'TEST-0000-00001', id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: addresses_update_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: addresses_update_result.error, expected: 'accela_validation_failed', field_name: 'records_addresses_update_returns_validation_failed_without_address' + + assign addresses_delete_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function addresses_delete_check_missing = 'modules/accela_construct/commands/records/addresses/delete/check', object: addresses_delete_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: addresses_delete_check_missing, field_name: 'records_addresses_delete_check_invalid_without_ids' + + assign addresses_delete_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "ids": "1" } + function addresses_delete_check_ok = 'modules/accela_construct/commands/records/addresses/delete/check', object: addresses_delete_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: addresses_delete_check_ok, field_name: 'records_addresses_delete_check_valid_with_ids' + + assign addresses_delete_build_input = { "record_id": "TEST-0000-00001", "ids": "1,2" } + function addresses_delete_build_output = 'modules/accela_construct/commands/records/addresses/delete/build', object: addresses_delete_build_input + # build.liquid url_encodes the ids, so compare against url_encode's own + # output rather than assuming the comma stays literal + assign addresses_delete_expected_ids = addresses_delete_build_input.ids | url_encode + assign addresses_delete_expected_path = "/records/TEST-0000-00001/addresses/{{ addresses_delete_expected_ids }}" + function contract = 'modules/tests/assertions/equal', contract: contract, given: addresses_delete_build_output.path, expected: addresses_delete_expected_path, field_name: 'records_addresses_delete_build_path' + + function addresses_delete_result = 'modules/accela_construct/commands/records/addresses/delete', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: addresses_delete_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: addresses_delete_result.error, expected: 'accela_validation_failed', field_name: 'records_addresses_delete_returns_validation_failed_without_ids' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/records_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/records_test.liquid new file mode 100644 index 00000000..59d833fc --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/commands/records_test.liquid @@ -0,0 +1,204 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% liquid + # These tests only exercise build.liquid/check.liquid directly, plus each + # orchestrator's validation-FAILURE path (missing a required param, which + # short-circuits before any network call). They never call an orchestrator + # with complete/valid params, since that would attempt a real HTTP request + # to Accela. + + # --- records/create --- + + assign create_check_missing = { "errors": {}, "valid": true } + function create_check_missing = 'modules/accela_construct/commands/records/create/check', object: create_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: create_check_missing, field_name: 'records_create_check_invalid_without_record' + + assign create_check_ok = { "errors": {}, "valid": true, "record": { "type": { "id": "Building-Residential-Alteration-NA" } } } + function create_check_ok = 'modules/accela_construct/commands/records/create/check', object: create_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: create_check_ok, field_name: 'records_create_check_valid_with_record' + + assign create_build_input = { "record": { "type": { "id": "Building-Residential-Alteration-NA" } } } + function create_build_output = 'modules/accela_construct/commands/records/create/build', object: create_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: create_build_output.path, expected: '/records', field_name: 'records_create_build_path' + function contract = 'modules/tests/assertions/presence', contract: contract, object: create_build_output, field_name: 'payload' + + function create_result = 'modules/accela_construct/commands/records/create' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: create_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: create_result.error, expected: 'accela_validation_failed', field_name: 'records_create_returns_validation_failed_without_record' + + # --- records/update --- + + assign update_check_missing = { "errors": {}, "valid": true, "id": "TEST-0000-00001" } + function update_check_missing = 'modules/accela_construct/commands/records/update/check', object: update_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: update_check_missing, field_name: 'records_update_check_invalid_without_record' + + assign update_check_ok = { "errors": {}, "valid": true, "id": "TEST-0000-00001", "record": { "description": "x" } } + function update_check_ok = 'modules/accela_construct/commands/records/update/check', object: update_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: update_check_ok, field_name: 'records_update_check_valid_with_record' + + assign update_build_input = { "id": "TEST-0000-00001", "record": { "description": "x" } } + function update_build_output = 'modules/accela_construct/commands/records/update/build', object: update_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: update_build_output.path, expected: '/records/TEST-0000-00001', field_name: 'records_update_build_path' + function contract = 'modules/tests/assertions/presence', contract: contract, object: update_build_output, field_name: 'payload' + + function update_result = 'modules/accela_construct/commands/records/update', id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: update_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: update_result.error, expected: 'accela_validation_failed', field_name: 'records_update_returns_validation_failed_without_record' + + # --- records/initialize --- + + assign initialize_check_missing = { "errors": {}, "valid": true } + function initialize_check_missing = 'modules/accela_construct/commands/records/initialize/check', object: initialize_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: initialize_check_missing, field_name: 'records_initialize_check_invalid_without_record' + + assign initialize_check_ok = { "errors": {}, "valid": true, "record": { "type": { "id": "Building-Residential-Alteration-NA" } } } + function initialize_check_ok = 'modules/accela_construct/commands/records/initialize/check', object: initialize_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: initialize_check_ok, field_name: 'records_initialize_check_valid_with_record' + + assign initialize_build_input = { "record": { "type": { "id": "Building-Residential-Alteration-NA" } } } + function initialize_build_output = 'modules/accela_construct/commands/records/initialize/build', object: initialize_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: initialize_build_output.path, expected: '/records/initialize', field_name: 'records_initialize_build_path' + + function initialize_result = 'modules/accela_construct/commands/records/initialize' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: initialize_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: initialize_result.error, expected: 'accela_validation_failed', field_name: 'records_initialize_returns_validation_failed_without_record' + + # --- records/delete --- + + assign delete_check_missing = { "errors": {}, "valid": true } + function delete_check_missing = 'modules/accela_construct/commands/records/delete/check', object: delete_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: delete_check_missing, field_name: 'records_delete_check_invalid_without_ids' + + assign delete_check_ok = { "errors": {}, "valid": true, "ids": "TEST-0000-00001" } + function delete_check_ok = 'modules/accela_construct/commands/records/delete/check', object: delete_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: delete_check_ok, field_name: 'records_delete_check_valid_with_ids' + + assign delete_build_input = { "ids": "TEST-0000-00001,TEST-0000-00002" } + function delete_build_output = 'modules/accela_construct/commands/records/delete/build', object: delete_build_input + # build.liquid url_encodes the ids, so compare against url_encode's own + # output rather than assuming the comma stays literal + assign delete_expected_ids = delete_build_input.ids | url_encode + assign delete_expected_path = "/records/{{ delete_expected_ids }}" + function contract = 'modules/tests/assertions/equal', contract: contract, given: delete_build_output.path, expected: delete_expected_path, field_name: 'records_delete_build_path' + + function delete_result = 'modules/accela_construct/commands/records/delete' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: delete_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: delete_result.error, expected: 'accela_validation_failed', field_name: 'records_delete_returns_validation_failed_without_ids' + + # --- records/finalize (no payload) --- + + assign finalize_check_missing = { "errors": {}, "valid": true } + function finalize_check_missing = 'modules/accela_construct/commands/records/finalize/check', object: finalize_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: finalize_check_missing, field_name: 'records_finalize_check_invalid_without_record_id' + + assign finalize_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function finalize_check_ok = 'modules/accela_construct/commands/records/finalize/check', object: finalize_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: finalize_check_ok, field_name: 'records_finalize_check_valid_with_record_id' + + assign finalize_build_input = { "record_id": "TEST-0000-00001" } + function finalize_build_output = 'modules/accela_construct/commands/records/finalize/build', object: finalize_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: finalize_build_output.path, expected: '/records/TEST-0000-00001/finalize', field_name: 'records_finalize_build_path' + + function finalize_result = 'modules/accela_construct/commands/records/finalize' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: finalize_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: finalize_result.error, expected: 'accela_validation_failed', field_name: 'records_finalize_returns_validation_failed_without_record_id' + + # --- records/additional/update (build.liquid merges recordId into the payload) --- + + assign additional_check_missing = { "errors": {}, "valid": true } + function additional_check_missing = 'modules/accela_construct/commands/records/additional/update/check', object: additional_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: additional_check_missing, field_name: 'records_additional_update_check_invalid_without_record_id' + + assign additional_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function additional_check_ok = 'modules/accela_construct/commands/records/additional/update/check', object: additional_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: additional_check_ok, field_name: 'records_additional_update_check_valid_with_record_id' + + assign additional_build_input = { "record_id": "TEST-0000-00001", "additional": { "buildingCount": 2 } } + function additional_build_output = 'modules/accela_construct/commands/records/additional/update/build', object: additional_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: additional_build_output.path, expected: '/records/TEST-0000-00001/additional', field_name: 'records_additional_update_build_path' + assign additional_build_payload = additional_build_output.payload | parse_json + function contract = 'modules/tests/assertions/equal', contract: contract, given: additional_build_payload.recordId, expected: 'TEST-0000-00001', field_name: 'records_additional_update_build_merges_record_id_into_payload' + function contract = 'modules/tests/assertions/equal', contract: contract, given: additional_build_payload.buildingCount, expected: 2, field_name: 'records_additional_update_build_keeps_additional_fields' + + function additional_result = 'modules/accela_construct/commands/records/additional/update' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: additional_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: additional_result.error, expected: 'accela_validation_failed', field_name: 'records_additional_update_returns_validation_failed_without_record_id' + + # --- records/votes/create (optional body, defaults to {}) --- + + assign votes_check_missing = { "errors": {}, "valid": true } + function votes_check_missing = 'modules/accela_construct/commands/records/votes/create/check', object: votes_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: votes_check_missing, field_name: 'records_votes_create_check_invalid_without_record_id' + + assign votes_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function votes_check_ok = 'modules/accela_construct/commands/records/votes/create/check', object: votes_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: votes_check_ok, field_name: 'records_votes_create_check_valid_with_record_id' + + assign votes_build_input = { "record_id": "TEST-0000-00001" } + function votes_build_output = 'modules/accela_construct/commands/records/votes/create/build', object: votes_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: votes_build_output.path, expected: '/records/TEST-0000-00001/votes', field_name: 'records_votes_create_build_path' + function contract = 'modules/tests/assertions/equal', contract: contract, given: votes_build_output.payload, expected: '{}', field_name: 'records_votes_create_build_defaults_payload_to_empty_object' + + function votes_result = 'modules/accela_construct/commands/records/votes/create' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: votes_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: votes_result.error, expected: 'accela_validation_failed', field_name: 'records_votes_create_returns_validation_failed_without_record_id' + + # --- records/usercomments/create (deprecated by Accela; optional body, defaults to {}) --- + + assign usercomments_check_missing = { "errors": {}, "valid": true } + function usercomments_check_missing = 'modules/accela_construct/commands/records/usercomments/create/check', object: usercomments_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: usercomments_check_missing, field_name: 'records_usercomments_create_check_invalid_without_record_id' + + assign usercomments_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function usercomments_check_ok = 'modules/accela_construct/commands/records/usercomments/create/check', object: usercomments_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: usercomments_check_ok, field_name: 'records_usercomments_create_check_valid_with_record_id' + + assign usercomments_build_input = { "record_id": "TEST-0000-00001" } + function usercomments_build_output = 'modules/accela_construct/commands/records/usercomments/create/build', object: usercomments_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: usercomments_build_output.path, expected: '/records/TEST-0000-00001/usercomments', field_name: 'records_usercomments_create_build_path' + function contract = 'modules/tests/assertions/equal', contract: contract, given: usercomments_build_output.payload, expected: '{}', field_name: 'records_usercomments_create_build_defaults_payload_to_empty_object' + + function usercomments_result = 'modules/accela_construct/commands/records/usercomments/create' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: usercomments_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: usercomments_result.error, expected: 'accela_validation_failed', field_name: 'records_usercomments_create_returns_validation_failed_without_record_id' + + # --- records/related/create (related_record_ids is genuinely Accela-required) --- + + assign related_create_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function related_create_check_missing = 'modules/accela_construct/commands/records/related/create/check', object: related_create_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: related_create_check_missing, field_name: 'records_related_create_check_invalid_without_related_record_ids' + + assign related_create_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "related_record_ids": "TEST-0000-00002,TEST-0000-00003" } + function related_create_check_ok = 'modules/accela_construct/commands/records/related/create/check', object: related_create_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: related_create_check_ok, field_name: 'records_related_create_check_valid_with_related_record_ids' + + assign related_create_build_input = { "record_id": "TEST-0000-00001", "related_record_ids": "TEST-0000-00002,TEST-0000-00003" } + function related_create_build_output = 'modules/accela_construct/commands/records/related/create/build', object: related_create_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_create_build_output.path, expected: '/records/TEST-0000-00001/related', field_name: 'records_related_create_build_path' + assign related_create_payload = related_create_build_output.payload | parse_json + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_create_payload.relatedRecordIds.size, expected: 2, field_name: 'records_related_create_build_splits_ids_into_array' + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_create_payload.relatedRecordIds.first, expected: 'TEST-0000-00002', field_name: 'records_related_create_build_array_first_id' + + function related_create_result = 'modules/accela_construct/commands/records/related/create', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: related_create_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_create_result.error, expected: 'accela_validation_failed', field_name: 'records_related_create_returns_validation_failed_without_related_record_ids' + + # --- records/related/delete (no payload) --- + + assign related_delete_check_missing = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001" } + function related_delete_check_missing = 'modules/accela_construct/commands/records/related/delete/check', object: related_delete_check_missing + function contract = 'modules/tests/assertions/invalid_object', contract: contract, object: related_delete_check_missing, field_name: 'records_related_delete_check_invalid_without_child_record_ids' + + assign related_delete_check_ok = { "errors": {}, "valid": true, "record_id": "TEST-0000-00001", "child_record_ids": "TEST-0000-00002" } + function related_delete_check_ok = 'modules/accela_construct/commands/records/related/delete/check', object: related_delete_check_ok + function contract = 'modules/tests/assertions/valid_object', contract: contract, object: related_delete_check_ok, field_name: 'records_related_delete_check_valid_with_child_record_ids' + + assign related_delete_build_input = { "record_id": "TEST-0000-00001", "child_record_ids": "TEST-0000-00002" } + function related_delete_build_output = 'modules/accela_construct/commands/records/related/delete/build', object: related_delete_build_input + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_delete_build_output.path, expected: '/records/TEST-0000-00001/related/TEST-0000-00002', field_name: 'records_related_delete_build_path' + + function related_delete_result = 'modules/accela_construct/commands/records/related/delete', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: related_delete_result, field_name: 'success' + function contract = 'modules/tests/assertions/equal', contract: contract, given: related_delete_result.error, expected: 'accela_validation_failed', field_name: 'records_related_delete_returns_validation_failed_without_child_record_ids' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/accela_oauth_token_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/accela_oauth_token_test.liquid new file mode 100644 index 00000000..7c05634e --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/accela_oauth_token_test.liquid @@ -0,0 +1,14 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% comment %} + Unlike the other query tests in this suite, this one does NOT touch + Accela at all - it's a local GraphQL read of the accela_oauth_token + table, so it's safe to assert concretely rather than as a smoke test. + In a fresh test environment the table is empty, so the query should + return a blank/nil record. +{% endcomment %} +{% liquid + function token_record = 'modules/accela_construct/queries/accela_oauth_token/find' + function contract = 'modules/tests/assertions/not_true', contract: contract, value: token_record, field_name: 'accela_oauth_token_find_returns_blank_when_table_empty' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/accela_request_response_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/accela_request_response_test.liquid new file mode 100644 index 00000000..da886504 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/accela_request_response_test.liquid @@ -0,0 +1,15 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% comment %} + Like accela_oauth_token_test.liquid, this doesn't touch Accela - it's a + local GraphQL read of the accela_request_response table. Filters by a + request_id that can't exist rather than asserting the table is empty, + since real usage of this module writes rows to this table continuously + (see lib/accela_client/log_request.liquid) - asserting global emptiness + would be flaky against anything but a brand new, never-used environment. +{% endcomment %} +{% liquid + function responses = 'modules/accela_construct/queries/accela_request_response/list', request_id: 'accela_construct_test_nonexistent_request_id' + function contract = 'modules/tests/assertions/equal', contract: contract, given: responses.results.size, expected: 0, field_name: 'accela_request_response_list_filters_by_request_id' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/accela_request_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/accela_request_test.liquid new file mode 100644 index 00000000..a01c88f0 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/accela_request_test.liquid @@ -0,0 +1,19 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% comment %} + Like accela_oauth_token_test.liquid, this doesn't touch Accela - it's a + local GraphQL read of the accela_request table. Filters by a path that + can't exist rather than asserting the table is empty, since real usage + of this module writes rows to this table continuously (see + lib/accela_client/log_request.liquid) - asserting global emptiness + would be flaky against anything but a brand new, never-used environment. +{% endcomment %} +{% liquid + function requests = 'modules/accela_construct/queries/accela_request/list', path: '/accela_construct_test_nonexistent_path' + function contract = 'modules/tests/assertions/equal', contract: contract, given: requests.results.size, expected: 0, field_name: 'accela_request_list_filters_by_path' + + assign nonexistent_reference = { "id": "accela_construct_test_nonexistent_id", "table": "accela_construct_test_nonexistent_type" } + function requests_by_reference = 'modules/accela_construct/queries/accela_request/list', reference: nonexistent_reference + function contract = 'modules/tests/assertions/equal', contract: contract, given: requests_by_reference.results.size, expected: 0, field_name: 'accela_request_list_filters_by_reference' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/documents_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/documents_test.liquid new file mode 100644 index 00000000..c047efaf --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/documents_test.liquid @@ -0,0 +1,22 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% comment %} + These are contract/shape smoke tests, not path-correctness tests - they + assert graceful failure in the absence of live Accela credentials (the + expected state for automated test runs); with real credentials + configured some assertions here would need to expect success instead. +{% endcomment %} +{% liquid + function result = 'modules/accela_construct/queries/records/documents/list', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'documents_list_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'documents_list_error' + + function result = 'modules/accela_construct/queries/records/documents/categories', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'documents_categories_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'documents_categories_error' + + function result = 'modules/accela_construct/queries/documents/download', document_id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'documents_download_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'documents_download_error' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/inspections_checklists_conditions_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/inspections_checklists_conditions_test.liquid new file mode 100644 index 00000000..71aaaabe --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/inspections_checklists_conditions_test.liquid @@ -0,0 +1,30 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% comment %} + Contract/shape smoke tests, not path-correctness tests - they assert + graceful failure in the absence of live Accela credentials (the expected + state for automated test runs); with real credentials configured some + assertions here would need to expect success instead. +{% endcomment %} +{% liquid + # queries/inspections/checklists/list + function result = 'modules/accela_construct/queries/inspections/checklists/list', inspection_id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'inspections_checklists_list_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'inspections_checklists_list_error' + + # queries/inspections/conditions/list + function result = 'modules/accela_construct/queries/inspections/conditions/list', inspection_id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'inspections_conditions_list_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'inspections_conditions_list_error' + + # queries/inspections/conditions/get + function result = 'modules/accela_construct/queries/inspections/conditions/get', inspection_id: '1001', id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'inspections_conditions_get_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'inspections_conditions_get_error' + + # queries/inspections/conditions/histories + function result = 'modules/accela_construct/queries/inspections/conditions/histories', inspection_id: '1001', id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'inspections_conditions_histories_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'inspections_conditions_histories_error' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/inspections_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/inspections_test.liquid new file mode 100644 index 00000000..6d7719d0 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/inspections_test.liquid @@ -0,0 +1,45 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% comment %} + Contract/shape smoke tests, not path-correctness tests - they assert + graceful failure in the absence of live Accela credentials (the expected + state for automated test runs); with real credentials configured some + assertions here would need to expect success instead. +{% endcomment %} +{% liquid + # queries/records/inspections/list (record-scoped) + function result = 'modules/accela_construct/queries/records/inspections/list', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'inspections_list_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'inspections_list_error' + + # queries/records/inspection_types/list (record-scoped) + function result = 'modules/accela_construct/queries/records/inspection_types/list', record_ids: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'inspections_types_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'inspections_types_error' + + # queries/inspections/all + function result = 'modules/accela_construct/queries/inspections/all', module: 'Building' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'inspections_all_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'inspections_all_error' + + # queries/inspections/get + function result = 'modules/accela_construct/queries/inspections/get', ids: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'inspections_get_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'inspections_get_error' + + # queries/inspections/available_dates + function result = 'modules/accela_construct/queries/inspections/available_dates', type_id: 173, record_id: 'TEST-0000-00001', start_date: '2026-08-01' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'inspections_available_dates_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'inspections_available_dates_error' + + # queries/inspections/histories + function result = 'modules/accela_construct/queries/inspections/histories', inspection_ids: '1001,1002' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'inspections_histories_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'inspections_histories_error' + + # queries/inspections/related + function result = 'modules/accela_construct/queries/inspections/related', id: '1001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'inspections_related_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'inspections_related_error' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/records_sub_resources_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/records_sub_resources_test.liquid new file mode 100644 index 00000000..f6d8de47 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/records_sub_resources_test.liquid @@ -0,0 +1,62 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% comment %} + These are contract/shape smoke tests, not path-correctness tests - they + assert graceful failure in the absence of live Accela credentials (the + expected state for automated test runs); with real credentials + configured some assertions here would need to expect success instead. +{% endcomment %} +{% liquid + function result = 'modules/accela_construct/queries/records/parcels/list', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_parcels_list_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_parcels_list_error' + + function result = 'modules/accela_construct/queries/records/owners/list', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_owners_list_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_owners_list_error' + + function result = 'modules/accela_construct/queries/records/addresses/list', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_addresses_list_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_addresses_list_error' + + function result = 'modules/accela_construct/queries/records/conditions/list', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_conditions_list_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_conditions_list_error' + + function result = 'modules/accela_construct/queries/records/conditions/get', record_id: 'TEST-0000-00001', id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_conditions_get_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_conditions_get_error' + + function result = 'modules/accela_construct/queries/records/conditions/histories', record_id: 'TEST-0000-00001', id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_conditions_histories_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_conditions_histories_error' + + function result = 'modules/accela_construct/queries/records/workflow_tasks/list', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_workflow_tasks_list_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_workflow_tasks_list_error' + + function result = 'modules/accela_construct/queries/records/workflow_tasks/get', record_id: 'TEST-0000-00001', id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_workflow_tasks_get_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_workflow_tasks_get_error' + + function result = 'modules/accela_construct/queries/records/workflow_tasks/statuses', record_id: 'TEST-0000-00001', id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_workflow_tasks_statuses_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_workflow_tasks_statuses_error' + + function result = 'modules/accela_construct/queries/records/workflow_tasks/histories', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_workflow_tasks_histories_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_workflow_tasks_histories_error' + + function result = 'modules/accela_construct/queries/records/workflow_tasks/comments_histories', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_workflow_tasks_comments_histories_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_workflow_tasks_comments_histories_error' + + function result = 'modules/accela_construct/queries/records/payments/list', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_payments_list_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_payments_list_error' + + function result = 'modules/accela_construct/queries/records/payments/get', record_id: 'TEST-0000-00001', payment_id: '1' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_payments_get_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_payments_get_error' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/records_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/records_test.liquid new file mode 100644 index 00000000..2ffa02b9 --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/records_test.liquid @@ -0,0 +1,51 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% comment %} + These are contract/shape smoke tests, not path-correctness tests - they + assert graceful failure in the absence of live Accela credentials (the + expected state for automated test runs); with real credentials + configured some assertions here would need to expect success instead. +{% endcomment %} +{% liquid + function result = 'modules/accela_construct/queries/records/get', ids: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_get_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_get_error' + + assign search_criteria = { "module": "Building" } + function result = 'modules/accela_construct/queries/records/search', criteria: search_criteria, limit: 25 + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_search_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_search_error' + + function result = 'modules/accela_construct/queries/records/describe_create', type: 'Building/Residential/Alteration/NA' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_describe_create_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_describe_create_error' + + function result = 'modules/accela_construct/queries/records/list', module: 'Building', limit: 25 + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_list_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_list_error' + + function result = 'modules/accela_construct/queries/records/mine' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_mine_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_mine_error' + + function result = 'modules/accela_construct/queries/records/additional', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_additional_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_additional_error' + + function result = 'modules/accela_construct/queries/records/related', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_related_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_related_error' + + function result = 'modules/accela_construct/queries/records/usercomments', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_usercomments_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_usercomments_error' + + function result = 'modules/accela_construct/queries/records/votes', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_votes_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_votes_error' + + function result = 'modules/accela_construct/queries/records/votes_summary', record_id: 'TEST-0000-00001' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'records_votes_summary_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'records_votes_summary_error' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/searches_test.liquid b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/searches_test.liquid new file mode 100644 index 00000000..80b888fc --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/lib/test/queries/searches_test.liquid @@ -0,0 +1,67 @@ +{% doc %} + @param {object} contract - test contract object tracking results +{% enddoc %} +{% comment %} + Contract/shape smoke tests, not path-correctness tests - they assert + graceful failure in the absence of live Accela credentials (the expected + state for automated test runs); with real credentials configured some + assertions here would need to expect success instead. +{% endcomment %} +{% liquid + assign criteria = { "module": "Building" } + + # queries/searches/addresses + function result = 'modules/accela_construct/queries/searches/addresses', criteria: criteria + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'searches_addresses_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'searches_addresses_error' + + # queries/searches/agencies + function result = 'modules/accela_construct/queries/searches/agencies', criteria: criteria + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'searches_agencies_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'searches_agencies_error' + + # queries/searches/global (plain GET, no criteria hash) + function result = 'modules/accela_construct/queries/searches/global', query: 'main street' + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'searches_global_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'searches_global_error' + + # queries/searches/assessments + function result = 'modules/accela_construct/queries/searches/assessments', criteria: criteria + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'searches_assessments_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'searches_assessments_error' + + # queries/searches/contacts + function result = 'modules/accela_construct/queries/searches/contacts', criteria: criteria + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'searches_contacts_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'searches_contacts_error' + + # queries/searches/costs + function result = 'modules/accela_construct/queries/searches/costs', criteria: criteria + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'searches_costs_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'searches_costs_error' + + # queries/searches/inspections + function result = 'modules/accela_construct/queries/searches/inspections', criteria: criteria + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'searches_inspections_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'searches_inspections_error' + + # queries/searches/owners + function result = 'modules/accela_construct/queries/searches/owners', criteria: criteria + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'searches_owners_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'searches_owners_error' + + # queries/searches/parcels + function result = 'modules/accela_construct/queries/searches/parcels', criteria: criteria + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'searches_parcels_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'searches_parcels_error' + + # queries/searches/parts + function result = 'modules/accela_construct/queries/searches/parts', criteria: criteria + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'searches_parts_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'searches_parts_error' + + # queries/searches/professionals + function result = 'modules/accela_construct/queries/searches/professionals', criteria: criteria + function contract = 'modules/tests/assertions/not_true', contract: contract, object: result, field_name: 'searches_professionals_success' + function contract = 'modules/tests/assertions/presence', contract: contract, object: result, field_name: 'searches_professionals_error' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/migrations/20260730120100_set_accela_constants.liquid b/pos-module-accela_construct/modules/accela_construct/public/migrations/20260730120100_set_accela_constants.liquid new file mode 100644 index 00000000..9a731a2d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/migrations/20260730120100_set_accela_constants.liquid @@ -0,0 +1,27 @@ +{% comment %} + Seeds the Accela credentials/config as encrypted Constants from + template-values.json (see pos-cli "template values" docs). Re-run this + migration (or update the constants directly via GraphiQL / constant_set) + whenever credentials change. + + IMPORTANT: verify `constant_set` behavior and template-value interpolation + (<%= accela_client_id %> etc.) against your platformOS instance/pos-cli + version before relying on this in production - this pattern is inferred + from other published modules (e.g. payments-stripe) rather than a single + authoritative doc page. +{% endcomment %} + +{% liquid + graphql g1 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_BASE_URL', value: '<%= accela_base_url %>' + graphql g2 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_AUTH_URL', value: '<%= accela_auth_url %>' + graphql g3 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_APP_ID', value: '<%= accela_app_id %>' + graphql g4 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_CLIENT_ID', value: '<%= accela_client_id %>' + graphql g5 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_CLIENT_SECRET', value: '<%= accela_client_secret %>' + graphql g6 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_USERNAME', value: '<%= accela_username %>' + graphql g7 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_PASSWORD', value: '<%= accela_password %>' + graphql g8 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_AGENCY', value: '<%= accela_agency %>' + graphql g9 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_ENVIRONMENT', value: '<%= accela_environment %>' + graphql g10 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_SCOPE', value: '<%= accela_scope %>' + graphql g11 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_MAX_RETRIES', value: '<%= accela_max_retries %>' + graphql g12 = 'modules/accela_construct/constants/set', name: 'ACCELA_CONSTRUCT_RETRY_DELAY_MINUTES', value: '<%= accela_retry_delay_minutes %>' +%} diff --git a/pos-module-accela_construct/modules/accela_construct/public/schema/accela_oauth_token.yml b/pos-module-accela_construct/modules/accela_construct/public/schema/accela_oauth_token.yml new file mode 100644 index 00000000..dd70015c --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/schema/accela_oauth_token.yml @@ -0,0 +1,13 @@ +# Table used to cache the Accela OAuth2 token so we don't request a new one +# on every API call. Accela access tokens are short-lived (15 minutes as of +# May 2024); refresh tokens last 8 hours. See lib/accela_client/get_valid_token.liquid. +name: accela_oauth_token +properties: + - name: access_token + type: string + - name: refresh_token + type: string + - name: expires_at + type: string # unix timestamp (seconds), stored as string + - name: refresh_token_expires_at + type: string # unix timestamp (seconds), stored as string diff --git a/pos-module-accela_construct/modules/accela_construct/public/schema/accela_request.yml b/pos-module-accela_construct/modules/accela_construct/public/schema/accela_request.yml new file mode 100644 index 00000000..57d3870f --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/schema/accela_request.yml @@ -0,0 +1,21 @@ +# Table logging one row per logical Accela request this module makes - +# created once, on that request's first attempt. See +# lib/accela_client/log_request.liquid. Each request may have multiple +# accela_request_response rows (one per attempt, including background +# retries) - see accela_request_response.yml. How many attempts a +# request has had is derived from that table (filter accela_request_response +# by request_id and read total_entries - see queries/accela_request_response/list), +# not stored here. +name: accela_request +properties: + - name: method + type: string + - name: path + type: string + - name: request_payload + type: string + - name: reference_id + type: string # optional polymorphic association to a caller-defined object + - name: reference_schema + type: string # the platformOS table reference_id's row lives in (a real Record.table + # value, not a caller-invented label) - see log_request.liquid diff --git a/pos-module-accela_construct/modules/accela_construct/public/schema/accela_request_response.yml b/pos-module-accela_construct/modules/accela_construct/public/schema/accela_request_response.yml new file mode 100644 index 00000000..a279c44d --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/schema/accela_request_response.yml @@ -0,0 +1,18 @@ +# Table logging one row per attempt against an accela_request - the +# original synchronous attempt and every background retry. Written by +# lib/accela_client/log_request.liquid right after send.liquid computes +# each attempt's result. +name: accela_request_response +properties: + - name: request_id + belongs_to: accela_request + - name: attempt_number + type: integer # 1 = the original synchronous call, 2+ = background retries + - name: status + type: integer + - name: response_body + type: string + - name: success + type: boolean + - name: error + type: string diff --git a/pos-module-accela_construct/modules/accela_construct/public/views/pages/accela_construct/test.liquid b/pos-module-accela_construct/modules/accela_construct/public/views/pages/accela_construct/test.liquid new file mode 100644 index 00000000..421ed4eb --- /dev/null +++ b/pos-module-accela_construct/modules/accela_construct/public/views/pages/accela_construct/test.liquid @@ -0,0 +1,22 @@ +--- +slug: accela_construct/test +--- +{% comment %} + Manual smoke-test page for the module. Visit /accela_construct/test?module=Building + once ACCELA_* constants are configured. Remove or protect this page + (e.g. with an authorization_policy limiting it to admins) before + shipping to production - it exposes raw Accela responses. +{% endcomment %} + +{% liquid + assign search_module = context.params.module | default: 'Building' + assign criteria = { "module": search_module } + function result = 'modules/accela_construct/queries/records/search', criteria: criteria, limit: 5 +%} + +

Accela Construct API - test call

+

Search module: {{ search_module }}

+

Success: {{ result.success }}

+

Status: {{ result.status }}

+{% if result.error %}

Error: {{ result.error }}

{% endif %} +
{{ result.raw }}
diff --git a/pos-module-accela_construct/modules/accela_construct/template-values.json b/pos-module-accela_construct/modules/accela_construct/template-values.json new file mode 100644 index 00000000..e69de29b diff --git a/pos-module-accela_construct/pos-module.json b/pos-module-accela_construct/pos-module.json new file mode 100644 index 00000000..3da0cba0 --- /dev/null +++ b/pos-module-accela_construct/pos-module.json @@ -0,0 +1,5 @@ +{ + "machine_name": "accela_construct", + "version": "1.0.0", + "name": "Accela Construct API Wrapper Module" +} diff --git a/pos-module-accela_construct/pull_request_template.md b/pos-module-accela_construct/pull_request_template.md new file mode 100644 index 00000000..e231a4ef --- /dev/null +++ b/pos-module-accela_construct/pull_request_template.md @@ -0,0 +1,13 @@ +# Description + +Please include a summary of the changes and the related issue. Please also include relevant motivation and context. List any dependencies that are required for this change. + +## Issue ticket number and link + + +# Checklist: + +- [ ] My code follows the style guidelines of this project +- [ ] I have performed a self-review of my code +- [ ] I have made corresponding changes to the documentation +- [ ] Any dependent changes have been merged and published in downstream modules