HV Tech Stack Chapter 03 · Flows
Power Automate moves every byte between systems. Each flow has a trigger, a target, and a loop guard.
I.
Part One
One naming rule. One request shape. One rule that stops every loop.
Every flow name reads HV-<source>-<verb>-<target>.
Examples: HV-WP-Submit-VarianceRequest,
HV-DV-Sync-ResidentRoster, HV-MX-Mirror-WorkOrders.
Every flow logs to hv_sync_log with flow_name,
direction, payload_hash, initiated_by,
and status. The log is the audit trail and the loop-break mechanism.
Every upstream submission uses the same shape.
form_submission CPT, and fires a webhook.Submitted in hv_sync_log.initiated_by. If the Power Automate service account made the update, the flow skips the webhook-back step. No loop.
Every Dataverse update carries Modified By. The service-account
identity is known. Power Automate applies this rule on every DV-to-WP flow:
if trigger.modified_by == @{variables('svc_account_id')}
-> log Skipped, exit
else
-> proceed with WP sync
Every WordPress-to-Dataverse flow writes initiated_by = 'resident'
or initiated_by = 'staff-ui'. DV-to-WP flows only fire when
initiated_by is one of those values.
II.
Part Two
Eight flows run upstream. Five run downstream. Each has one trigger, one action, one loop guard.
| Flow | Trigger | Action | Notify |
|---|---|---|---|
HV-WP-Submit-VarianceRequest |
Webhook, form_type = variance_request |
Create hv_variance_requests, status Submitted |
Adaptive Card to Carol |
HV-WP-Submit-EVChargerRequest |
Webhook, ev_charger |
Create hv_ev_charger_requests |
Card to Nate |
HV-WP-Submit-OccupancySurvey |
Webhook, occupancy_survey |
Create hv_occupancy_surveys |
None |
HV-WP-Submit-AlternateAddress |
Webhook, snowbird_address |
Create hv_alternate_addresses |
None — staff reviews in batch |
HV-WP-Submit-EmergencyContact |
Webhook, emergency_contact |
Upsert hv_emergency_contacts |
None |
HV-WP-Submit-ContactChange |
Webhook, contact_change |
Create hv_contact_change_requests |
Auto-approve for secondary email; else staff card |
HV-WP-Submit-NewsletterOptIn |
Webhook, newsletter_optin |
Create hv_email_optins, Requested |
Card to Sarah |
HV-WP-Submit-AccessRequest |
Public form, access_request |
Create hv_access_requests |
Card to office triage |
| Flow | Trigger | Action | Cadence |
|---|---|---|---|
HV-DV-Sync-ResidentRoster |
Row change on hv_residents |
Upsert wp_users; map associated_units |
Real-time; batched 02:00 for bulk moves |
HV-DV-Sync-VarianceStatus |
Row change on hv_variance_requests |
Update WP variance dashboard | Real-time |
HV-DV-Sync-EVChargerStatus |
Row change on hv_ev_charger_requests |
Update WP dashboard entry | Real-time |
HV-DV-Sync-ApprovedVehicles |
Row change on hv_vehicles |
Update resident dashboard vehicle list | Nightly 02:00 |
HV-DV-Sync-UnitAssignments |
Row change on hv_resident_units |
Rebuild associated_units ACF repeater |
Real-time |
Every downstream flow applies the loop-break rule.
Service-account writes skip the WP hop and log Skipped.
III.
Part Three
MaintainX, Constant Contact, Teams, and Excel each get their own lane.
MaintainX stays master for work orders. Residents read their own orders through a WordPress REST proxy that calls MaintainX server-side. Dataverse mirrors the data for staff reporting.
HV-MX-Mirror-WorkOrdershv_work_orders in Dataverse/wp-json/hv/v1/work-ordersassociated_units, call MaintainX REST with the API key held in wp-config.php or a secrets plugin, filter to those units, return scoped resultsHV-DV-Publish-NewsletterOptInhv_email_optins status transitions to Approvedhv_email_optins.status = SyncedThe free-tier staff (Carol, Sarah, others) never log into Power Apps. They approve from Teams.
| Card flow | Target | On approve |
|---|---|---|
HV-DV-Card-Variance | Carol, Governance channel | Write decision back to Dataverse |
HV-DV-Card-EVCharger | Nate, Infrastructure channel | Write back |
HV-DV-Card-NewsletterOptIn | Sarah | Fire HV-DV-Publish-NewsletterOptIn |
HV-DV-Card-AccessRequest | Office triage | Create hv_residents; provision WP user downstream |
The service-account Adaptive Card pattern is safe for occasional approvals. If volume grows into dozens per day across many staff, Microsoft may flag the pattern.
Tier-3 staff get Excel files on SharePoint. No Power Apps access. No Dataverse licenses.
| Flow | Cadence | Writes to | Recipients |
|---|---|---|---|
HV-DV-Export-VarianceLog | Nightly 01:30 | variance-log.xlsx | Ops staff |
HV-DV-Export-WorkOrderSummary | Nightly 01:45 | work-orders-summary.xlsx | Trades supervisors |
HV-DV-Export-ResidentRoster | Weekly Sunday 02:00 | resident-roster.xlsx | Office staff, library volunteers |
The Excel connector is the right tool at this scale. Dataverse Export to Data Lake is overkill.
IV.
Part Four
Webhook vs batch. Error handling. Rate limits. Security.
Use real-time webhooks when a human waits for the result. Use scheduled sync when batch is fine.
| Signal | Pattern | Why |
|---|---|---|
| Variance submitted | Real-time webhook | Carol needs to see it immediately |
| Access request | Real-time webhook | Office triages same day |
| Occupancy survey | Real-time webhook | Individual rows, trivial volume |
| Nightly roster reconciliation | Scheduled 02:00 | Catches name-spelling or unit-transfer drift |
| Excel reports | Scheduled | No live consumer |
| Bulk move-in season | Scheduled 02:00 | Avoids spamming webhooks |
Every flow uses the same pattern:
Configure run after set to has failed.hv_sync_log.status = Failed with the error.
For idempotency, every flow uses payload_hash to detect replays.
If the hash matches a recent log row (within 60 seconds), skip.
wp-config.php.