This guide covers creating a Power Automate cloud flow that automatically processes booking requests, creates Contact records, and sends portal invitations to new users.
Prerequisites:
- Complete Booking Request Form - Form must be functional
- Complete Identity and Contacts - Understand Contact system
- Power Automate license (included with Power Pages)
Booking Request Created
│
▼
┌───────────────────────┐
│ Check if Contact │
│ exists (by email) │
└───────────┬───────────┘
│
┌───────┴───────┐
│ │
▼ ▼
Exists? Not Exists?
│ │
│ ▼
│ ┌───────────────┐
│ │ Create Contact│
│ │ Record │
│ └───────┬───────┘
│ │
└───────┬───────┘
│
▼
┌───────────────────────┐
│ Link Contact to │
│ Booking Request │
└───────────┬───────────┘
│
▼
┌───────────────────────┐
│ Send Portal Invitation │
│ Email │
└───────────┬───────────┘
│
▼
┌───────────────────────┐
│ Update Booking Request│
│ Status to "Pending" │
└───────────────────────┘
Storing flows in solutions enables:
- Application Lifecycle Management (ALM) - Version control and deployment
- Environment Management - Move flows between dev/test/prod
- Dependency Tracking - Understand what components work together
- Backup and Recovery - Easier to restore or replicate
-
Navigate to Power Platform Admin Center → Solutions
-
Click New solution
-
Configure:
- Display Name: PawsFirst Portal Flows
- Name: PawsFirstPortalFlows (auto-generated)
- Publisher: Your organization publisher
- Version: 1.0.0.0
-
Click Create
- Open your solution
- Click New → Automation → Cloud flow → Automated
- Name the flow: Process Booking Request - User Onboarding
- Important: The flow is automatically added to your solution
-
Search for "When a row is added, modified or deleted" trigger
-
Select When a row is added
-
Configure trigger:
- Environment: Your Power Platform environment
- Table name: Booking Request (pa911_bookingrequest)
- Scope: Organization
-
Click Show advanced options:
- Filter rows:
pa911_requeststatus eq 144400000(Pending status only) - This ensures we only process new requests, not updates
- Filter rows:
-
Add action: List rows (Dataverse)
-
Configure:
- Table name: Contacts
- Filter rows:
emailaddress1 eq '@{triggerOutputs()?['body/pa911_email']}' - Select columns:
contactid,emailaddress1,firstname,lastname
-
Purpose: Check if a Contact with this email already exists
-
Add Condition control
-
Configure:
- Condition:
length(body('List_rows')?['value'])is greater than0 - This checks if any contacts were found
- Condition:
-
If yes: Contact exists → Use existing Contact
-
If no: Contact doesn't exist → Create new Contact
-
In the If no branch, add Create a new row (Dataverse)
-
Configure:
- Table name: Contacts
- Fields:
firstname:@{triggerOutputs()?['body/pa911_firstname']}lastname:@{triggerOutputs()?['body/pa911_lastname']}emailaddress1:@{triggerOutputs()?['body/pa911_email']}telephone1:@{triggerOutputs()?['body/pa911_phone']}adx_identity_logon_enabled:true(Enable portal login)
-
Name the output:
NewContact
-
In the If yes branch, add Get a row by ID (Dataverse)
-
Configure:
- Table name: Contacts
- Row ID:
@{first(body('List_rows')?['value'])?['contactid']} - Select columns:
contactid,emailaddress1,firstname,lastname
-
Name the output:
ExistingContact
- After the Condition, add Initialize variable
- Configure:
- Name: ContactId
- Type: String
- Value:
@{if(equals(length(body('List_rows')?['value']), 0), outputs('NewContact')?['body/contactid'], outputs('ExistingContact')?['body/contactid'])}
This variable will contain the Contact ID whether it was created or found.
- Add Update a row (Dataverse)
- Configure:
- Table name: Booking Request (pa911_bookingrequest)
- Row ID:
@{triggerOutputs()?['body/pa911_bookingrequestid']} - Fields:
pa911_contact:@{variables('ContactId')}pa911_requeststatus:144400000(Keep as Pending - staff will approve)
- Add Send an invitation (Power Pages)
- Configure:
- Site: Select your Power Pages site
- Contact:
@{variables('ContactId')} - Invitation Template: Default (or create custom template)
- Email:
@{triggerOutputs()?['body/pa911_email']}
Note: If "Send an invitation" action is not available, use alternative:
- Add Send an email (V2) action
- Configure:
- To:
@{triggerOutputs()?['body/pa911_email']} - Subject: Welcome to PawsFirst Veterinary Portal
- Body:
Dear @{triggerOutputs()?['body/pa911_firstname']}, Thank you for your booking request. We've created your portal account. Click the link below to register and access your account: [Your Portal URL]/signin Once registered, you can: - View your booking request status - Manage your pet information - Book additional appointments Best regards, PawsFirst Veterinary Clinic
- To:
If you want to temporarily reserve the slot when a request is created:
- Add Update a row (Dataverse)
- Configure:
- Table name: Appointment Slot (pa911_appointmentslot)
- Row ID:
@{triggerOutputs()?['body/pa911_appointmentslot']} - Fields:
pa911_isavailable:false(Mark as unavailable)
Note: You may want to make this conditional - only mark unavailable if request is approved, not just submitted.
- Wrap critical actions in Scope controls
- Add Configure run after:
- Set to run even if previous action fails
- Add error notification action
- Add Send an email (V2) action
- Configure to run If action failed
- Send notification to admin with:
- Booking Request details
- Error message
- Flow run link
┌─────────────────────────────────────┐
│ Trigger: When Booking Request Added │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ List Contacts (by email) │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Condition: Contact Exists? │
└──────┬──────────────────────┬───────┘
│ │
│ Yes │ No
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ Get Contact │ │ Create Contact │
│ by ID │ │ Record │
└──────┬───────┘ └────────┬─────────┘
│ │
└───────────┬───────────┘
│
▼
┌─────────────────────────────────────┐
│ Initialize Variable: ContactId │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Update Booking Request │
│ (Link Contact) │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Send Portal Invitation │
└─────────────────────────────────────┘
- Navigate to Power Pages → Your Site → Settings → Cloud flows
- Click Add cloud flow
- Select your flow: Process Booking Request - User Onboarding
- Click Add
Note: This step may not be required for all flow types, but ensures the flow is associated with your site for monitoring and management.
-
New User (Contact Doesn't Exist):
- Submit booking request with new email
- Verify Contact is created
- Verify invitation email is sent
- Verify Booking Request is linked to Contact
-
Existing User (Contact Exists):
- Submit booking request with existing email
- Verify existing Contact is used (not duplicated)
- Verify invitation email is sent
- Verify Booking Request is linked to Contact
-
Error Handling:
- Test with invalid email format
- Test with missing required fields
- Verify error notifications work
- Go to Power Automate → My flows
- Find your flow
- Click Run → Test
- Select Manually test option
- Provide sample Booking Request data
- Click Run flow
- Monitor execution and verify each step
-
Navigate to Power Pages → Your Site → Content → Email Templates
-
Create new template:
- Name: Booking Request Invitation
- Subject: Welcome to PawsFirst - Complete Your Registration
- Body: Custom HTML with portal link, branding, etc.
-
Update flow to use custom template
Add conditions for:
- Only send invitation if email is valid
- Skip invitation if Contact already has portal access
- Different invitation templates for new vs. existing users
Consider adding:
- Create Activity: Log invitation sent in timeline
- Update Contact: Set custom fields (source = "Booking Request")
- Notifications: Notify staff of new booking request
- Business Rules: Set default values on Contact creation
-
Open your solution
-
Click Export solution
-
Choose:
- Managed (for production)
- Unmanaged (for development)
-
Download the solution file (.zip)
- Navigate to target environment
- Go to Solutions
- Click Import solution
- Upload the .zip file
- Follow import wizard
Note: Ensure all dependencies (tables, columns) exist in target environment before importing.
- Go to Power Automate → My flows
- Click on your flow
- View Run history tab
- Click on individual runs to see details
Issue: Flow doesn't trigger
- Check: Trigger filter is correct
- Check: Booking Request record is actually created
- Check: Flow is enabled (not turned off)
Issue: Contact not created
- Check: Required fields are provided in Booking Request
- Check: Email format is valid
- Check: Table permissions allow flow to create Contacts
Issue: Invitation not sent
- Check: Power Pages action is configured correctly
- Check: Contact record has
adx_identity_logon_enabled = true - Check: Email address is valid
Issue: Flow fails with permissions error
- Check: Flow connection has appropriate Dataverse permissions
- Check: Service principal has access to required tables
- Check: Solution includes all dependencies
- Filter Early: Use trigger filters to reduce unnecessary runs
- Batch Operations: Process multiple requests together if possible
- Error Handling: Don't let one failure stop the entire flow
- Least Privilege: Grant only necessary permissions to flow
- Data Validation: Validate email and other inputs
- Audit Trail: Log important actions for compliance
- Documentation: Add comments explaining complex logic
- Naming: Use clear, descriptive action names
- Version Control: Export solutions regularly for backup
- Testing: Test in development environment first
- Custom Web Templates - Build custom components for enhanced UX
Note: Lists and Views should already be completed as it's covered on Day 1.