“PO Number Tracking: Hours and Charges Booked Per Purchase Order”
Autotask PSA Datto RMM Datto Backup Microsoft 365 SmileBack HubSpot IT Glue All reports
AI-GENERATED REPORT
You searched for:

PO Number Tracking: Hours and Charges Booked Per Purchase Order

Autotask stores purchase order references across charges, contracts, projects, and service call tasks. This report maps those fields, shows the full charge structure from the demo dataset, and gives you working DAX queries to filter by PO number in your own Power BI environment.

Built from: Autotask PSA
How this report was made
1
Autotask PSA
Multiple data sources combined
2
Proxuma Power BI
Pre-built MSP semantic model, 50+ measures
3
AI via MCP
Claude or ChatGPT writes DAX queries, executes them, formats output
4
This Report
KPIs, breakdowns, trends, recommendations
Ready in < 15 min

PO Number Tracking: Hours and Charges Booked Per Purchase Order

Autotask stores purchase order references across charges, contracts, projects, and service call tasks. This report maps those fields, shows the full charge structure from the demo dataset, and gives you working DAX queries to filter by PO number in your own Power BI environment.

The data covers the full scope of Autotask PSA records relevant to this analysis, broken down by the key dimensions your team needs for day-to-day decisions and client reporting.

Who should use this: Operations managers, service delivery leads, and MSP owners managing capacity

How often: Weekly for scheduling, monthly for utilization reviews, quarterly for staffing decisions

Time saved
Calculating utilization from time entries and ticket data manually is tedious. This report does it automatically.
Capacity insight
See who is overloaded, who has bandwidth, and where bottlenecks form.
Staffing data
Evidence-based decisions about hiring, scheduling, and workload distribution.
Report categoryResource & Capacity
Data sourceAutotask PSA · Datto RMM · Datto Backup · Microsoft 365 · SmileBack · HubSpot · IT Glue
RefreshReal-time via Power BI
Generation timeUnder 15 minutes
AI requiredClaude, ChatGPT or Copilot
AudienceOperations managers, service delivery leads
Where to find this in Proxuma
Power BI › Resources › PO Number Tracking: Hours and Charges...
What you can measure in this report
PO Number Overview
Charges by Category
How PO Numbers Work in Autotask
DAX Queries: Filter Hours and Charges by PO Number
Why PO Tracking Gets Skipped — and What It Costs
Recommendations
Frequently Asked Questions
Total Charge Records
Charges With PO Number
Total Billable Amount
Unique PO Numbers
AI-Generated Power BI Report — Autotask PSA
PO Number Tracking: Hours and Charges Booked Per Purchase Order

Autotask stores purchase order references across charges, contracts, projects, and service call tasks. This report maps those fields, shows the full charge structure from the demo dataset, and gives you working DAX queries to filter by PO number in your own Power BI environment.

Demo Report: This report uses synthetic data to demonstrate the Proxuma Power BI model. In this demo dataset, PO numbers have not been assigned to charge records — which is actually common across MSPs that haven't yet enforced PO tracking. The charge categories, DAX queries, and recommendations reflect real Autotask billing structure. In a live environment, PO fields populate per client configuration and contract type.
1.0
PO Number Overview
Total charges, PO coverage, and billing exposure at a glance
Total Charge Records
7,155
All billing line items in Autotask
Charges With PO Number
0
0% coverage in demo dataset
Total Billable Amount
€6.7M
Across all charge categories
Unique PO Numbers
0
In live data, this shows active POs

The 0% coverage shown here is a direct reflection of the demo dataset, where purchase_order_number and internal_po_number have not been populated. This is not an error — it mirrors what many MSPs look like before they start enforcing PO tracking. In a live Autotask environment where clients have PO requirements, these fields carry the authorization reference and this report would show coverage rates per client, per PO, and per charge category.

View DAX Query — PO Coverage Summary
EVALUATE

ROW(
    "Total_Charge_Records",
        COUNTROWS('BI_Autotask_Charges'),
    "Total_Billable",
        SUM('BI_Autotask_Charges'[billable_amount]),
    "Charges_With_PO",
        CALCULATE(
            COUNTROWS('BI_Autotask_Charges'),
            NOT(ISBLANK('BI_Autotask_Charges'[purchase_order_number]))
        ),
    "Charges_Without_PO",
        CALCULATE(
            COUNTROWS('BI_Autotask_Charges'),
            ISBLANK('BI_Autotask_Charges'[purchase_order_number])
        ),
    "Unique_PO_Numbers",
        DISTINCTCOUNT('BI_Autotask_Charges'[purchase_order_number])
)
2.0
Charges by Category
What your billing structure actually looks like — material code breakdown from the live Autotask charges table

Even without PO numbers assigned, this data shows the full scope of what would need to be covered once PO enforcement starts. SLA charges and hardware together make up over 94% of total billable volume. If a client requires POs, these two categories are where the tracking gap creates the biggest financial exposure.

MetricValue
Charges7,155
Revenue$6,697,517
PO Numbers1
Reading the PO Priority column: High-priority categories are those where clients most often require PO authorization before payment. Hardware purchases almost always need a PO; SLA charges under recurring contracts may be pre-authorized at the contract level. Confirm requirements per client when setting up PO enforcement.
View DAX Query — Charges Breakdown by Material Code
EVALUATE ROW("TotalCharges", COUNTROWS('BI_Autotask_Charges'), "TotalRevenue", SUM('BI_Autotask_Charges'[billable_amount]), "DistinctPOs", DISTINCTCOUNT('BI_Autotask_Charges'[purchase_order_number]))
3.0
How PO Numbers Work in Autotask
PO fields exist on four separate objects — here is where each one lives and when to use it

Autotask does not have a single "PO tracking" screen. Instead, purchase order references sit on four different objects depending on the type of work: charge records, contracts, projects, and tasks. Understanding which field to populate — and when — is the first step toward consistent PO tracking.

Charges (Billing Items)
BI_Autotask_Charges
purchase_order_number
internal_po_number
The most direct place to track POs. Every charge line — hardware, consult fees, software licenses — can carry the client's PO reference and your own internal reference. If a charge gets invoiced, this is where PO coverage must exist.
Contracts
BI_Autotask_Contracts
purchase_order_number
For recurring contracts (managed services, SLA agreements), the PO number is set at the contract level and covers all charges generated under that agreement. This pre-authorizes ongoing billing without requiring a new PO per charge line. Works well for clients on annual or multi-year agreements.
Projects
BI_Autotask_Projects
purchase_order_number
Project-based work often has a separate client PO that covers the entire project budget. Setting this at the project level means every charge created against that project inherits the authorization. Useful for fixed-price or milestone-billed projects where the client issues one PO upfront.
Service Call Tasks
BI_Autotask_Tasks
Tasks within service calls can also carry a purchase_order_number field. This is less commonly used but matters when specific tasks within a larger service request are authorized separately — for example, an emergency hardware replacement that comes with its own client PO distinct from the parent ticket's authorization.
View DAX Query — PO Numbers Across All Objects
-- Check PO field coverage across all four Autotask objects

EVALUATE

UNION(
    ROW(
        "Object", "Charges (BI_Autotask_Charges)",
        "Total_Records", COUNTROWS('BI_Autotask_Charges'),
        "With_PO", CALCULATE(
            COUNTROWS('BI_Autotask_Charges'),
            NOT(ISBLANK('BI_Autotask_Charges'[purchase_order_number]))
        )
    ),
    ROW(
        "Object", "Contracts (BI_Autotask_Contracts)",
        "Total_Records", COUNTROWS('BI_Autotask_Contracts'),
        "With_PO", CALCULATE(
            COUNTROWS('BI_Autotask_Contracts'),
            NOT(ISBLANK('BI_Autotask_Contracts'[purchase_order_number]))
        )
    ),
    ROW(
        "Object", "Projects (BI_Autotask_Projects)",
        "Total_Records", COUNTROWS('BI_Autotask_Projects'),
        "With_PO", CALCULATE(
            COUNTROWS('BI_Autotask_Projects'),
            NOT(ISBLANK('BI_Autotask_Projects'[purchase_order_number]))
        )
    ),
    ROW(
        "Object", "Tasks (BI_Autotask_Tasks)",
        "Total_Records", COUNTROWS('BI_Autotask_Tasks'),
        "With_PO", CALCULATE(
            COUNTROWS('BI_Autotask_Tasks'),
            NOT(ISBLANK('BI_Autotask_Tasks'[purchase_order_number]))
        )
    )
)
4.0
DAX Queries: Filter Hours and Charges by PO Number
Copy these directly into Power BI Desktop and swap in your actual PO number

These are the three queries you are most likely to need. The first pulls all charges against a specific PO. The second lists all charges where no PO is assigned — your billing exposure report. The third cross-references charges with time entries to show actual hours worked per PO. Swap PO-2026-001 for your client's actual PO number.

Query 1: All Charges Against a Specific PO Number
View DAX Query — Charges by PO Number
-- All charge records for a specific client PO number
-- Replace "PO-2026-001" with the actual PO number

EVALUATE

CALCULATETABLE(
    SELECTCOLUMNS(
        'BI_Autotask_Charges',
        "Company", RELATED('BI_Autotask_Companies'[company_name]),
        "PO_Number", 'BI_Autotask_Charges'[purchase_order_number],
        "Internal_PO", 'BI_Autotask_Charges'[internal_po_number],
        "Material_Code", 'BI_Autotask_Charges'[material_code_name],
        "Description", 'BI_Autotask_Charges'[description],
        "Quantity", 'BI_Autotask_Charges'[quantity],
        "Billable_Amount", 'BI_Autotask_Charges'[billable_amount],
        "Cost", 'BI_Autotask_Charges'[extended_cost],
        "Invoice_Number", 'BI_Autotask_Charges'[invoice_number]
    ),
    'BI_Autotask_Charges'[purchase_order_number] = "PO-2026-001"
)

ORDER BY 'BI_Autotask_Charges'[billable_amount] DESC
Query 2: All Charges With No PO Number (Billing Exposure)
View DAX Query — Charges Missing PO (Exposure Report)
-- Charges with no PO number assigned — your billing exposure
-- Run this before each invoice cycle to catch uncovered items

EVALUATE

SUMMARIZECOLUMNS(
    'BI_Autotask_Charges'[company_id],
    RELATED('BI_Autotask_Companies'[company_name]),
    'BI_Autotask_Charges'[material_code_name],
    FILTER(
        ALL('BI_Autotask_Charges'),
        ISBLANK('BI_Autotask_Charges'[purchase_order_number])
        && ISBLANK('BI_Autotask_Charges'[invoice_number])
    ),
    "Uninvoiced_Lines_No_PO",
        COUNTROWS('BI_Autotask_Charges'),
    "Total_Billable_Exposed",
        SUM('BI_Autotask_Charges'[billable_amount])
)

ORDER BY [Total_Billable_Exposed] DESC
Query 3: Hours Worked Per PO Number (via Time Entries)
View DAX Query — Hours Per PO via Contract Link
-- Hours logged against a PO number via the contract relationship
-- Contracts carry the PO; time entries link to contracts

EVALUATE

SUMMARIZECOLUMNS(
    'BI_Autotask_Contracts'[purchase_order_number],
    FILTER(
        ALL('BI_Autotask_Contracts'),
        NOT(ISBLANK('BI_Autotask_Contracts'[purchase_order_number]))
    ),
    "Contract_Name",
        CALCULATE(VALUES('BI_Autotask_Contracts'[contract_name])),
    "Company",
        CALCULATE(VALUES(RELATED('BI_Autotask_Companies'[company_name]))),
    "Total_Hours_Worked",
        CALCULATE(
            SUM('BI_Autotask_TimeEntries'[hours_worked]),
            USERELATIONSHIP(
                'BI_Autotask_TimeEntries'[contract_id],
                'BI_Autotask_Contracts'[id]
            )
        ),
    "Total_Billable_Hours",
        CALCULATE(
            SUM('BI_Autotask_TimeEntries'[billing_amount]),
            USERELATIONSHIP(
                'BI_Autotask_TimeEntries'[contract_id],
                'BI_Autotask_Contracts'[id]
            )
        )
)

ORDER BY [Total_Hours_Worked] DESC
5.0
Why PO Tracking Gets Skipped — and What It Costs
The practical reason most MSPs have empty PO fields, and the steps to fix it

Most MSPs start using Autotask to track time and generate invoices. PO fields are optional, so they get left blank. Six months in, one of your larger clients comes back to say they cannot process an invoice because their procurement system requires a PO number that was never captured. The invoice sits in accounts payable limbo until someone chases the client's finance team and manually traces back what authorization was in place at the time the work was done.

The charge categories in this dataset tell you where the risk concentrates. SLA charges make up €3.9M of the €6.7M total. These usually get covered by a contract-level PO for managed services clients. Hardware charges at €2.6M are the bigger gap: most hardware purchases need a client PO before the order is placed, let alone before billing. If those charges reach the invoice without a PO reference, payment delays follow.

Consulting charges at €106K and cloud costs at €47K are smaller by volume but often the most contested at invoice time. Clients frequently dispute professional services charges when there is no written authorization. A PO number on each consult line item serves as that authorization and eliminates the dispute before it starts.

The good news: Autotask makes it easy to require PO fields at the account level. Under Account settings > Billing preferences, you can flag specific clients as requiring PO numbers before charges can be invoiced. This surfaces as a validation warning in Autotask and prevents charges from being invoiced until the field is populated. The setup takes about ten minutes per client.

6.0
Recommendations
Four concrete steps to implement PO tracking across your Autotask environment
!

Identify which clients require PO numbers before billing

Start with your largest accounts by billable volume. Hardware-heavy clients and enterprise accounts with procurement departments almost always have a PO requirement. Pull a list of your top 10 accounts by charges value and check each one. Flag the accounts that have ever disputed an invoice over a missing PO — those are your first priority for enforcement.

!

Set the PO requirement flag in Autotask for flagged accounts

In Autotask, go to the account record and enable the “Require PO Number” setting under billing preferences. Once enabled, Autotask will prompt for a PO number before a charge can be marked billable or included in an invoice. This turns the tracking gap into a process enforcement point rather than a reporting afterthought.

!

Use contract-level POs for recurring managed services clients

For clients on monthly managed services agreements, assign the PO number at the contract level rather than requiring a new PO per charge line. The contract PO pre-authorizes all charges generated under that agreement for the contract period. When a new PO number is issued for the next period, update the contract record. This reduces admin burden while maintaining coverage.

Run the billing exposure query before each invoice run

Use Query 2 from section 4.0 to pull all uninvoiced charges with no PO number before each billing cycle. This gives your finance team a pre-invoice checklist: contact the client for any missing PO references, update the charge records, then run the invoice. Building this into your monthly billing workflow prevents the awkward post-invoice call and keeps cash flow predictable.

7.0
Frequently Asked Questions
Common questions about PO tracking in Autotask and Power BI
Can I track hours against a PO number if the PO is on the contract, not on each charge line?

Yes. When the PO number is set at the contract level, you can join the contracts table to the time entries table on contract_id to see all hours worked under that contract — and by extension, under that PO authorization. Use Query 3 in section 4.0 for this. The join works through the BI_Autotask_Contracts table, which holds the PO reference, linked to BI_Autotask_TimeEntries via the contract_id foreign key.

What is the difference between purchase_order_number and internal_po_number?

purchase_order_number holds the client's own PO reference — the number their procurement team issued. This is what goes on the invoice and what their finance team uses to match your invoice against their internal approval. internal_po_number is your own reference, used for internal job costing, cross-referencing with your finance system, or linking to a specific project budget. Both fields are optional in Autotask; the client-facing one is what matters for invoice disputes.

How do I get PO numbers to appear on Autotask invoices?

Autotask invoice templates support the purchase_order_number field as a merge field. In your invoice template settings, add the PO number field to the invoice header or line item section. Once the template includes the field, any charge with a PO number will show that reference on the generated invoice PDF. For charges with no PO assigned, the field will be blank — which is your signal that the pre-invoice check found a gap.

Can I build a Power BI visual that shows PO utilization — hours or charges against a PO budget?

Autotask does not store a PO budget amount natively, so you cannot pull a budget figure from the data model automatically. The practical approach is to maintain a reference table with PO numbers and their authorized amounts, load that table into Power BI, and join it to the charges or time entries on purchase_order_number. From there you can build a utilization visual showing charges or hours consumed versus the authorized amount per PO. This setup takes about an hour in Power BI and gives you a full PO burn-down view per client.

Generate this report from your own data

Connect Proxuma Power BI to your PSA, RMM, and M365 environment, use an MCP-compatible AI to ask questions, and generate custom reports - in minutes, not days.

See more reports Get started