Asbestos Survey — Overview¶
Peter Steele: "Asbestos data — a whole world of pain."
The Asbestos Survey is one of the most complex form ecosystems in Versaa. It has its own dedicated workflows for loading, data enrichment, and completion — completely separate from the generic Property Check Appointment pipeline.
Forms¶
| Form | Current Version | Purpose |
|---|---|---|
Asbestos Survey |
12 (27/05/2026) | Primary surveyor form |
Asbestos Data |
42 (27/05/2026) | Lightweight test/debug form — bypasses property screen, directly loads asbestos data |
Asbestos Reinspection |
70 (27/05/2026) | Reinspection of previously surveyed components |
Asbestos Site Audit |
78 (as of 14/08/2026) | Site-level audit form |
Asbestos Edit DataList |
3 | Data list editing form |
Asbestos reassign review |
6 (27/05/2026) | Reassign/review routing form |
Asbestos Data form as a debug tool: Peter confirmed the Asbestos Data form is "a relatively quick form that doesn't actually involve pressing any buttons" — it exists specifically to test that data loading works. It bypasses the property screen and loads asbestos data directly. If the Asbestos Data form loads correctly, the data pipeline is confirmed working.
Workflows¶
| Workflow | Current Version | Trigger | Purpose |
|---|---|---|---|
Asbestos Get Property Data |
4 (27/05/2026) | *.GetAsbestosPropertyData |
Orchestrates data load — checks idempotency, fires AppendPCAData, waits for callback |
Asbestos Survey Load Data |
8 (27/05/2026) | Asbestos Survey.AppendPCAData / Asbestos Data.AppendPCAData |
Loads all QL property + asbestos component data into the task |
Asbestos Survey Completion |
4 | Asbestos Survey.PCACompletion |
Handles asbestos-specific completion — updates Property Data and Components Data in QL |
Asbestos Reins Concat Groups |
21 | — | Concatenates reinspection group data |
Asbestos Reference Data |
1 | — | Handles reference data for asbestos forms |
Asbestos Get Property Data |
1 | — | Earlier version/variant |
Asbestos site audit conc |
1 | — | Site audit concatenation step |
Asbestos QL Update |
0 | — | QL update step |
Workflow Variables¶
| Variable | Value | Purpose |
|---|---|---|
Asbestos_SurveyCycle |
5 |
Cycle number used when filtering asbestos components from QL |
Asbestos_ReferenceDataFolder |
— | Path to reference data files |
Asbestos_PropertySearch |
— | Property search SQL/config |
Asbestos_FileLocation |
— | File storage path |
Asbestos_OrderNotIssuedRecipient |
— | Email recipient for unissued orders |
Asbestos_ConvertTaskDataToRefData |
— | XSLT for data conversion |
AsbestosReinspectionDescriptionConcat |
— | Concat template for reinspection |
AsbestosReferenceDataFolder |
— | Alternate reference data path |
AsbestosQLPropertySearch |
— | QL property search config |
AsbestosLocationsSQL |
— | SQL for locations list |
AsbestosDocumotiveFileLocation |
— | Documotive (document storage) path |
asbestos_site_audit_xslt |
— | XSLT for site audit output |
How Data Loading Works¶
Why Asbestos is NOT in the generic PCA workflow¶
The generic Property Check Appoint LoadDat workflow handles *.AppendPCAData for most forms. However, it contains an explicit exclusion list at the first step. If the incoming event name contains any of the following, the workflow exits immediately with status "Ignored":
Asbestos Survey.Asbestos Data.Building Safety Check.Fire Risk Assessment.Estate Assessment Inspection.- (and 10+ others)
This means asbestos forms must be handled by their own dedicated workflow.
The Two-Workflow Pattern¶
Asbestos data loading uses two workflows in sequence:
Form button press
↓
[Form sends: FormName.GetAsbestosPropertyData]
↓
Asbestos Get Property Data workflow starts
├─ Checks if "Asbestos Data Loaded" = "Yes" → if yes, exits (idempotency)
├─ Sends: FormName.AppendPCAData
├─ Waits for: AppendPCADataCallBack
↓
Asbestos Survey Load Data workflow starts
├─ Tag Workflow ($Tag FRA$)
├─ Tag Form Name (from task formTypeName)
├─ Tag AD User Name (from task userName)
├─ Append Extended Property Task Data (QL property details)
├─ Clear Components (DELETE FROM QLPrtyCm_Components)
├─ Append Component Task Data (appendAsbestos=true, cycle=$Asbestos_SurveyCycle$)
├─ Append Original Cycle No (SQL transform + status normalisation)
├─ Append Property Extra Extended Task Data
├─ Append Loaded Flag (sets "Asbestos Data Loaded" = "Yes")
└─ Send Callback Event → returns to Get Property Data
↓
Get Property Data workflow receives callback
└─ Unpacks PCA data, sets AsbestosDataLoaded = "Yes", ends
Component Data Details¶
The Append Component Task Data step:
- Sets appendAsbestos="true" — only asbestos components are loaded
- All other types (appendDecentHomes, appendNormal, appendLettings, appendUndefined) = false
- Uses $Asbestos_SurveyCycle$ (currently 5) as the cycle number filter
- Data lands in the QLPrtyCm_Components group
The Append Original Cycle No step runs SQL against the in-memory QLPrtyCm_Components group:
SELECT *,
QLPrtyCy_cycle_no AS cycle_no_original,
CASE QLPrtyCm_cmpnt_status
WHEN 'Existing' THEN 'Active'
ELSE 'Historical'
END AS Component_Status
FROM QLPrtyCm_Components
ORDER BY QLPrtyCm_location
Key transformations:
- cycle_no_original preserves the original cycle number before any edits
- Component_Status: Existing → Active; anything else → Historical
- Components sorted by QLPrtyCm_location
Note on Tag Mapping¶
The Tag Workflow step uses $Tag FRA$ — this reuses the Fire Risk Assessment tag mapping. This is deliberate (shared tag structure between FRA and Asbestos Survey inspection types).
Completion Flow¶
The Asbestos Survey Completion workflow fires on Asbestos Survey.PCACompletion.
Steps:
1. Unpack Data
2. Set status "Asbestos Survey.Starting"
3. Set Tags ($Tag Property Check$)
4. Tag Form Name + AD User Name
5. Abandonment check — if Form_AbandonProcessing = Yes, routes to abandoned branch
6. Update Property Data — writes property record back to QL (UpdatePropertyWorkflowStep)
7. Update Property Components Data — writes component changes back to QL (UpdateComponentsWorkflowStep)
Active Development (18/05/2026)¶
As of 18 May 2026, active package iterations:
| Package | Versions built | Notes |
|---|---|---|
asbestos_get_property_data_v2/v3/v4_180526.ftpackage |
v1→v4 today | Multiple iterations fixing data load issues |
asbestos_survey_load_data_v5/v6/v7/v8_180526.ftpackage |
v5→v8 | Load data workflow; v8 reverts useless Clear Components step |
asbestos_data_form_v39/v40/v41_190526.ftpackage |
v38→v41 | Form fix; v39/v40 failed SQL 8152 (long manifest comment); v41 imported OK |
Known bug fixed (v41, Asbestos Data form, 19/05/2026):
- Root cause: GetAsbestosPropertyData Request FormItem had sendAllItems=False and items=GenBP_Key_PropertyId; only — Asbestos Data Loaded was never sent with the event, so the guard in Asbestos Get Property Data v4 always saw an empty value and never triggered "already loaded"
- Fix: Set sendAllItems=True on the Get Asbestos Data request — form now sends all DataItems (including Asbestos Data Loaded) with the event; guard works correctly on second open
- Import failures (v39, v40): Both failed with SQL 8152 due to overly long comment attribute in manifest.xml. Form manifest comment must be kept to ~100 chars or fewer.
Asbestos Site Audit fixes (v75, 20/05/2026) — Halo ticket 7930 items 5 & 6:
Item 5 — "Any Other Comments" duplicating inside Issues Identified:
- Root cause: QLcrm_Full Description formula expression included +$formItem.Tenant_Comments, so "Any Other Comments" appeared inside the "Issues Identified:" section of the QL full description
- Fix (form): Removed +$formItem.Tenant_Comments from QLcrm_Full Description formula expression
- Fix (XSLT variable): Added <xsl:value-of select="//Task[not(ancestor::Task)]/DataItems/DataItem[@name='Tenant Comments']"/> after the </xsl:for-each> in the XSLT, so "Any Other Comments" now appears at the end of the QL full description, outside Issues Identified
- Watch out: The XSLT value in the .variable file is double-entity-encoded in the raw XML (&lt; for <). When editing with Python's xml.etree, elem.text gives the singly-decoded version. Edit there and write back, or do the raw string edit at the double-encoded level.
Item 6 — QL contact has no classification when no issues identified:
- Root cause: QLcrm_Class Level 1 formula had 10 conditions (Q1–Q10 = "No" or Q8 = "Yes"), but the final fallback Summary used <Value type="NoValue" />. If none of the 10 triggered (all questions = "Yes", no defects found), all 5 classification levels returned empty → QL contact received no classification
- Fix: Changed final Summary Value type from NoValue to Constant with value COMPLIANCE
- Result: All Asbestos Site Audit completions now generate a COMPLIANCE > POSTINSPEC > ASBESTOS > DEFECT classification in QL, regardless of whether issues were found
- Watch out: The form XML stores self-closing tags as <Value type="NoValue"></Value> (not <Value type="NoValue" />). String replacements must match the actual file format.
Asbestos Site Audit fixes (v76, 19/06/2026) — Halo ticket 7930 (Kelly's 11/06/2026 re-test):
Blocker — could not submit; "VALIDATION ERRORS: QLcrm_DefaultAction_Action Outcome: A value is required":
- Root cause: QLcrm_DefaultAction_Action Outcome (Data List, source Aareon.QL-x.TenancyContactOutcomes.list) had isMandatory=True, even though it sits under the red "Optional, rarely used" label. Surveyors could not move past it. Because QLcrm_CreateDefaultAction defaults to Yes, a contact action is always created; being forced to pick an Outcome is also why the contact action came through "already completed" (Kelly set it to completed just to proceed).
- Fix (form): Set isMandatory False on QLcrm_DefaultAction_Action Outcome. With Outcome/Completed left blank by default the QL contact action is created open in the Compliance worktray.
- Watch out: Q2/4/6/8 ("A value is required" in Kelly's screenshots) are legitimately mandatory survey questions (isMandatory=True) — not a bug, just unanswered.
Relabel + reorder of the QL contact description (Kelly request):
- Relabel (form): The Tenant Comments calculated field emitted " Any Other Comments: "; changed to " Any other comments from the tenant: ".
- Reorder (XSLT variable): asbestos_site_audit_xslt FullDescription emitted Additional Comments before Any Other Comments. Moved the Tenant Comments <xsl:value-of> to before the z_Additional Information + Additional Information for-each, so the QL order (Issues Identified → Any Other Comments → Additional Comments) matches the on-form flow (on the form, "Any other comments" precedes the Additional Information grid).
Asbestos Site Audit layout fix (v77, 19/06/2026) — Ticket 7930, Kelly: "questions 1, 3 and 5 are to the right and 2, 4, 6, 8 are below, they used to be side by side":
- How the two columns are actually built: a SectionBreakElement carries the width of the section it opens (largeDeviceControlWidth / regularDeviceControlWidth). The Audit block opens three consecutive 50%-wide sections on a large device: the Front Photo section, then Q1/Q3/Q5/Q7, then Q2/Q4/Q6/Q8. The odd/even split is deliberate — with two 50% sections side by side, each row reads Q1|Q2, Q3|Q4, Q5|Q6, Q7|Q8.
- Root cause: three 50% sections cannot fit two columns. The photo section took column 1, the odd questions were pushed into column 2, and the even questions wrapped onto the next row — exactly what Kelly saw.
- Fix: Front Photo section break largeDeviceControlWidth 50 → 100, so the photo occupies its own full-width row and the two question sections pair up again.
- Why it only broke on desktop: the photo section was already regularDeviceControlWidth=100, so phones were always correct. Kelly tested on the Windows desktop app (large device).
- Watch out: the question order in the XML is Q1 Q3 Q5 Q7 Q2 Q4 Q6 Q8 and is identical in every version back to v10 — it is not a regression and must not be "corrected" to 1–8, or the column pairing breaks.
Asbestos Site Audit PDF de-duplication (v78, 14/08/2026) — Ticket 7930, Kelly 07/08:
- Symptom: the completed-form PDF showed the tenant-comment label twice — Any other comments from the tenant with regards to the survey? immediately followed by Any other comments from the tenant: she was very happy.
- Root cause — the PDF is a Word template, not an auto-render. extracted/document_templates/DocumentTemplates/Asbestos+Site+Audit.template (selected by the form's Form_DocumentTemplateName="Asbestos Site Audit") contains static heading text "Any other comments from the tenant with regards to the survey?" and binds a merge field Tenant Comments:1d8ba2f9-…. The v76 relabel had put "Any other comments from the tenant:" inside the Tenant Comments calc value, so the merge field re-printed the label the heading already showed. The raw z_Tenant Comments is not bound in the template.
- Fix (scriptable — no template edit): changed the Tenant Comments calc field to emit the raw answer only ($formItem.z_Tenant_Comments ? $formItem.z_Tenant_Comments : ""). The merge field now prints just the answer under the static heading → question/answer format, matching Q1–Q12. The Any other comments from the tenant: label was moved into the XSLT variable (<xsl:if> on non-empty) so the QL work tray full description is unchanged.
- Also: aligned the two on-form TextBoxElement captions customer → tenant (app now matches PDF/QL).
- Gotcha — the duplicated label was static text baked into the Word template, not a form field. When a completed-form PDF shows unexpected/duplicated text, check the .template word/document.xml (static runs + descr="FieldName:GUID" merge bindings), not just the form. A bound merge field renders even with the form item's availableForDocumentRendering=False.
CPL017 action code (carried over from 2025 item 7) — NOT a Versaa change:
- CPL017 is allocated to user COGGIJ; Kelly wants it allocated to COMPLIANCE. CPL017/COGGIJ appear nowhere in the form or workflow — this is QL action-type configuration. Handle as a separate QL admin SQL change (see Common Issues row below).
Asbestos Data form — duplication FIXED + VERIFIED, and the blank "Location" column (Ticket 17337, Kelly 11/06/2026):
Two genuinely separate defects; keep them apart.
1. The duplication (the ticket's actual subject) — FIXED, verified by Kelly in Test 11/06/2026:
- Root cause: sendAllItems=False on the Get Asbestos Data request meant the Asbestos Data Loaded DataItem never reached the Asbestos Get Property Data idempotency guard. The guard always saw an empty value, never short-circuited, and the load workflow ran twice — appending every component a second time ("duplicates below the yellow line").
- Fix: sendAllItems=True on the form (on-disk package labelled _41/_42; MS Dev active is v40 — MS assigns its own version and ignores the package label, so track the MS number not the filename).
- Verified by Kelly across 6 properties — B47461, D52521, B45526, D54386, D34586, B47451 — no duplicates anywhere. She tested TEST, where the form is v12.
- Version audit (21/07/2026, live MS query — numbers are NOT comparable across envs, each auto-increments on import):
| Artefact | Dev | Test (verified) | Live |
|---|---|---|---|
| Asbestos Data (form) | 40 | 12 | 6 |
| Asbestos Get Property Data (wf) | 5 | 3 | 4 |
| Asbestos Survey Load Data (wf) | 8 | 4 | 4 |
| Property Check Appoint LoadDat (wf) | 31 | 24 | 8 |
- Live deployment still OUTSTANDING — and a content diff (not just versions) shows the fix has 3 parts, of which Live is missing 2 (
compare_asbestos_test_live.py, 21/07): - Asbestos Data form (Test v12) — sends
sendAllItems=Trueon theGet Asbestos Datarequest (the "loaded" flag). Promote (Live v6 predates the fix). - Asbestos Get Property Data (Test v3) — the idempotency guard (
XPathConditionalTargetonAsbestos Data Loaded). Live v4 has ZERO guard — despite the higher number, Live's content is the unfixed one (numbers aren't comparable across envs). Promote — core fix. - Property Check Appoint LoadDat — Live v8's exclusion list is missing
Asbestos Data, so in Live the generic workflow also loads it (a duplication source). ⛔ DO NOT promote Test v24 — a full structural diff (27/07) found three unrelated generic changes riding along: (a) it would DROPVoid Weekly Flushingfrom the exclusion list (present in Live v8, absent in Test v24) → recreates this same double-load bug on that form; (b) it adds a third component-load pass (AppendPCAComponent3CallBack) affecting every PCA form; (c) it removes the terminalEndSetUserStatus step. ✅ Correct fix = surgical one-token edit to Live v8's existing XPath: appendor contains(//Event[not(ancestor::Event)]/@name, 'Asbestos Data.')— mind the trailing dot (entries match the event prefix, e.g.Asbestos Data.PCALoadData). - Skip Asbestos Survey Load Data — Test v4 vs Live v4 differ only by a
Clear Componentsstep that Dev reverted at v8 as ineffective; not part of the working fix. - Manual MS Export-from-Test → Import-to-Live (I can't drive imports); re-test on Live after. Scripts:
versaa-rag/audit_asbestos_versions.py,compare_asbestos_test_live.py; checklistscratch/halo_tickets/ticket_17337_live_deployment_check.md. Live has run the duplicating version since 21/11/2025. - Gotcha reinforced: the generic PCA
Property Check Appoint LoadDatmust exclude bothAsbestos DataandAsbestos Survey; if either is missing from the ignored-forms XPath, that form gets double-loaded (generic PCA + its own asbestos workflow). - Generic-workflow rule (learned here): never promote a shared workflow wholesale to fix one form. Its ignored-forms list diverges in both directions between envs, so an import can silently remove another form's exclusion. Diff the exclusion lists as sets before importing, and prefer editing the target env's existing version.
- Possible unreported double-loads in Live: four forms are excluded in Test but not Live — Damp and Mould Inspection, Red Flag Reporting, Component Replacement Request, Family Survey 2 MW. If any is live with its own loader it may be duplicating now. Check with Mark/Peter; don't fix blind.
2. Blank "Location" column on Laundry rows — NOT the duplication bug, and NOT a Versaa change:
- Symptom: on B47451 and B3701, the grid's Location cell is empty for Laundry components; every other location on the same property renders correctly. QL itself shows these components perfectly (location = LAUNDRY, Location Desc = Laundry).
- How the column resolves: grid column z_QLPrtyCm_location lookup (Data List, datasource Aareon.QL-x.AsbestosLocations.list) displays the description matching the component's QLPrtyCm_location code. That list is built by the AsbestosLocationsSQL variable from cmpgencd (mod_id='HSG', category_id='LOCATION'), minus an exclusion list, and is a snapshot — not live — so it must be rebuilt after any cat/gen-code change.
- ⚠️ TWO workflows write this same datalist, and the one you'd expect is NOT the scheduled one:
| Workflow | Writes Aareon.QL-x.AsbestosLocations |
Trigger | Notifies devices |
|---|---|---|---|
QL Asbestos Base Data |
yes, via $AsbestosLocationsSQL$ |
none — bare <Start>, no timer/message, allowRunFromPortal="false" → manual only |
yes (SendNotificationStep, RefData, userNames="*") |
QL Property Survey Base Data |
yes, near-identical inline SQL (extra desn not like 'CAT&GENCODE%'; uses $1T_DB_ProviderType$ not $QL_DB_ProviderType$) |
scheduled daily 20:20 (Frequency=Minutely, RepeatDelay=1440) |
yes |
Last writer wins, so a manual QL Asbestos Base Data run is a temporary override — the nightly QL Property Survey Base Data overwrites it the same evening. The durable fix is always the cmpgencd data itself. Schedules are per-environment: confirm the nightly exists and is running in the env you care about before assuming a rebuild happened.
- The Asbestos Data form is the outlier. Every other asbestos consumer (Append Asbestos By Property, Load Asbestos Data Config, EleLoadAsbestosData, Electrical Cert AdHoc) resolves the description server-side with a cmpgencd join. Only this form resolves it client-side against the cached datalist — which is exactly why a code can be perfect in QL and blank here, and why a stale device cache can break it on one device but not another.
- Reading the deployed list: .list files are gzipped XML (that is why Versaa_Exports_md/reference_lists/*.md render as *(parse error)*). Use versaa-rag/fetch_reference_list.py --env <env> --name AsbestosLocations — it fetches a single list, which matters because Live's ~6,255 reference-data items make a whole-category export 504 every time.
- Root cause — duplicate-description collision. ONE row survives, and it is the lowest code_id. cmpgencd held two HSG/LOCATION codes both described Laundry — LAUNDR (used by nothing) and LAUNDRY (93 asbestos components across 33 properties). The list writer keeps one row per unique Name; AsbestosLocationsSQL is order by desn with no DISTINCT and no tie-break, so ties fall to physical/index order (code_id ascending). LAUNDR sorts before LAUNDRY, so the dead code won the slot and the in-use code had no entry → blank cell.
- ⚠️ This corrects the "neither row is written" mechanism previously recorded here (attributed to Peter Steele, 21/07/2026). It was tested against the deployed artefact on 18/08/2026 and does not hold. .list files are gzipped XML; decompressing Aareon.QL-x.AsbestosLocations.list at three commits shows the broken list contained exactly one row for every duplicate pair, always the lower code_id:
| Export | Laundry row | Items | Duplicate Names |
|---|---|---|---|
| `3024d35` 22/04/2026 (Dev) | `Laundry` → `LAUNDRY` ✅ | 188 | 0 |
| `152721f` 15/07/2026 (Test) | `Laundry` → **`LAUNDR`** ❌ | 215 | 0 |
| `da8d70b` 29/07/2026 (Dev) | `Laundry` → `LAUNDRY` ✅ | 218 | 0 |
In the broken (15/07) list: `BINSTORE`✅ / `COMMONROOM`✅ / `PASSAGE`✅ / `FELEV` / **`LAUNDR`❌** — the survivor is the alphabetically first code every time. Laundry was the *only* pair that broke because it is the only one whose dead code sorts first.
- RESOLVED by Peter Steele (21/07/2026). Deleted the
LAUNDRcat/gen code in Dev, Test and Live (first verifyinghgmprcomhad zero components usingLAUNDR), then re-ran theQL Asbestos Base Dataworkflow in Test and Dev to rebuild the list. (Deleting the unused code is cleaner than the… (Legacy)rename originally proposed — same effect, removes the dead code.) - VERIFIED SERVER-SIDE IN ALL THREE ENVIRONMENTS (18/08/2026). Fetched the deployed list from each Management Studio with
versaa-rag/fetch_reference_list.py: Dev 218 / Test 215 / Live 217 items,Laundry → LAUNDRYin all three, zero duplicate Names.BINSTR/PSSAGE/COMNRMare absent everywhere — the in-use code holds every slot. There is nothing left to fix server-side in any environment. - STILL REPORTED BLANK BY THE USER (Kelly, 07/08/2026) on B47451, B3701 and B3786 in Test, with
Location Codecorrectly showingLAUNDRYon the same screen. Since the task carries the right code and all three servers resolve it, the remaining suspect is a stale reference-data cache on the device. Next step is a forced full device sync and re-check — not another QL change. If it still blanks after a clean resync, escalate as a RefData notification-delivery fault (the rebuild workflows do sendSendNotificationStep/RefDatatouserNames="*"). - Fix pattern for this class (QL config, not Versaa — no form/package/redeploy): (1) make the description unique — delete the unused duplicate, or suffix it
… (Legacy)per the conventionFront Elevation (Legacy)/Landing (Legacy)/Corridor (Legacy)… — then (2) re-runQL Asbestos Base Datato regenerate the list. - CLOSED — the other duplicate pairs were never at risk. The "neither-written" rule predicted that Bin Store (
BINSTORE~1,050 comps /BINSTR), Common Room (COMMONROOM81 /COMNRM) and Passage (PASSAGE408 /PSSAGE) should also be blank. They are not, and never were: in each pair the in-use code sorts first, so it wins the slot. Confirmed twice — in the broken 15/07 list and in all three environments on 18/08. That is why no user ever reported them.ticket_17337_verify_after_peter.sql(V2) was written to settle this and is now moot for the purpose.FELEV/FRTELVis latent only (neither in use). - Still open — 8 codes missing from HSG/LOCATION entirely (a different cause: the code doesn't exist, vs. a duplicate) so also blank:
KIT(29 components / 28 properties),BATH(27/27), andWETRM,HALLCUP2,LOUNGE,REARGARDEN,LANDCB2,CUPB1(1 each).KIT/BATHlook like legacy variants ofKITCHEN/BATHROOM. Either add the codes or remap the components — an asbestos-register decision. - Diagnostic SQL:
scratch/halo_tickets/ticket_17337_location_desc_investigation.sql,ticket_17337_followup.sql, andticket_17337_verify_after_peter.sql(run viarun_as_sql_admin.ps1 --db ql).
Common Issues / Gotchas¶
| Issue | Cause | Fix |
|---|---|---|
| Asbestos data not loading on form | Generic PCA workflow ignoring it | Correct — it's expected. Asbestos has its own workflow. Check Asbestos Get Property Data workflow instances |
| "Already Loaded" status immediately | Asbestos Data Loaded = Yes already set in task |
Idempotency check firing. If you need to reload: clear the DataItem or start a fresh task |
SQL 8152 string truncation on items |
DataItems items column has a 255-char limit; inline modification exceeds it |
Use sendAllItems=True on the event request instead of modifying items inline |
| SQL 8152 on form package import | Form manifest comment attribute stored in a short column (~100 chars); long comments truncate |
Keep form manifest comments brief (<100 chars); workflow comments tolerate longer strings |
| Tenant Comments appearing inside Issues Identified in QL | QLcrm_Full Description formula included +$formItem.Tenant_Comments |
Remove from formula; add Tenant Comments DataItem output to XSLT variable after for-each (see Site Audit v75 fix) |
| QL contact has no classification (audit with no defects found) | QLcrm_Class Level 1 formula final fallback returned NoValue |
Change final Summary Value to Constant COMPLIANCE so all contacts get classified |
| Form won't submit: "QLcrm_DefaultAction_Action Outcome: A value is required" | Field is isMandatory=True but sits in the "Optional, rarely used" section |
Set isMandatory=False (Site Audit v76). A mandatory field can hide inside an "optional" label block — the label is cosmetic, the property is what validates |
| QL contact action arrives "already completed" | Mandatory Action Outcome forced the surveyor to pick an outcome (QLcrm_CreateDefaultAction defaults Yes → action always created) |
Make Action Outcome optional; leave Outcome/Completed blank → action created open |
| Form columns misaligned on desktop (odd questions right, even below) | Three consecutive 50%-wide sections (photo + two question sections) competing for two columns — the SectionBreakElement carries the section width |
Set the photo section's largeDeviceControlWidth to 100 so it takes its own row (Site Audit v77). Do not renumber the questions to 1–8 — the odd/even order is what creates the pairing |
| Form looks right on phone but wrong on desktop | largeDeviceControlWidth and regularDeviceControlWidth are set independently; a section can be 100 on phone and 50 on large |
Always check both width properties when diagnosing layout — and confirm which device class the reporter tested on |
| Fix "doesn't work" after import | Env not updated — Dev and Test hold different active versions | Version-audit both envs before believing a fix failed (GetAllFormsWithVersions). Ticket 7930: Dev=76, Test=30 → Kelly re-tested the old form. Also check the workflow variable landed, not just the form |
| Apparent duplicate QL contacts | Querying WHERE contact_no > N with no prty_id filter on a shared env picks up other users' contacts |
Always filter by property. Ticket 7930 "1 audit → 3 contacts" was 2 unrelated EDI contacts from another user |
| Verifying a QL contact action (open vs completed) | — | QLHGM_ContactActions on t_qlfdat: ContactNumber, ActionCode, AllocatedUser, CompletedYN, CompletedDate, OutcomeCode. Contact + full_desc in hgmcntct |
| CPL017 action code allocated to wrong user (COGGIJ) | Allocation is configured in QL (action-type table), not the Versaa form/workflow | QL admin SQL: UPDATE [QL action-type table] SET alloc_id='COMPLIANCE' WHERE actn_code='CPL017' — exact table TBC by QL admin |
| Components not appearing | Wrong cycle number | Check $Asbestos_SurveyCycle$ variable (currently 5). Must match QL cycle |
| Grid Location cell blank for some components (e.g. Laundry) while others render | Two cmpgencd HSG/LOCATION codes share one description. The list keeps one row per Name and AsbestosLocationsSQL has no DISTINCT/tie-break (order by desn only), so the lowest code_id wins the slot — if that's the dead code, the in-use one renders blank |
Make the description unique — delete the unused duplicate code (or suffix it … (Legacy)) in QL Category & General Code Maintenance, then rebuild the list. Find dupes: GROUP BY RTRIM(desn) HAVING COUNT(*)>1 over cmpgencd HSG/LOCATION (Ticket 17337: LAUNDR/LAUNDRY). Only pairs whose dead code sorts first are affected — don't assume every pair is broken. Not a form bug — no redeploy |
| Location renders correctly on the server list but is still blank on a device | The device holds a stale reference-data cache. This form resolves the location client-side off Aareon.QL-x.AsbestosLocations.list, unlike every other asbestos form (which joins cmpgencd server-side) |
Verify the deployed list first — fetch_reference_list.py --env <env> --name AsbestosLocations. If the server is correct, force a full device sync / re-login. If it survives a clean resync, escalate as a RefData notification-delivery fault |
| A cat/gen-code fix "didn't take" even though the rebuild workflow was run | QL Asbestos Base Data is manual-only; QL Property Survey Base Data writes the same list on a nightly 20:20 schedule and overwrites it. Schedules are per-environment |
Fix cmpgencd (the durable source), then either wait for the nightly or run the manual workflow for an immediate rebuild. Confirm the nightly actually exists and is running in that environment |
Grid Location blank for KIT, BATH, WETRM, LOUNGE, … |
The code is used on components but does not exist in cmpgencd HSG/LOCATION at all |
Add the code in QL Category & General Code Maintenance, or remap the components to the correct code (KITCHEN/BATHROOM). Sweep with the NOT EXISTS query in ticket_17337_location_desc_investigation.sql |
| A QL lookup "works in QL but is blank in Versaa" | QL resolves the code by its own lookup; Versaa resolves it through a datalist built by a workflow-variable SQL with its own filters/exclusions | Compare the two: read the *SQL workflow variable that builds the list (e.g. AsbestosLocationsSQL) and re-run it verbatim. Duplicate descriptions and exclusion lists are the usual culprits |
| Tag FRA used for Asbestos Survey | This is intentional — shared tag structure | No action needed |