---
title: "The parts filter that read correctly and would have billed nothing"
description: "A billing bridge filtered parts on IsConsumed = true, which reads like parts that were used. It means parts that came out of inventory. For a company with no warehouse it is false forever, and every spring would have fallen off every invoice without a single error."
source: "https://noconaconsulting.com/blog/product-consumed-isconsumed-billing-filter/"
---

# The parts filter that read correctly and would have billed nothing

_Build log · Doorvana · Garage door manufacturing & service_

A billing bridge filtered parts on IsConsumed = true, which reads like parts that were used. It means parts that came out of inventory. For a company with no warehouse it is false forever, and every spring would have fallen off every invoice without a single error.

Nocona Consulting · September 28, 2026 · 7 min read

A technician replaces a broken spring and logs the part on the job. The invoice goes out with the labor and the service fee on it — and no spring. Not on that job. On every job.

No error. No warning. The Work Order looks complete, the Order exists, the customer pays, and the money for the part is just missing. This was five characters of a `WHERE` clause and it passed a human review, because the clause reads like plain English and means something else.

## What the bridge does

At [Doorvana](https://noconaconsulting.com/work/) a completed `WorkOrder` becomes a Draft `Order` on the single revenue ledger that the accounting integration invoices from. One `OrderItem` per priced `WorkOrderLineItem`, one `OrderItem` per part logged as `ProductConsumed`, and every line stamped back with the standard `WorkOrderLineItem.OrderId` so nothing can be billed twice.

_Labor lines and parts arrive on the Order by two different paths. WorkOrderLineItem.OrderId is the stamp that makes the bridge idempotent — a line that already carries an OrderId is never billed again._

## The filter that looked obviously right

The first draft of the parts query filtered on `IsConsumed`:

```sql
FROM ProductConsumed
WHERE WorkOrderId IN :workOrderIds
  AND IsConsumed = true
```

Read that out loud. _Parts that were consumed._ Parts that were used on the job. That is what you want to bill for, and the field name is the sentence.

Twelve of thirteen tests passed. The one that failed was the parts test, and it failed on a count: it expected two Order Products on the Order and got one. The labor line was there. The spring was not.

The assertion is the only reason this was caught

The test asserted the exact number of `OrderItem` records, not merely that an `Order` had been created. An assertion on existence would have passed — there _was_ an Order, with a perfectly good labor line on it. Half an invoice looks exactly like an invoice until somebody counts.

## What `IsConsumed` actually tracks

A rolled-back anonymous Apex probe settled it. Create a `ProductConsumed` against a `PricebookEntry` that has no backing inventory `ProductItem`, read the field back, roll the whole thing away:

anonymous Apex, rolled back

```apex
Savepoint sp = Database.setSavepoint();
ProductConsumed part = new ProductConsumed(
    WorkOrderId       = workOrderId,
    PricebookEntryId  = springEntryId,
    QuantityConsumed  = 2
);
insert part;
System.debug([SELECT Id, IsConsumed FROM ProductConsumed WHERE Id = :part.Id][0].IsConsumed);
Database.rollback(sp);
// false
```

`IsConsumed` does not mean “was this part used”. It means **“did this come out of inventory”** — whether the consumption drew down a `ProductItem`, a stocked quantity at a Location or on a van. It is Field Service’s inventory flag, and it is doing exactly what it was designed to do.

Doorvana holds no inventory. Technicians collect product from vendor locations on the way to a job, which means there are no `ProductItem` records, which means every part the company will ever log has `IsConsumed = false`. Forever. The filter was not going to return fewer parts than expected. It was going to return none, on every job, for the life of the org.

The filter came out, and the query now says why it is missing:

force-app/main/default/classes/WorkOrderBillingSelector.cls

```apex
/**
 * Deliberately no IsConsumed filter. IsConsumed tracks inventory depletion and is false for a
 * part logged against a price book entry with no ProductItem, which is every part Doorvana
 * logs: it holds no inventory. Filtering on it would silently bill no parts at all.
 */
public static List<ProductConsumed> selectBillableParts(Set<Id> workOrderIds) {
    return [
        SELECT Id, WorkOrderId, WorkOrderLineItemId, PricebookEntryId,
               QuantityConsumed, UnitPrice, PricebookEntry.UnitPrice,
               PricebookEntry.Product2.ProductCode
        FROM ProductConsumed
        WHERE WorkOrderId IN :workOrderIds
            AND PricebookEntryId != null
        WITH SYSTEM_MODE
        ORDER BY ProductConsumedNumber
    ];
}
```

`PricebookEntryId != null` is the filter that actually expresses the intent: bill the parts that have a price. Whether a part came out of a warehouse is a different question that this org will never need to ask.

Rule of thumb

A boolean field named after a verb tells you what the platform recorded, not what you meant. Before filtering on one, create a record the way your org will actually create it, read the field back, and roll it away. Two minutes of anonymous Apex against a name you inferred is cheaper than a filter that is correct in the documentation’s org and empty in yours.

## The second thing the tests found: user mode is the default now

The same build produced a failure that had nothing to do with billing logic:

```plaintext
Operation failed due to fields being inaccessible on Sobject WorkOrderLineItem
```

It came from the administrator’s own test setup, writing `OrderId` onto a `WorkOrderLineItem`. An administrator. On a standard field.

From **API version 67.0, Apex runs in user mode by default**, test classes included. Queries and DML are evaluated against the running user’s field-level security rather than with full system access, and a field the running user cannot see is a field the code cannot write.

That matters far more here than it does in a test. The bridge is triggered by the `WorkOrder` moving into the `Completed` status category, so it runs as **whoever completed the job** — a technician, who has no access to `Order`, `OrderItem` or price book records and no reason to. Left in user mode, the automation would have failed for exactly the population that sets it off, and passed every time an administrator ran it by hand.

So every query in the selector carries `WITH SYSTEM_MODE`, the DML uses `AccessLevel.SYSTEM_MODE`, and the class header says why in prose rather than leaving the next person to infer it.

An inaccessible field and a nonexistent field produce the same error

Under user mode, `No such column 'BillToContactId' on entity 'Order'` does not mean the field is absent. It can equally mean the running user has no field-level security on it — and `sf sobject describe` hides both cases identically. That one is worth its own post; it was first written up here as a missing field and it is not.

## Verified, then believed

The bridge was checked end to end in the sandbox UI rather than only in Apex: one completed test Work Order produced a Draft Order carrying the labor line, the service fee, the spring as its own Order Product, and a negative service fee credit where the fee applies toward the repair. That last step is what turns thirteen passing tests into a thing you are willing to say works.

## Practical summary

-   `ProductConsumed.IsConsumed` is an inventory flag. It is `false` for every part logged against a `PricebookEntry` with no `ProductItem` behind it, however physically consumed that part was.
-   For billing, filter on `PricebookEntryId != null`. That is the question you are actually asking.
-   Assert on counts in tests. A silent filter produces a valid-looking record with fewer children than it should have, and existence assertions cannot see the difference.
-   From API 67.0, Apex defaults to user mode everywhere, including tests. Automation triggered by low-privilege users needs `WITH SYSTEM_MODE` and `AccessLevel.SYSTEM_MODE` declared deliberately, not discovered.
-   A rolled-back anonymous Apex probe is the cheapest way to learn what a standard field actually stores in your org’s configuration.

The most expensive bugs on this project so far have all had the same shape: something read correctly, reviewed clean, and meant something other than what it said.

-   Field Service
-   Apex
-   Billing
-   ProductConsumed
-   Order Products
-   Testing

Disclosure: Doorvana's owner is also a co-owner of Nocona Consulting. This is a real engagement between two separate companies, but not an arm's-length one — and not an independent reference. [More on the work page](https://noconaconsulting.com/work/).

## FAQ

### What does IsConsumed mean on the Salesforce ProductConsumed object?

IsConsumed records whether the part was depleted from inventory, not whether it was used on the job. It is set when the consumption draws down a ProductItem — a stocked quantity at a Location or on a van. A ProductConsumed created against a PricebookEntry with no backing ProductItem stores IsConsumed = false even though the part was physically installed. Any logic that reads IsConsumed as was this part used will be wrong in every org that does not carry inventory in Salesforce.

### Should a billing process filter ProductConsumed on IsConsumed?

Only if the org actually tracks inventory in Salesforce and you specifically want depleted stock. For billing, filter on whether the part carries a price instead — PricebookEntryId != null — because that is what determines whether there is anything to charge for. Filtering on IsConsumed in an org with no ProductItem records silently returns an empty list, which produces invoices that are missing every part and raises no error anywhere.

### Why did Apex start failing with fields being inaccessible after API version 67.0?

From API version 67.0 Apex runs in user mode by default, including in test classes. Queries and DML are evaluated against the running user's field-level security rather than with full system access. Code that worked under an older API version fails with messages such as Operation failed due to fields being inaccessible on Sobject WorkOrderLineItem when the running user cannot see a field the code writes. The fix is explicit: WITH SYSTEM\_MODE on SOQL and AccessLevel.SYSTEM\_MODE on Database DML, in the places where system behaviour is genuinely intended.

### Should a Field Service billing automation run in system mode?

Usually yes, and the reason is who triggers it. Billing is started by whoever completes the Work Order, which is typically a technician with no access to Order, Order Product or price book records. If the automation inherits that user's access it fails for precisely the population that sets it off, while passing for an administrator running it by hand. Declaring system mode explicitly and restricting the class's callers is more honest than discovering the asymmetry in production.

### How do you catch a filter that silently returns nothing in Salesforce?

Assert on counts, not only on success. A test that checks an Order was created passes happily when the Order has half the lines it should. Asserting the exact number of Order Products against the number of billable inputs is what turns a silent omission into a failing test. Where a filter's meaning is inferred from its name, a rolled-back anonymous Apex probe that creates a record and reads the field back settles what the platform actually stores.
