Dynamics 365 Project Service Automation: Using Flow to pass values from custom fields on Actuals throughout PSA’s end-to-end process

Tested on:
Dynamics 365 CE version 9.1, PSA solution version 3.4, Unified Interface

One of the interesting challenges in PSA has always been passing values from custom fields on Actuals throughout PSA’s end-to-end process. With end-to-end I mean the process of Time Entry to Invoice, keeping in mind that Invoices can be corrected and reconfirmed. Before we dive into the Flows that make this possible, it’s important to understand the very basics of PSA’s data model in the sense of Actuals, Journal Lines, Transaction Origins and Transaction Connections.

Limitations in the Flows covered on this blog post

The Flows covered on this blog post have some limitations. These limitations are fairly easy to overcome by refining these Flows to cover a broader set of functionality. Consider the following points when using these Flows:

  • The Flows covered on this blog post do not take changes in the following entities and records into account. You can broaden the scope of these Flows to include these entities: Journal Lines, Invoice Line Details, Expenses. Consider your financial process and integration scenarios when planning your scenario with these Flows. Below are use case examples where these Flows do not update records:
    • Journal Lines are created from Time Entries or Expenses.
    • Actuals are for Expenses.
    • Actuals are corrected with Journals.
    • Invoice Line Details are created when an Invoice is created from a Project Contract or with Batch Jobs.
  • The Power Platform October ’18 update introduces options around correcting Actuals post Project Approval i.e when Cost and Unbilled Sales Actuals have been created. As these features are not GA in their full scope at the time of writing this blog post, the Flows covered on this post may not support the upcoming functionalities.

Actuals in PSA’s end-to-end process

PSA’s end-to-end process for the creation of financial data starts from Time Entries and ends at invoicing. During this process, PSA creates various different records under the hood. The typical life cycle of Time Entries can be seen in image 1 below. The example in the image doesn’t take corrected invoices, revered Billed Sales Actuals and the following new Unbilled Sales Actuals into account.

When corrected Invoices are taken into account, a single Time or Expense Entry creates up to 8 Actual records. As PSA creates a Project Approval for every single Time and Expense Entry, a user may easily have 200 entries a month if they submit entries for 10 projects every day, Monday to Friday. Multiply this with the number of users you have and the total Flow runs a month might make you grin. This is why the Flows covered on this blog post are not based on created Actuals but on updated Project Approvals and Invoices.

Image 2: Actuals created in PSA’s end-to-end process.

Transaction Origins and Transaction Connections

Transaction Origins are used to store the very origin of each business transaction in PSA. As we move from Time Entry to Invoice, several transactions are created. This entity will show the origin of all those transactions. The 8 Actual records displayed in image 2 have created a total of 60 Transaction Origin records in PSA, as seen in image 3.

Image 3: Transaction Origins.

A Transaction Connection shows the relation between two similar business transactions. For example when a Time Entry is approved, both Cost and Unbilled Sales Actuals are created. These two Actual records are related business transactions and can be seen on a Transaction Connection record.

Image 4: Transaction Connections.

Flow #1: From Time Entry to Actuals

Flow #1 passes a value entered on a custom field on a Time Entry to another custom field on an Actual. In this example the custom field is a lookup to the Case entity. The goal is to pass a Case throughout PSA’s end-to-end process. When Billed Sales Actuals are created and transferred to an ERP via an integration, a value for Case is passed along.

The Flow fires off when Approved by, msdyn_approvedby changes. Next we want to check that a Case is present on a Time Entry, Entry Type is for Time instead of Expense and Approved By contains data. The Flow can be easily extended to cover Expenses as well.

After a Time Entry is approved, Actuals are created. In my experience this may sometimes take a few seconds so we want to give the plug-ins a few seconds. After the Delay, it’s time to list all Transaction Origins that are related to the initial Time Entry. We can then list all Actuals that are related to these Transaction Origins. We now know which Cost and Unbilled Sales Actuals are based on the initial Time Entry. The final action is to update these Actuals with Case from the initial Time Entry.

At this point we will have Cost and Unbilled Sales Actuals that have the lookup to Case populated based on what was entered on the initial Time Entry record. The next step is to make sure the value for Case is passed to Billed Sales Actuals when an Invoice is confirmed.

Image 5: Flow #1.

Flow #2: Updating Billed Sales and Unbilled Sales Actuals

Flow #2 updates Actuals when an Invoice is confirmed. The initial confirmation of an Invoice creates Billed Sales Actuals. When an Invoice is corrected and the corrected Invoice is then reconfirmed, reversed Billed Sales Actuals and Unbilled Sales Actuals are created.

Using msdyn_projectinvoicestatus as an Attribute Filter Item fires the Flow off when a value in that field changes. I had some issues filtering based on that field and noticed the following behavior, which is still unexplained at the time of writing this blog post:

  • On PSA 3.4, the Flow will fire off when an Invoice is created from an Order and msdyn_projectinvoicestatus is not used as an Attribute Filter Item. This is despite the trigger of the Flow being a When a record is updated CDS trigger. This was reproed in two different tenants.

Both the “true” and “false” sides following the Is Project Invoice Status equal to Confirmed condition contain the same set of Actions. The only difference is that the “true” side updates positive Billed Sales Actuals following an invoice confirmation and the “false” side updates reversed Billed Sales Actuals and Unbilled Sales Actuals following a confirmation of a corrected invoice.

The first action following the initial condition is to give the OOTB plug-ins some time to create the necessary Actuals. After this, all Actuals related to an Order found on the Invoice are listed. Transaction Type is used to narrow down the results of the List records action further.

Next action is to list all Transaction Origins that have an Origin of Time Entry and are related to the Actuals from the previous action. As the relevant Transaction Origin is now listed, the Time Entry related to the Transaction Origin can be retrieved. With the Time Entry at our disposal, the Actual record can be updated with Case from Time Entry.

We now have a value for Case from Time Entry on both a revered Billed Sales Actual and an Unbilled Sales Actual. The Unbilled Sales Actual can be invoiced again. As I mentioned earlier, Invoice Line Details are not taken into account in Flow #2.

Image 6: Flow #2.

Passing values from custom fields throughout PSA’s end-to-end process is something that is a pretty frequent ask in PSA implementations. In this blog post we have passed a value for Case from Time Entry to a corrected Invoice. I hope this post gives you some ideas on how to leverage Flow and Transaction Origins to extend PSA. As always, these Flows can be found from the TDG Power Platform Bank here.

All my blog posts reflect my personal opinions and findings unless otherwise stated.