STM Streamline · Architecture Documentation · 2026

WORKFLOW
OPTIMIZATION

Left → right: manual process to enterprise automation. v2.0 based on actual Power Automate flow definitions.

Manual
v1.0 Legacy
v2.0 Legacy
v3.0 Current
Manual Process
Human
Daily oversight · no automation
Fallback / Escalation
1
Access · 8:00 AM
Open SharePoint STM list
Monitor opens the list manually each morning and applies overdue view
2
Filter
Schedule ≤ Today AND Actual = Empty
Surfaces all overdue items across all 8 phases manually
3
Contact
Call / message responsible party
QA Team, CI, PE, or VC depending on phase
"H611-27 Drop Test overdue — Mar 23, actual?"
↓ outcome from contact
Completed
Actual = today
Mark phase done
Rescheduled
Update schedule date
New date from party
4
Document
Add note to item
"Rescheduled 3/23→3/27 per J.Tran 3/25"
5
Save
Save record to SharePoint
Human audit trail — who changed what and when
When to use
Automation unavailable
Critical escalations
Flow runtime errors
Maintenance windows
Trade-offs
15–30 min/day per monitor
Risk of human error
Max ~100 items/monitor
Handles any edge case
Rich context in notes
Version 1.0
Baseline
Single monolithic loop
Legacy / Deprecated
1
Trigger · Recurrence
Once daily — 5:00 PM SE Asia
Single fixed run per day, no second cycle
2
Read · SharePoint
Get all STM list items
Full unfiltered list read
3
Loop · Apply to each
Process all 8 phases per item
Kickoff, WW Review, WW Signoff, Drop Test, Final PPR Review, PPR Signoff, Pilot Run, AFSR — all in one massive loop with no concurrency cap
4
Filter
Find overdue & 24h items
Schedule < Today OR ≤ Now+24h
↓ two branches in the same flow
Overdue
Post Teams card
One card per item
Within 24h
Post Teams card
One card per item
5
Wait · blocks entire flow
Wait for adaptive card response
Whole flow paused — no timeout set. A single non-response hangs everything.
6
Update · SharePoint
Patch phase schedule column
Writes new date to hardcoded field reference
Problems
Only 1 run/day at 5 PM
100 items = 100 cards
No response timeout
One failure = full stop
No fault isolation
Scheduler & notifier coupled
Version 2.0
By Item
Queue-based decoupling
Legacy / Deprecated
Flow 1 — Scheduler
1
Trigger · Recurrence
Daily at 17:00 & 20:00 SE Asia
Two cycles per day — 5 PM and 8 PM
schedule.hours: ["17", "20"]
2
Init · Variable
Initialize TrackingList array
TrackingList = [] (type: array)
3
Read · SharePoint GetItems
Get items from STM list
table: 87653ec3 · Select maps 59 fields (field_1 → field_59) to readable names
4
Filter · Query
Filter out unassigned items
where: vendorNumber != null
5
Loop · Apply to each (concurrency: 50)
Per item: compose all 8 phases
Compose_all_Phases builds [{name, actual, deadline, schedule, status}×8] → Filter_Incomplete keeps actual=null rows → first() = current phase → Compose_Result_Object → Append to TrackingList
status: if(empty(currentPhase), 'Completed', 'In Progress')
6
Filter · Query
Filter events within 24 hours
Keeps items where schedule is not empty AND ≤ now+24h · then Set_variable overwrites TrackingList with this filtered result
schedule <= addHours(utcNow(), 24)
7
Loop · Apply to each (concurrency: 40)
Branch: overdue vs upcoming → enqueue
Condition: schedule < utcNow() → determines card type
↓ if schedule < utcNow()
True → Overdue
Create_item in Activity List
AdaptiveCardOption = "Overdue" · Status = "Pending"
False → 24hrs
Create_item_1 in Activity List
AdaptiveCardOption = "Within 24hrs" · Status = "Pending"
Activity List — message queue (table: 8dc70288)
Title = itemNumber · OriginalItemID = STM item ID
VendorName · Schedule · CurrentPhase
Status = "Pending" · AdaptiveCardOption = "Overdue" | "Within 24hrs"
↓ triggers Flow 2 on each new item
Flow 2 — Worker (Adaptive Card Bot)
8
Trigger · When item created
Fires on each new Activity List item
Polls every 1 min · splitOn processes each item independently
table: 8dc70288 · poll interval: 1min
9
Init + Parse JSON
Init card string var · parse OriginalItemID
Wraps OriginalItemID safely into JSON array so downstream Switch can read [0].id
if(empty(id),'[]', if(startsWith(id,'['),id,concat('[',id,']')))
10
Switch · AdaptiveCardOption/Value
Set adaptive card body based on card type
↓ switch on AdaptiveCardOption
"Overdue"
Reschedule card
Input.Date + Input.Time · Action.Submit "updateSchedule"
"Within 24hrs"
Meeting or change card
Action.Submit "createMeeting" OR Action.ShowCard (new date/time)
11
Post + Wait · Teams · timeout: 3h
Post card to JohTran@Ashleyfurniture.com
Flow bot → Chat with Flow bot · waits up to 3 hours for user response
↓ if userChoice = "createMeeting"?
Yes
Create Teams meeting
start = Schedule · end = +1h · attendee = JohTran · Activity item → Completed
No → Reschedule
Compose NewDate
concat(newDate,'T',newTime,':00Z') → Switch on CurrentPhase → patch field
12
Switch · CurrentPhase → patch field
Update correct column in STM list
Kickoff→field_11 · WW Review→field_15 · WW Signoff→field_19
Drop Test→field_23 · Final PPR→field_27 · PPR Signoff→field_31
Pilot Run→field_39 · AFSR→field_45
13
Update · Activity List item
Log response & mark Completed
Writes NewSchedule, PIC (responder email), TimeEdited, Status = "Completed"
PIC = responder.email · TimeEdited = responseTime
Gains vs v1.0
2 runs/day (17:00 + 20:00)
Decoupled — 2 independent flows
Instant trigger via queue
3h timeout — no infinite wait
PIC + timestamp audit trail
Concurrency: 50 + 40 parallel
Still to improve
Phase fields hardcoded (Switch)
Recipient hardcoded (JohTran)
Single environment only
Version 3.0 · Current
By Group
Config-driven · multi-env
★ current
Flow 1 — Dispatcher (enhanced)
1
Trigger · Recurrence
Same: 17:00 & 20:00 SE Asia
No change to trigger schedule
2
Init · EnvironmentConfig
Load environment settings object
Replaces all hardcoded URLs and table IDs
{ siteUrl, trackingListId, activityListId,
notifyList, environ: DEV|UAT|PROD }
3
Read + Select + Filter
Same 59-field get + vendorNumber filter
Identical to v2 — siteUrl and tableId now come from EnvironmentConfig
4
Loop · Apply to each
Same 8-phase composition as v2
Compose_all_Phases → filter incomplete → first() → result object → append
5
Build · Checkbox payload
Generate Input.Toggle per item
Dynamic checkbox array — user can select multiple items to bundle into one meeting
Input.Toggle: { id, itemNumber, phase, schedule }
6
Filter + Branch + Enqueue
Same overdue / 24h split → Activity List
Same condition as v2; payload enriched with toggles and pre-computed next-day meeting time
meetingTime: addDays(utcNow(), 1)
Activity List — enriched queue
Same fields as v2 + EnvironmentConfig ref
Input.Toggle checkbox array (multi-select)
Pre-computed meetingTime with fallback
↓ triggers Flow 2 on each new item
Flow 2 — Worker (enhanced)
7
Trigger + Init + Parse
Same trigger as v2 · same OriginalItemID parse
No change to this plumbing
8
Switch · Build card
Same Overdue / Within 24hrs card types
Cards now include dynamically generated Input.Toggle checkboxes for multi-item selection
9
Post + Wait · timeout: 3h
Post to dynamic recipient list
Recipients from EnvironmentConfig.notifyList — not hardcoded to a single email
recipients: config.notifyList (not "JohTran@...")
10
Filter selected items
Extract checked toggles
Filter where toggle value = 'True' — user bundles multiple items into one meeting
where: toggle.value equals 'True'
11
Create Teams meeting · smart time
Auto-schedule with fallback time
if(empty(meetingTime), '00:00:00', meetingTime)
Agenda HTML built from selected item list
12
Switch · PhaseColumnMap (config-driven)
Patch correct field via config map
Replaces 8 hardcoded Switch cases with a single config-driven lookup — no code changes to add a phase
PhaseColumnMap["Drop Test"] → field_23
PhaseColumnMap["Pilot Run"] → field_39
PhaseColumnMap["AFSR"] → field_45
13
Update · Activity List + full audit
Same log fields as v2 + OriginalItemID trace
NewSchedule · PIC · TimeEdited · Status="Completed"
Gains vs v2.0
EnvironmentConfigDEV/UAT/PROD — zero code changes per environment
PhaseColumnMapReplaces 8 Switch cases — add phases via config only
Dynamic recipientsnotifyList from config — not hardcoded to JohTran
Multi-item checkboxesInput.Toggle bundles multiple items into one meeting
Smart time fallbackif(empty(meetingTime), '00:00:00', meetingTime)
Current Limitation
Not centralized recipients — manual list management
Future Application
Deadline checking — auto-escalation before overdue
STM Streamline · Ashley Furniture Industries, LLC · Strategy Execution
By: Johnniee Tri Tran