HV Tech Stack Chapter 02 · Data

Data.

Where each piece of data lives. Who owns it. How it moves. Every Dataverse table and every WordPress CPT by name.

Contents

In this chapter

  1. i.Source-of-truth lanesI
  2. ii.The consolidation ruleII
  3. iii.Dataverse tablesIII
  4. iv.WordPress CPTs and ACFIV
  5. v.Relationships and decisionsV

I.

Part One

Source-of-truth lanes

The hub is Dataverse. The spokes are WordPress, AUC/ADMINS, MaintainX, Constant Contact, and the census form. Data flows in lanes.

Lane 1 · Downstream (Dataverse to WordPress)

Dataverse is master. WordPress mirrors.

Lane 2 · Upstream (WordPress to Dataverse)

WordPress captures. Dataverse stores.

Lane 3 · MaintainX bridge

MaintainX is master for trade data. Dataverse mirrors work orders. WordPress never stores work orders; it reads scoped views through a server-side REST proxy.

Lane 4 · Constant Contact

Constant Contact holds the subscriber list. Dataverse holds the opt-in record. Power Automate writes to Constant Contact after Sarah approves.

Lane 5 · AUC / ADMINS import

AUC is master for units, owners of record, and financials. It has no API. A scheduled CSV export lands in a watched SharePoint folder. Power Automate imports it into Dataverse. One-way, read-only. Until AUC automates the export, an employee runs it daily or weekly by hand.

Lane 6 · Census (Microsoft Forms)

The census feeds resident-confirmed contact data into the hub. Freshest source, about 50% response. Census answers enrich hv_residents with a source stamp and a verified date.

II.

Part Two

The consolidation rule

Four conflicting sources. One spine. One rule for every merge.

Resident contact data starts in four conflicting sources: AUC, the directory spreadsheet, MaintainX, and the census. AUC is the spine: one row per unit, every owner of record. Enrich blanks from the census first, then the spreadsheet, then MaintainX. Never overwrite. Stamp every contact field with its source and the date last confirmed. When two sources disagree, flag the record for human review; most-recent-verified wins. Track percent verified as a live number. Full strategy: hv-data-hub/PLAN.md §3.

III.

Part Three

Dataverse tables

Every table below is a Dataverse row type. Names follow a hv_ prefix to keep them isolated inside the environment.

hv_residents

The master resident record. Every other operational table links here.

ColumnTypeNotes
resident_idGUIDprimary key
first_nametext
last_nametext
login_emailtextunique; syncs to wp_users.user_email
secondary_emailstext (multi)display only; never used for auth
phonetext
statuschoiceActive, Pending, Suspended, Moved-out
email_sourcechoiceAUC, Census, Directory spreadsheet, MaintainX, Resident submission
phone_sourcechoicesame choices as email_source
email_verifiedbool
phone_verifiedbool
last_verified_ondatedate a resident or staff member last confirmed the record
conflict_flagbooltwo sources disagree; queued for human review
created_ondatetime
approved_bylookup to hv_staff

The source, verified, and conflict columns exist from day one. They drive the consolidation in Phase 1 and the live percent-verified dashboard. That percentage is also the readiness gauge for electronic voting, which stays parked until verified-email coverage is high.

hv_units

The 2,580 dwellings. One row per unit. AUC is master; this table mirrors its unit list via the CSV import.

ColumnTypeNotes
unit_idGUIDprimary key
unit_numbertextcanonical display
auc_keytextAUC account or parcel ID; candidate match key for consolidation (open question)
condo_associationchoice1 through 24
modeltextone of 13 HV models
statuschoiceOwned, For Sale, Vacant, Rental
last_auc_importdatetimestamp from the CSV import flow

hv_resident_units

The join table. Solves multi-unit owners.

ColumnTypeNotes
link_idGUIDprimary key
resident_idlookup
unit_idlookup
rolechoiceOwner, Co-owner, Tenant, Authorized contact
start_datedate
end_datedatenull if current

hv_vehicles

Approved vehicles per unit. Drives barcode and gate access records.

ColumnTypeNotes
vehicle_idGUIDprimary key
unit_idlookup
maketext
modeltext
platetext
barcodetext
statuschoiceActive, Expired, Pending

hv_alternate_addresses

Snowbird and temporary mail-forwarding.

ColumnType
address_idGUID (primary key)
resident_idlookup
line1, line2, city, region, postal_codetext
start_date, end_datedate

hv_emergency_contacts

File-of-life data. Opt-in per resident.

ColumnTypeNotes
contact_idGUIDprimary key
resident_idlookup
name, relationship, phonetext
notestextmedical allergies, access notes

hv_variance_requests

Governance queue. Carol approves from Teams.

ColumnTypeNotes
request_idGUIDprimary key
resident_id, unit_idlookup
categorychoiceExterior, Landscape, Structural, Other
descriptiontext
attachmentsfile
statuschoiceSubmitted, In review, Approved, Denied, Withdrawn
decision_notestext
decided_bylookup to hv_staff
submitted_on, decided_ondatetime

hv_ev_charger_requests

Routes to Nate.

ColumnTypeNotes
request_idGUIDprimary key
resident_id, unit_idlookup
charger_model, panel_location, notestext
statuschoiceSubmitted, Site visit, Approved, Denied, Installed

hv_occupancy_surveys

Annual or periodic. Bulk data.

ColumnType
survey_idGUID (primary key)
unit_idlookup
resident_idslookup (multi)
primary_residencebool
season_start, season_enddate
submitted_ondatetime

hv_email_optins

Tracks newsletter consent before writing to Constant Contact.

ColumnTypeNotes
optin_idGUIDprimary key
resident_idlookup
emailtext
list_nametexte.g., "e-Bulletin"
statuschoiceRequested, Approved, Synced, Unsubscribed
approved_bylookup to hv_staff

hv_contact_change_requests

Upstream edit requests. Appends or updates pending approval.

ColumnTypeNotes
change_idGUIDprimary key
resident_idlookup
fieldchoicelogin_email, phone, secondary_email, address
old_value, new_valuetext
statuschoicePending, Approved, Denied, Auto-applied

hv_access_requests

Public "Request Access" submissions.

ColumnTypeNotes
request_idGUIDprimary key
first_name, last_name, email, claimed_unittext
statuschoiceSubmitted, Verified, Approved, Denied

hv_work_orders (mirror)

A thin mirror of MaintainX work orders. Dataverse caches them for reporting. WordPress still reads live from the REST proxy.

ColumnTypeNotes
work_order_idtextMaintainX ID (primary key)
unit_idlookup
titletext
statuschoiceOpen, In progress, On hold, Closed
prioritychoice
created_on, closed_on, last_synceddatetime

hv_staff

Staff directory. Scopes who can approve what.

ColumnTypeNotes
staff_idGUIDprimary key
entra_object_idtextties to SSO
nametext
rolechoiceData manager, Governance liaison, Comms, Ops, Library, Read-only
tierchoice1, 2, 3

hv_sync_log

Every Power Automate run logs here. Used to break loops and to audit.

ColumnTypeNotes
log_idGUIDprimary key
flow_nametext
directionchoiceWP-to-DV, DV-to-WP, MaintainX-to-DV, DV-to-CC, AUC-to-DV, Forms-to-DV
payload_hashtext
initiated_bytextservice account name
statuschoiceSuccess, Skipped (loop guard), Failed
timestampdatetime

IV.

Part Four

WordPress CPTs and ACF

Each post type maps to a hub. Each field group maps to a post type, a user profile, or a taxonomy.

Custom Post Types

CPTHubPurposePublic?
announcementResidentsAlerts, bulletin itemsgated
bulletin_pdfResidentsArchived bulletinsgated
form_submissionResidentsForm capture wrappergated
facilityLiving HereOne record per facilitypublic
clubLiving HereOne record per clubpublic
activityLiving HereDay trips, classes, events metadatapublic
board_meetingGovernanceAgenda, minutes, packet, videopublic
committeeGovernancePer-committee recordpublic
condoGovernanceOne record per condo associationpublic
financial_docGovernanceAudit, budget, statementpublic
buyer_pageBuyersAbout, homes, floor plans, FAQpublic
staff_contactContactDirectory entrypublic

Native page and post stay enabled for the editorial blog and one-off static pages. Gutenberg disables on every CPT above.

ACF field groups

Each group attaches to a CPT, to the user profile, or to a taxonomy.

User profile
associated_units (repeater or relationship), secondary_emails (display only), directory_opt_in (name, unit, phone, email checkboxes), magic_link_last_sent (throttle guard), dataverse_resident_id (sync key).
board_meeting
meeting_date, committee_of_record taxonomy, agenda_pdf, minutes_pdf, packet_pdf, video_url, last_updated.
committee
charter_pdf, open_or_closed, chair_contact, meetings (relationship to board_meeting).
facility
hours (repeater of day/open/close), address, reservation_form_id, photo_gallery, policies_pdf.
club
category taxonomy, meeting_day, meeting_time, location (relationship to facility), contact, how_to_join.
condo
association_number (1 to 24), board_members repeater, minutes_archive repeater (date, pdf), last_updated.
financial_doc
doc_type (Audit, Budget, Statement, Insurance), period (e.g. "2025-2026"), pdf, release_date.
announcement
alert_level (Routine, Urgent, Emergency), expires_on, target_audience (All, Condo N, Committee).
form_submission
form_type (maps to Dataverse request table), payload_json, dataverse_id, submitted_by.

Taxonomies

V.

Part Five

Relationships and decisions

The core shape of the relational model, and the source-of-truth calls that drive every flow.

Entity relationships

The core shape:

hv_residents 1---* hv_resident_units *---1 hv_units
hv_residents 1---* hv_alternate_addresses
hv_residents 1---* hv_emergency_contacts
hv_residents 1---* hv_variance_requests *---1 hv_units
hv_residents 1---* hv_ev_charger_requests *---1 hv_units
hv_residents 1---* hv_email_optins
hv_residents 1---* hv_contact_change_requests
hv_units 1---* hv_vehicles
hv_units 1---* hv_work_orders (mirror of MaintainX)
hv_staff 1---* hv_variance_requests (via decided_by)
hv_staff 1---* hv_email_optins (via approved_by)

See Diagrams for the rendered ER picture.

Source-of-truth decisions (locked)

Data point Master Mirror Notes
Units and owners of recordAUC / ADMINSDataverse (hv_units)CSV import; one-way, read-only
Financials (AP, AR, GL)AUC / ADMINSnone (summaries later, Phase 4)Never leaves AUC except reports
Resident name, email, phoneDataverseWordPressChanges start as requests upstream; fields carry source stamps
Unit assignmentsDataverseWordPress user ACFMulti-unit resolved here
Work ordersMaintainXDataverse, WordPress live-readNever stored in WP MySQL
Variance statusDataverseWordPress (read-only dashboard)
Newsletter subscribersConstant ContactDataverse opt-in record
Editorial contentWordPressnoneAnnouncements, clubs, facilities, meetings
Vehicles and barcodesDataversenone (staff only)
Emergency contactsDataversenone (staff only)

Out of scope