Skip to main content

Build an Overtime Timesheet App in Power Apps — Part 8: Build the Approval Flow for Teams and Outlook

· 40 min read
Jagdish Kumawat
Founder @ Dewiride

An overtime entry now waits for a decision, and this part builds the flow that gets one. Every pending entry goes to its department's approvers in Teams and Outlook, or to the person's manager when nobody else approves for that department. The answer is saved on the entry, approves or rejects it in SharePoint, and is emailed to the person who logged it.

This is Part 8 of a 20-part series.

  1. Part 1: Plan the App and Set Up the Demo Organization
  2. Part 2: Create the SharePoint Site and Lists
  3. Part 3: Keep Overtime Private with SharePoint Permissions
  4. Part 4: Create the Solution, Environment Variables and Canvas App
  5. Part 5: Build the Home Screen
  6. Part 6: Build the Log Overtime Screen
  7. Part 7: Build the My Overtime Screen
  8. Part 8: Build the Approval Flow for Teams and Outlook (you are here)
  9. Part 9: Show Approvers What's Waiting (coming soon)
  10. Part 10: Build the Departments Screen (coming soon)
  11. Part 11: Build the Reports Screen (coming soon)
  12. Part 12: Import the Old Excel Timesheet (coming soon)
  13. Part 13: Create the Monthly Payroll Workbook with Office Scripts (coming soon)
  14. Part 14: Build the Power BI Overtime Report (coming soon)
  15. Part 15: Share the App and Add It to Microsoft Teams (coming soon)
  16. Part 16: Test Every Role and Department (coming soon)
  17. Part 17: Build a Setup Flow That Creates the Lists (coming soon)
  18. Part 18: Run the Solution Checker and Export the Solutions (coming soon)
  19. Part 19: Install the App in a New Environment (coming soon)
  20. Part 20: Recap, Production Checklist and Next Steps (coming soon)

In Part 7, the status badges were set by hand. This part builds Overtime Approval, an automated cloud flow in the app's solution, and tries it as the demo organization's approvers in Teams, Outlook and Power Automate. Each generic task has its own guide; this part gives the values for this app, and why.

What You'll Build​

The finished flow, action by action:

Overtime Approval
When an item is created or modified OvertimeEntries, only when Status is Pending
├─ Get the department Get item: the entry's department
├─ Approver emails Select: each approver's email
├─ Approvers other than the employee Filter array: leaves out the employee
├─ Initialize ApproverEmails Initialize variable: who to ask
├─ Check for other approvers Condition: anyone left?
│ ├─ True: Ask the other approvers Set variable: their emails
│ └─ False: Get the manager Get manager (V2)
│ Ask the manager Set variable: the manager's email
├─ Time zone Compose: GMT Standard Time
├─ Shift date Compose: Saturday 07/11/2026
├─ Shift times Compose: 08:00 to 12:00
├─ Hours worked out Compose: 3.75
├─ Ask for approval Start and wait for an approval
├─ Get the entry now Get item: the entry after the answer
└─ Check the entry is unchanged Condition: same version?
├─ True: Record the decision Update item
│ Set the approval status Set content approval status
│ Tell the employee Send an email (V2)
└─ False: Stop: the entry changed Terminate: Cancelled

What an approver gets, here in the Approvals app in Microsoft Teams:

The Approval request details dialog: Requested, Overtime for Admin User, Monday 02/11/2026, 3.00 hours, the lines Department: Emergency Department, Date: Monday 02/11/2026, Time: 18:00 to 21:00, Unpaid break: 0 minutes, Hours: 3.00 and Reason: Covered the evening handover while the department was a nurse short., then Status: Requested with Olivia Bennett Pending response, a Comments box, and Reject and Approve buttons

How the Flow Works​

The decisions behind the actions:

  • It starts in SharePoint, not in the app. The trigger is SharePoint's When an item is created or modified on OvertimeEntries, so an entry changed in SharePoint goes for approval just like one saved in the app. It isn't instant: in my tests, each run started within about a minute of the save. Microsoft's SharePoint guidance says In most cases, if there's a single change in the list or library, the flow run may occur within minutes after that change.
  • Only pending entries. A trigger condition starts the flow only when Status is Pending. The flow sets Status to Approved or Rejected, so its own update doesn't start it again. In the tests, eight saves started eight runs, and the flow's own updates started none.
  • The department's approvers, but never the employee. The approvers come from the Departments list of Part 2. The person who logged the entry is left out, and when nobody is left, the request goes to their manager in Microsoft Entra. Daniel Brooks approves Radiology, so his own Radiology overtime goes to his manager.
  • The first answer decides. Any one of a department's approvers can decide, in the Teams Approvals app, from the Outlook email, or in Power Automate.
  • The flow works the hours out again from the start and finish times and the break, shows them in the request, and saves them with the decision, as Part 2 planned. Hours changed by hand in SharePoint don't survive the approval.
  • An answer counts only for the entry it was about. After the approval, the flow reads the entry again. If it changed while the request waited, the run stops, and the request for the newer version decides.
  • Two records of the decision. The Status column, which the app reads, and SharePoint's Approval Status, from the content approval in Part 3, which staff can't change. The flow sets both, with its owner's connection.
  • The employee is told by email: the decision, who made it and their comment.

Prerequisites​

Step 1: Create the Flow in the Solution​

In the Overtime Timesheet solution, select New > Automation > Cloud flow > Automated. Name the flow Overtime Approval, choose SharePoint's When an item is created or modified, and select Create (How to Create an Automated Cloud Flow in a Solution in Power Automate).

It opened in the classic designer. I chose the site and the OvertimeEntries list in the trigger and selected Save, which said Should at least contain one trigger and one action: a flow can't be saved with only its trigger (Fixed: "Should at least contain one trigger and one action" When Saving a Flow in Power Automate). The first action, Get the department, is in Step 4; with it, Save worked.

The classic designer there has no New designer toggle, so I opened the flow from My flows and selected Edit, which opens it in the new designer, with Save draft and Publish. The flow stays in the solution.

Step 2: Use the Solution's Own Connection References​

Each action's pane ends with the line Connected to and the name of a connection reference: the part of a solution that says which connection a flow uses. On my environment, the trigger said it was connected to a SharePoint reference from another solution, and Overtime Timesheet had no connection references at all. Power Automate reuses an existing reference before it creates one, and a reference outside the solution doesn't move with it (Fixed: A Flow in a Solution Uses Another Solution's Connection Reference in Power Automate).

  1. In the solution, create a SharePoint connection reference, Overtime Timesheet SharePoint, with the maker's SharePoint connection (How to Create a Connection Reference in a Solution in Power Apps).
  2. In the trigger and in each SharePoint action you add, read the Connected to line, and when it names another reference, select Change connection reference and choose Overtime Timesheet SharePoint. Until the trigger and every SharePoint action used it, each new SharePoint action got the other reference again.

The first time you add an Approvals, Office 365 Users or Office 365 Outlook action, the designer asks you to create a connection, and it adds a connection reference for it to the solution. At the end, the solution had four:

The Objects page of the Overtime Timesheet solution with All (11) and a Connection references (4) group, listing the connection references Office 365 Outlook, Office 365 Users, Overtime Timesheet SharePoint and Standard approvals with the flow, the app and the environment variables

The three the designer created have names that start with new_ in the solution, not the publisher's dewiride_, like the one I created. The flow works with them all the same.

Step 3: Start the Flow Only for Pending Entries​

The site and the list. In the trigger, set Site Address to the Overtime Timesheet Site environment variable and List Name to OvertimeEntries. They're in the dynamic content list under Parameters (How to Use Environment Variables in a Power Automate Flow). Every SharePoint action in the flow uses them the same way, so the flow follows the solution to another environment:

The trigger's pane in the new designer with Site Address set to the environment variable Overtime Times… and List Name set to the environment variable OvertimeEntries…, Advanced parameters Showing 0 of 1, and the line Connected to Overtime Timesheet SharePoint. with Change connection reference, next to the canvas with the trigger and a Get item action

The trigger condition. On the trigger's Settings tab, under Trigger conditions, select Add and enter (How to Add a Trigger Condition in Power Automate):

When an item is created or modified → Settings → Trigger conditions
@equals(triggerOutputs()?['body/Status/Value'], 'Pending')

A macOS-style code window titled When an item is created or modified → Trigger conditions, showing the expression @equals(triggerOutputs()?['body/Status/Value'], 'Pending')

Status is a Choice column, so the condition reads its Value. A trigger condition starts with @, and when it's false, the flow doesn't run and nothing is added to its run history. That's what stops the loop Microsoft's guidance on infinite loops warns about: Cloud flows can trigger themselves, creating an infinite loop. Leave Split on on, as it is, so each changed entry gets its own run.

Step 4: Find the Department's Approvers​

Three actions, after the trigger:

ActionNameSettings
SharePoint Get item (guide)Get the departmentSite Address Overtime Timesheet Site, List Name Departments, Id the trigger's DepartmentId
Select (guide)Approver emailsFrom the Approvers of Get the department; Map, in text mode, the Approvers Email token
Filter array (guide)Approvers other than the employeeFrom the Output of Approver emails; the condition below, in advanced mode

Approvers is a Person column with several people, and Select turns it into a list of their emails. The Approvers Email token is this expression:

Approver emails → Map (text mode)
item()?['Email']

Filter array keeps every email that isn't the email of the person who created the entry. Both sides go through toLower, so capital letters don't matter:

Approvers other than the employee → Filter Query (advanced mode)
@not(equals(toLower(item()), toLower(triggerOutputs()?['body/Author/Email'])))

The Get the department action:

The Get the department pane with Site Address set to the Overtime Times… token, List Name set to the Departments (d… token, Id set to the DepartmentId token, and the line Connected to Overtime Timesheet SharePoint.

Step 5: Choose Who to Ask​

The approval goes to the emails in one variable, which the flow fills in one of two ways.

The variable. Add Initialize variable, Initialize ApproverEmails: Name ApproverEmails, Type String, no value (How to Use Variables in Power Automate). It goes before the condition, because a variable can't be initialized inside one.

The condition. Add a Condition, Check for other approvers, that checks whether the filter left anyone (How to Add a Condition in Power Automate and How to Count the Items in an Array in Power Automate with length()): this expression is greater than 0.

Check for other approvers → left value
length(body('Approvers_other_than_the_employee'))

True: ask them. Add Set variable, Ask the other approvers, with Name ApproverEmails and this Value. Assigned to takes several people separated by semicolons (How to Join an Array into Text in Power Automate):

Ask the other approvers → Value
join(body('Approvers_other_than_the_employee'), ';')

False: ask the manager. Add the Office 365 Users action Get manager (V2), Get the manager, with User (UPN) set to the trigger's Created By Email. Then Set variable, Ask the manager, with the manager's email, the Mail token of Get the manager (How to Get a User's Manager in Power Automate):

Ask the manager → Value
outputs('Get_the_manager')?['body/mail']

The condition, with its comparison:

The Check for other approvers pane on its Parameters tab with the Condition expression: And, then a row with the expression token length(...), the operator is greater t…, and the value 0

:::warning No apostrophes or question marks in action names Expressions refer to an action by its name, with underscores for spaces, such as outputs('Get_the_manager'). My first names for three of this flow's actions were Get the employee's manager, Anyone left to approve? and Unchanged while waiting?. The designer accepted them, and publishing rejected them, in Step 10. :::

Step 6: Work Out the Date, Times and Hours​

The request shows the shift in UK time, with the hours the flow works out. Four Compose actions (How to Use the Compose Action in Power Automate), each holding a value the later actions use:

NameInputsExample
Time zoneGMT Standard Time
Shift dateThe first expression belowSaturday 07/11/2026
Shift timesThe second expression below08:00 to 12:00
Hours worked outThe third expression below3.75

Dates and times. SharePoint gives the flow its date and time columns in UTC, and convertFromUtc() turns them into the time zone's local time, formatted. GMT Standard Time is the Windows name for UK time, which is an hour ahead of UTC in summer (How to Convert UTC to Local Time in Power Automate with convertFromUtc):

Shift date → Inputs
convertFromUtc(triggerOutputs()?['body/StartTime'], outputs('Time_zone'), 'dddd dd/MM/yyyy')

Shift times adds the next day when a shift ends on the day after it starts:

Shift times → Inputs
concat(convertFromUtc(triggerOutputs()?['body/StartTime'], outputs('Time_zone'), 'HH:mm'), ' to ', convertFromUtc(triggerOutputs()?['body/EndTime'], outputs('Time_zone'), 'HH:mm'), if(equals(convertFromUtc(triggerOutputs()?['body/StartTime'], outputs('Time_zone'), 'yyyy-MM-dd'), convertFromUtc(triggerOutputs()?['body/EndTime'], outputs('Time_zone'), 'yyyy-MM-dd')), '', ' the next day'))

The hours. To get a number, the expression subtracts the times' ticks: the minutes between the start and finish, less the unpaid break, divided by 60.0, as text with two decimals (How to Work Out the Hours Between Two Times in Power Automate and How to Format a Number with Two Decimal Places in Power Automate). Both times are in UTC, so the difference is the time that really passed, on the nights the clocks change too:

Hours worked out → Inputs
formatNumber(div(sub(div(sub(ticks(triggerOutputs()?['body/EndTime']), ticks(triggerOutputs()?['body/StartTime'])), 600000000), coalesce(triggerOutputs()?['body/BreakMinutes'], 0)), 60.0), '0.00')

The Hours worked out pane with Inputs set to a formatNumber(...) token and the expression editor beside it showing the whole formatNumber, div, sub, ticks and coalesce expression

Step 7: Ask for Approval​

Add Start and wait for an approval from Standard approvals, Ask for approval (How to Send an Approval Request in Power Automate):

SettingValue
Approval typeApprove/Reject - First to respond
TitleThe first block below
Assigned toThe ApproverEmails variable: select the gear next to the box, then Use dynamic content
DetailsThe second block below
RequestorThe trigger's Created By Email
Enable notificationsYes, so approvers get an email
Enable reassignmentNo, so only the department's approvers decide
Ask for approval → Title
Overtime for @{triggerBody()?['Author/DisplayName']}, @{outputs('Shift_date')}, @{outputs('Hours_worked_out')} hours
Ask for approval → Details
Department: @{outputs('Get_the_department')?['body/Department']}

Date: @{outputs('Shift_date')}

Time: @{outputs('Shift_times')}

Unpaid break: @{triggerBody()?['BreakMinutes']} minutes

Hours: @{outputs('Hours_worked_out')}

Reason: @{triggerBody()?['Reason']}

The Details box says Markdown supported, but Microsoft says Markdown isn't supported in the Teams Approvals app, so the details are plain lines with an empty line between them. They showed as separate lines in Teams and in Outlook.

The Ask for approval pane: Approval type Approve/Reject - First to respond; Title Overtime for, Created By DisplayName, the two Outputs tokens and hours; Assigned to ApproverEmails; Details with Department, Date, Time, Unpaid break, Hours and Reason lines; an empty Item link and Item link description; Advanced parameters Showing 4 of 4 with Requestor Created By Email, Enable notifications Yes, Enable reassignment No and Attachments; and the line Connected to Standard approvals.

Step 8: Check the Entry Hasn't Changed​

The flow waits at Ask for approval until someone answers, which can take hours, and the entry can change in the meantime. Each save starts a new run with a new request, so an answer to an old request mustn't decide the new version (How to Check an Item Hasn't Changed During an Approval in Power Automate):

  1. Add a SharePoint Get item, Get the entry now, on OvertimeEntries with the trigger's ID.
  2. Add a Condition, Check the entry is unchanged, comparing the entry's version number now with the version that started the run:
LeftOperatorRight
outputs('Get_the_entry_now')?['body/{VersionNumber}']is equal totriggerBody()?['{VersionNumber}']

The Check the entry is unchanged pane with the condition: And, then the token body/VersionN… from SharePoint, with VersionNumber in braces, is equal to, and the token VersionNumber from SharePoint

Step 9: Save the Decision and Tell the Employee​

The condition's True branch has three actions.

Record the decision. A SharePoint Update item on OvertimeEntries with the trigger's ID (How to Update a SharePoint List Item in Power Automate). Update item needs a value for every required column, so the required columns get the trigger's own values, and these columns get the decision (How to Get the First Item of an Array in Power Automate and How to Use the if() Function in Power Automate):

ColumnValue
Hoursfloat(outputs('Hours_worked_out'))
Status Valueif(equals(outputs('Ask_for_approval')?['body/outcome'], 'Approve'), 'Approved', 'Rejected')
ApproverCommentfirst(outputs('Ask_for_approval')?['body/responses'])?['comments']
DecisionByfirst(outputs('Ask_for_approval')?['body/responses'])?['responder']?['displayName']
DecisionOnThe Completion date of Ask for approval

Hours worked out is text, so float() turns it into a number for the Hours column.

Set the approval status. A SharePoint Set content approval status (How to Approve or Reject a SharePoint Item in Power Automate):

SettingValue
Site AddressThe Overtime Timesheet Site variable
Library NameThe OvertimeEntries variable
IdThe trigger's ID
Actionif(equals(outputs('Ask_for_approval')?['body/outcome'], 'Approve'), 'Approve', 'Reject')
Commentsfirst(outputs('Ask_for_approval')?['body/responses'])?['comments']
ETagoutputs('Record_the_decision')?['body/@odata.etag']

It comes after Record the decision because, with content approval on, every edit sets the approval status back to Pending, the flow's own update included. The ETag from that update is the version it just wrote. My first run, Olivia's in Step 11, ran before I added the ETag, and SharePoint took the approval without one; every run after it used the ETag.

Tell the employee. An Office 365 Outlook Send an email (V2), with a connection named Overtime Timesheet Outlook (How to Send an Email in Power Automate). To is the trigger's Created By Email, and the subject and body use the flow's values:

Tell the employee → Subject
Overtime @{outputs('Record_the_decision')?['body/Status/Value']}: @{outputs('Shift_date')}, @{outputs('Hours_worked_out')} hours
Tell the employee → Body (tokens in brackets)
Hello [Created By DisplayName],
Your overtime on [Shift date], [Shift times], was [Status Value] by [DecisionBy].
Hours: [Hours worked out]
Department: [Department]
Comment: [ApproverComment]
You can see all your entries on the My overtime screen of the Overtime Timesheet app.

The Tell the employee pane: To set to Created By Email; Subject Overtime, the Status Value token, a colon, two Body tokens and hours; a Body box with Hello and the Created By Displ… token, Your overtime on two Body tokens, was Status Value by DecisionBy, Hours with a Body token, Department with the Department token, Comment with the ApproverComm… token, and the line about the My overtime screen; Importance Normal; and Connected to Office 365 Outlook.

The email comes from the mailbox of the connection's account, here the maker's.

The False branch. Add Terminate, Stop: the entry changed, with Status set to Cancelled (How to Stop a Flow Run with Terminate in Power Automate). The run ends there, records nothing and sends nothing; the newer request decides.

Step 10: Save, Check and Publish​

Select Save draft, then Flow checker (How to Check a Flow for Errors with Flow Checker in Power Automate). It listed no errors and no warnings. A draft doesn't run, so select Publish (How to Save a Draft and Publish a Flow in Power Automate).

Publishing stopped twice, on the names from Step 5's warning, and Flow checker had found neither:

  1. The input parameter(s) of operation 'Ask_the_manager' contains invalid expression(s). The manager action was still Get the employee's manager, and the apostrophe broke the expression that read its output. I renamed it Get the manager and picked its Mail token again: Fixed: "The input parameter(s) of operation contains invalid expression(s)" in Power Automate.
  2. Flow save failed with code 'InvalidWorkflowRunActionName', for the condition Anyone left to approve?: action names can't contain ?, or <, >, %, &, \ and /. I renamed both conditions, to Check for other approvers and Check the entry is unchanged: Fixed: "The provided workflow run action name has these invalid characters" (InvalidWorkflowRunActionName) in Power Automate.

The third publish worked:

The new designer with Overtime Approval • Published and a green banner, outlined, reading Your flow is ready to go. We recommend you test it., above the flow: When an item is created or modified, Get the department, Approver emails, Approvers other than the employee, Initialize ApproverEmails, and the condition Check for other approvers with Ask the other approvers under True and Get the manager and Ask the manager under False

From then on, every save of a pending entry started a run.

Step 11: Approve an Entry in Teams​

The app isn't shared until Part 15, so in these tests the maker used the app, and Aisha Khan, Maya Patel and Daniel Brooks changed their entries in the OvertimeEntries list in SharePoint, each signed in as themselves.

Entries saved before the flow was published don't start it. The maker's November entries had been Pending since Parts 6 and 7, with no request. Saving one again started a run: I opened 2 November, in the Emergency Department, with Edit on the My Overtime screen and saved it. The run started within a minute, and the request waited for Olivia Bennett in the Approvals app in Teams; it's the request at the top of this post (How to Approve a Request in the Microsoft Teams Approvals App). She wrote Thanks for covering the handover. and selected Approve:

The Approvals app on the Received tab with the same row, outlined, now with status Approved

Step 12: Approve and Reject in Outlook​

An approval. Aisha Khan corrected the reason of her 7 November entry in SharePoint. With notifications on, Olivia also got the request as an email she could answer in place (How to Approve a Request from an Outlook Email):

The email Overtime for Aisha Khan, Saturday 07/11/2026, 4.00 hours from Microsoft Power Automate to Olivia Bennett: Approvals | Power Automate, the title, Created by Admin User, Requested for Aisha Khan, Date Created Sunday, 8 November 2026 16:47, the lines Department: Emergency Department, Date: Saturday 07/11/2026, Time: 07:00 to 11:00, Unpaid break: 0 minutes, Hours: 4.00 and Reason: Extra cover for winter pressures until the day team arrived at 11:00, the Approve and Reject buttons, and a footer about the flow that sent it

She approved it with the comment Approved. Thank you for staying on., and Aisha's email arrived a few seconds later:

An email from Admin User to Aisha Khan with the subject Overtime Approved: Saturday 07/11/2026, 4.00 hours, reading Hello Aisha Khan, Your overtime on Saturday 07/11/2026, 07:00 to 11:00, was Approved by Olivia Bennett., Hours: 4.00, Department: Emergency Department, Comment: Approved. Thank you for staying on., and You can see all your entries on the My overtime screen of the Overtime Timesheet app.

A rejection, with the hours checked. Maya Patel's 7 November entry runs from 08:00 to 12:00 with a 15-minute break: 3.75 hours. In SharePoint, she changed its Hours to 4.00:

The OvertimeEntries list with one row: WorkDate 07/11/2026, StartTime 07/11/2026 08:00, EndTime 07/11/2026 12:00, BreakMinutes 15, Hours 4.00, DepartmentId 2, Department Radiology, Reason MRI backlog list, and Sum 4.00

The request Daniel Brooks got said 3.75 hours, worked out from the times:

The email Overtime for Maya Patel, Saturday 07/11/2026, 3.75 hours to Daniel Brooks, Created by Admin User, Requested for Maya Patel, with the shift's details and the Approve and Reject buttons

He rejected it: Please add which MRI list you covered and who asked you to stay. The flow saved the hours it worked out, and the decision in both Status and Approval Status:

The OvertimeEntries row with WorkDate 07/11/2026, StartTime 08:00, EndTime 12:00, BreakMinutes 15, Hours 3.75, DepartmentId 2 and Department Radiology, and Sum 3.75

The same row with Status Rejected, the comment Please add which MRI list you covered and who asked you to stay., DecisionBy Daniel Brooks, DecisionOn 08/11/2026 16:57 and Approval Status Rejected

And Maya's email told her why:

An email from Admin User to Maya Patel with the subject Overtime Rejected: Saturday 07/11/2026, 3.75 hours, saying it was Rejected by Daniel Brooks, Hours: 3.75, Department: Radiology, and Comment: Please add which MRI list you covered and who asked you to stay.

Step 13: Change an Entry While It Waits​

Sending an entry again from SharePoint. A rejected entry keeps its Status of Rejected when it's edited in SharePoint, so the trigger condition doesn't start the flow. To send it for approval again, set Status back to Pending in the same edit; the app does it on every save. The same goes for an approved entry edited in SharePoint, which Part 3 showed goes back to Pending in Approval Status. Maya added what Daniel asked for and set Status to Pending:

The SharePoint edit form with Reason Saturday MRI backlog list in Radiology. Daniel asked me to stay until 12:00., EmployeeName Maya Patel, EmployeeEmail maya.patel@example.com, Status Pending, and the Save and Cancel buttons

:::tip Close the Status drop-down by selecting another field While setting Status in SharePoint's edit panel, I once pressed Esc to close the drop-down, and the whole panel closed without saving. Selecting another field's label closes the drop-down and keeps the panel open. :::

A change while the request waits. The request reached Daniel at 17:06. Before he answered, Maya edited the entry again, adding the number of scans, and a second request arrived at 17:08:

Daniel's inbox with two emails from Microsoft Power Automate, both Overtime for Maya Patel, Saturday…, at 17:08 and 17:06, each with Requested for Maya Patel

Daniel approved the older request first. Its run had started from version 4.0 of the entry, and Get the entry now read version 5.0, so it stopped at Stop: the entry changed, and nothing was recorded (How to See a Flow's Run History in Power Automate):

The run view: Ask for approval succeeded after 3m 8s, Get the entry now succeeded, Check the entry is unchanged marked Terminated; under True, Record the decision, Set the approval status and Tell the employee skipped; under False, Stop: the entry changed succeeded

Then he approved the newer request, which recorded the approval:

The OvertimeEntries row with Reason Saturday MRI backlog list in Radiology, 8 scans. Daniel asked me to stay until 12:00., Status Approved, ApproverComment Approved. Thanks for clearing the backlog., DecisionBy Daniel Brooks, DecisionOn 08/11/2026 17:11 and Approval Status Approved

Nothing told Daniel that his first answer was set aside: the old request showed as approved like any other. Approvers should answer the newest request for an entry.

Step 14: Send an Approver's Own Overtime to Their Manager​

Daniel Brooks logged his own overtime for 5 November, 17:00 to 19:30 in Radiology, in SharePoint. He's Radiology's only approver, so Approvers other than the employee came out empty, and the run took the False branch:

The run view of the condition Check for other approvers: under True, Ask the other approvers was skipped; under False, Get the manager succeeded in 0.6s and Ask the manager succeeded

Get the manager returned Daniel's manager from Microsoft Entra, Admin User, and the request went to the maker, who answered it in Power Automate's Approvals (How to Respond to Approvals in Power Automate):

The Respond: Approve pane: Overview with the approval Overtime for Daniel Brooks, Thursday 05/11/2026, 2.50 hours, Requester Daniel Brooks and Received Nov 8, 05:20 PM (2 min ago); Details with Department: Radiology, Date: Thursday 05/11/2026, Time: 17:00 to 19:30, Unpaid break: 0 minutes, Hours: 2.50 and Reason: Covered the evening CT list after two radiographers called in sick.; Choose your response set to Approve; and Add a comment with Approved. Thank you for covering the CT list.

So every approver needs a manager in Microsoft Entra, as Part 1 set them. In Power Apps, the same lookup fails for a person without one: Fixed: Office365Users.ManagerV2 Failed: Resource 'manager' Does Not Exist.

Step 15: See the Decisions in the App​

The maker's Radiology entries for 1 and 6 November went to Daniel when I saved them again from the app. He rejected 6 November, Please check the finish time. The CT list closed at 20:00., and then approved 1 November. Refresh on the My Overtime screen between the two showed each status the flow can set:

The My overtime screen for November 2026 with Total for November 2026: 7.00 hours, the weeks Mon 26/10/2026 to Sun 01/11/2026: 6.00 hours and Mon 02/11/2026 to Sun 08/11/2026: 3.00 hours, and three entries: Sun 01/11/2026, 09:00 to 13:00, 4.00 hours, Radiology, Pending with an Edit button; Mon 02/11/2026, 18:00 to 21:00, 3.00 hours, Emergency Department, Approved with no Edit button; and Fri 06/11/2026, 17:00 to 21:00, 4.00 hours, Radiology, Rejected with an Edit button

The approved entry has no Edit button, and the rejected one isn't in the totals, as Part 7 built them. Nothing in the app changed in this part: the badges read the Status the flow saves.

Common Mistakes​

MistakeWhat happensDo this instead
No trigger conditionThe flow's own update can start it again@equals(triggerOutputs()?['body/Status/Value'], 'Pending')
An apostrophe or question mark in an action namePublishing failsNames like Get the manager and Check for other approvers
Saving the decision without reading the entry againAn answer to an old request decides a newer versionGet the entry now and the version check
Setting the approval status before Record the decisionThe update sets it back to PendingSet it last, with the update's ETag
Saving the hours the entry carriesHours changed by hand get approvedWork them out from the times
A SharePoint action on another solution's connection referenceThe solution doesn't carry what the flow needsChange connection reference on each one
Typing the variable into Assigned toIt searches for a person by that textGear, then Use dynamic content

Troubleshooting​

SymptomLikely causeFix
No request for an entryIt was saved before the flow was published, or its Status isn't PendingSave it again with Status Pending
The request comes a minute or more after the saveThe trigger isn't instantWait a few minutes before checking
Publishing fails with invalid expression(s)An apostrophe in the name of an action an expression readsRename it and pick its token again
Publishing fails with InvalidWorkflowRunActionNameA ? or another listed symbol in an action nameRename the action
A run shows CanceledThe entry changed while its request waitedExpected: the newer request decides
A reopened condition shows an extra empty rowThe designer shows one; Code view has only the real comparisonLeave it
Get the manager failsThe person may have no manager in Microsoft EntraSet their manager
An entry edited in SharePoint never goes for approvalIts Status is still Approved or RejectedSet Status to Pending in the same edit

FAQ​

Why do the requests say "Created by Admin User"?​

Approvals always show the flow's creator. Microsoft's connector reference says The creator of the flow will always be shown in the Approval details (email content and all clients). This is to prevent spoofing of approval sender identities. In production, create the flow and its Outlook connection with an account meant for the app, so requests and emails show that account rather than a person.

What happens if nobody answers?​

The run waits, within a limit. Microsoft's limits page says After 30 days, any pending steps time out, and its approvals known issues say An approval flow can wait for 28 days. The flow records nothing until someone answers, so the entry stays Pending; saving it again sends a new request.

Can staff approve their own overtime?​

Not through the flow: it leaves the person who logged the entry out of the request, and asks their manager when nobody else is left. Not in SharePoint either: approving needs Approve Items, which staff don't have (Part 3). They can edit their own entry's Status column, which is why Part 3 says not to trust it on its own; Approval Status is the record they can't change.

Why both Status and Approval Status?​

The app and its filters read Status, an ordinary Choice column. Approval Status is SharePoint's own record of the decision, and only people with approval rights can change it. The flow writes the same decision to both.

Does this need premium licenses?​

No. SharePoint, Approvals, Office 365 Users and Office 365 Outlook are standard connectors, and the flow's details page says This flow runs on owner's plan.

Conclusion​

Each overtime entry now gets a decision:

  • Overtime Approval, an automated cloud flow in the app's solution, with the solution's own connection references and its SharePoint values from environment variables;
  • a trigger condition that starts it only for pending entries, so its own updates don't start it again;
  • requests to the department's approvers, leaving out the person who logged the entry, or to their manager when nobody else is left;
  • the date, times and hours worked out again, in UK time, for the request and the record;
  • answers in Teams, Outlook or Power Automate, with the first one deciding;
  • a check that the entry hasn't changed, so an old answer never decides a newer version;
  • the decision saved in Status and in SharePoint's Approval Status, and an email to the employee.

Approvers find each request in Teams and Outlook. Part 9 gives them a screen in the app with everything waiting for them.

Additional Resources​

← Previous: Part 7: Build the My Overtime Screen Next → Part 9: Show Approvers What's Waiting (coming soon)