# Automatically calculate deal value from products and line items

URL: https://attio.com/help/reference/how-to-guides/calculate-deal-value-from-products-and-line-items
Breadcrumbs: [Help](https://attio.com/help) > [Reference](https://attio.com/help/reference) > [How-to guides](https://attio.com/help/reference/how-to-guides)

Automatically calculate deal value from products and line items.

> Available on pro, enterprise plans.
>
> Admins can create [custom objects](https://attio.com/help/reference/managing-your-data/objects/create-and-manage-custom-objects). Admins and members with full access to an object can create [attributes](https://attio.com/help/reference/managing-your-data/attributes/create-manage-attributes).

Calculating Deal value from the products or services on each deal gives every rep the same structure to work in, and gives your reports and forecasts consistent numbers. This article shows you how to set up two custom objects, three formulas, and three workflows that calculate Deal value for you. When a rep adds line items to a deal, Attio totals them and updates the Deal value. Each product's price is locked in on the line item when it's created, so changing a product's price later never rewrites past deals. Deals without line items keep the value reps type in.

If you haven't created custom objects or workflows before, read [create and manage custom objects](https://attio.com/help/reference/managing-your-data/objects/create-and-manage-custom-objects) and [create a workflow](https://attio.com/help/reference/automations/workflows/create-a-workflow) first. This article focuses on what to build and why.

## Decide whether you need products and line items

This setup is worth it when your team sells more than one product or variable quantities of a product on the same deal. A deal for 40 seats of a license plus an implementation fee is a good example.

If every deal is for one product at one price, you don't need to add complexity through this setup. A typed Deal value or a single formula attribute on Deals is enough.

The tradeoff is setup time, but once it's built, Deal value maintains itself.

## Understand how products, line items, and deals fit together

The setup uses three objects. Deals is a standard object that Attio provides, and Products and Line items are custom objects you create.

- **Products** is your price list, with one record per thing you sell (like a platform license) and its current list price.
- **Line items** track what's sold on a specific deal: which product, how many, and at what discount. Each line item belongs to one deal.
- **Deals** is the standard object for tracking your sales pipeline. One deal can have many line items.

This article follows one example throughout. Lumora is a SaaS analytics company that sells three products:

- **Platform license**: $600 per seat per year
- **Implementation package**: $5,000
- **Premium support**: $2,400 per year

Lumora's deal with its customer Ridgeway is for 40 Platform licenses at 10% off, plus the Implementation package.

Each row is a line item, and the deal's value is the sum of its line items. Here's what that looks like:

```
Platform license          40 seats × $600, 10% off     $21,600
Implementation package    1 × $5,000                    $5,000
                                                      --------
Deal value                                             $26,600
```

## Set up the Products and Line items objects

These two custom objects hold your products and what each deal sells (Line items). [Create a custom object](https://attio.com/help/reference/managing-your-data/objects/create-and-manage-custom-objects) called **Products** with these attributes:

- **Product name**: A text attribute for the product's name.
- **List price**: A currency attribute with the current price.

You can add more attributes if you need them.

Then create a custom object called **Line items** with these attributes:

- **Product**: A record reference to Products that allows only one value. Turn on **Required** so every line item gets a price.
- **Deal**: A relationship to Deals. Set it up so many line items can belong to one deal, and each line item belongs to one deal. This also adds a Line items attribute to Deals.

  ![](https://a.storyblok.com/f/234930/1614x696/e5a7b36d54/image.png)
- **Quantity**: A number attribute. Turn on **Required** so a line item can't be saved without a quantity.
- **Locked price**: A currency attribute. The workflow in [the section on copying the product's price onto each new line item](https://attio.com/help/reference/how-to-guides/calculate-deal-value-from-products-and-line-items#copy-the-products-price-onto-each-new-line-item) fills it in with the product's List price.
- **Discount %**: A number attribute for the rep's discount, entered as a whole number such as 10.

Learn [how to create attributes](https://attio.com/help/reference/managing-your-data/attributes/create-manage-attributes) and [how relationship attributes work](https://attio.com/help/reference/managing-your-data/attributes/relationship-attributes).

Once those attributes exist, [add a formula attribute](https://attio.com/help/reference/managing-your-data/attributes/formula-attributes) called **Name** that labels each line item with its product and quantity, such as "Platform license x 40". Create it with the **AI composer** in the formula editor, using this prompt:

```
Output text. Take the Product name attribute from the linked Product, add the text " x ", then add the Quantity attribute converted to text with text(). Example output: "Platform license x 40".
```

Creating formulas with [the AI composer](https://attio.com/help/reference/managing-your-data/attributes/formula-attributes) in this way doesn't use any credits.

Then set **Name** in the **Record text** dropdown menu for the Line items object. Reps won't need to enter a name, and it updates when the quantity changes. Learn how to [manage record labels](https://attio.com/help/reference/managing-your-data/objects/create-and-manage-custom-objects).

Treat the Locked price attribute as read-only. When a rep negotiates a better price, they should use the Discount % attribute to reflect that. That keeps the original list price on record, so you can see how much discounting is happening.

## Create a product record

Create a product record now so you have something to test with later in this article.

1. In the sidebar, open the **Products** object.
2. If you haven’t [created a view](https://attio.com/help/reference/managing-your-data/views) yet, you’ll be prompted to do so.
3. Click the **New Product** button.
4. Enter the **Product name** and **List price**.
5. Click **Create record**.

Your product appears in the Products object, ready to add to a deal.

## Show line items on the deal record page

Add a Line items tab to deal records so reps can see and edit each deal's line items in one place. Admins and members with full access to the Deals object can [configure record pages](https://attio.com/help/reference/managing-your-data/records/configure-record-pages).

1. Open any deal record.
2. Click the ⋮ icon in the upper-right corner.
3. Select **Configure page**.
4. Click **+ Add tab**.
5. Select **Line items**.
6. Select the attributes to show: **Product**, **Quantity**, **Locked price**, **Discount %**, and **Line total**.
7. Optionally, drag the **Line items** tab to where you want it.
8. Click **Save changes**.

Every deal record now has a **Line items** tab that lists its line items in a table. Reps can edit line items directly in the table, and sort or filter them. You'll use this tab to test the workflows and formulas in the next sections.

## Copy the product's price onto each new line item

This first workflow locks in the product's price on the line item the moment a line item is created, so changing a product's List price later doesn't change the deals it's already on. A **workflow** is an automation that runs a series of steps for you. It starts from a **trigger**, the event that sets it off, followed by **action blocks** that do the work.

> If you sell the same product at different prices by region or tier, create one product per price point. Each product then has a single price that doesn't need to change.

- Create a workflow with the **Attribute value changed** trigger on Line items, watching the **Product** attribute.
- Add an **Update record** block that updates the triggering line item.
- Set **Locked price** to the **List price** of the line item's product.

You can also [use Ask Attio to build this workflow](https://attio.com/help/reference/automations/workflows/create-a-workflow) for you by pasting in the prompt below (make any edits to attribute names if needed). Building it this way uses [seat credits](https://attio.com/help/reference/workspace-settings-billing/manage-workspace-and-seat-credits).

```
Build a new workflow called "Set locked price when product changes".

Trigger: "Attribute value changed" on Line items, watching the Product attribute.

Step: an "Update record" block that updates the triggering Line item, setting "Locked price" to the List price of the Product linked to that Line item.
```

The trigger fires when a value is set or changed for the Product attribute on a line item record. So if a rep picks the wrong product and fixes it, the line item picks up the correct product's price. Changing the value of a List price attribute on a product doesn't trigger this workflow, which is what keeps existing line items locked. See the [workflows block library](https://attio.com/help/reference/automations/workflows/workflows-block-library) for how each block works.

To test the workflow, open a test deal, click **New Line item** on its **Line items** tab, and select a product. Locked price should fill in with that product's List price. For Lumora, a Platform license line shows $600.

## Calculate line totals and the deal total

The Line total and Line items total formulas handle the math. Because formulas recalculate when any value they reference changes, editing a line item's quantity or discount updates its Line total and the deal's Line items total automatically, without extra workflows or credits.

[Create both formulas](https://attio.com/help/reference/managing-your-data/attributes/formula-attributes) with the **AI composer**, as you did for Name.

On the Line items object, create a formula attribute called **Line total** and use this prompt:

```
Multiply the Quantity attribute by the Locked price attribute, then reduce the result by the Discount % attribute as a percentage (10 means 10% off). If Discount % is empty, treat it as 0. Use each attribute's current value, not a historical value.
```

The result should look like this:

```
{Quantity} * {Locked price} * (1 - ifNull({Discount %}, 0) / 100)
```

Formulas return nothing if any input is empty, so `ifNull` stops a line item with no discount from dropping out of the deal's sum.

On the Deals object, create a formula attribute called **Line items total**, with **Currency** output, and use this prompt:

```
Add up the Line total attribute across all of this deal's Line items. If the deal has no line items, return 0.
```

The result should look like this:

```
if(count({Line items › Line total}) == 0, currency(0), sum({Line items › Line total}))
```

The `if` and `count` part returns $0 instead of a calculation error for deals with no line items. For formula syntax, see [formula attributes](https://attio.com/help/reference/managing-your-data/attributes/formula-attributes).

To test the formulas, add a second line item to your test deal and leave its discount empty. Each line should show a Line total, and Line items total should equal their sum. For Lumora's Ridgeway deal, that's $21,600 + $5,000 = $26,600.

![](https://a.storyblok.com/f/234930/3614x888/98af8b0c38/cleanshot_2026-10-21_at_16-24-452x.png)

## Keep Deal value in sync with the line items

Deal value feeds your reports and forecasts, so it needs to stay in sync with line items.

Once a deal has line items, the line items decide its Deal value. Deals without line items keep whatever value reps type in.

Create the second workflow:

- Use the **Attribute value changed** trigger on Deals, watching **Line items total**.
- Add a **Filter** block that only continues when the deal's **Deal stage** isn't a won or lost stage.
- Add a second **Filter** block that continues when the deal's **Line items** attribute isn't empty, or when the trigger's **Previous value** is greater than 0.
- Add an **Update record** block that sets **Deal value** to **Line items total**.

You can also [use Ask Attio to build this workflow](https://attio.com/help/reference/automations/workflows/create-a-workflow) for you by pasting in the prompt below (make any edits to attribute names if needed). Building it this way uses [seat credits](https://attio.com/help/reference/workspace-settings-billing/manage-workspace-and-seat-credits).

```
Build a new workflow that updates a Deal's value whenever its line items total changes, but only while the deal is still open.

Trigger:
- Use the "Attribute value changed" trigger on the Deals object, watching the "Line items total" attribute.

Steps, in order:
1. Filter: only continue if the triggering Deal's "Deal stage" is not "Closed Won" and not "Closed Lost".
2. Filter: only continue if the triggering Deal's "Line items" attribute is not empty, OR the trigger's previous value of "Line items total" is greater than 0.
3. Update record: on the triggering Deal, set "Deal value" to its current "Line items total".

Connect the blocks in a single line: trigger -> filter 1 -> filter 2 -> update record.

If you can't find any of these attributes or the "Closed Won" / "Closed Lost" stages, ask me which ones to use instead of guessing.
```

The second filter stops a new deal's $0 Line items total from overwriting a typed Deal value. It only continues when the deal has line items or has just lost its last one. The stage filter keeps closed deals at the value they closed at.

The trigger watches Line items total, not the Line items attribute, because a trigger on Line items only fires when line items are added or removed, not when a rep edits a line.

Don't use Deal value in the Line total or Line items total formulas. Otherwise, this workflow's update to Deal value can trigger it again in a loop that uses workspace credits.

Your test deal's Deal value should now match its Line items total. For Lumora, Ridgeway shows $26,600. If you remove all of a deal's line items, its Deal value goes to $0.

## Stop reps from typing over Deal value

You can't stop the Deal value from being edited, so a third workflow sets it back to Line items total when a rep edits it. Without it, a typed value can become a closed deal's final value.

Create the third workflow:

1. Use the **Attribute value changed** trigger on Deals, watching **Deal value**.
2. Add a **Filter** block that only continues when the deal's **Deal stage** isn't a won or lost stage.
3. Add a second **Filter** block that only continues when the deal's **Line items** attribute isn't empty.
4. Add a third **Filter** block that only continues when **Deal value** doesn't equal **Line items total**.
5. Add an **Update record** block that sets **Deal value** to **Line items total**.

You can also [use Ask Attio to build this workflow](https://attio.com/help/reference/automations/workflows/create-a-workflow) for you by pasting in the prompt below (make any edits to attribute names if needed). Building it this way uses [seat credits](https://attio.com/help/reference/workspace-settings-billing/manage-workspace-and-seat-credits).

```
Build a workflow called "Reset Deal value to line items total".

Trigger: "Attribute value changed" on the Deals object, watching "Deal value".

Blocks, connected in a single line (trigger -> 1 -> 2 -> 3 -> 4):
1. Filter: "Deal stage" is not "Closed Won" AND not "Closed Lost", in one Filter block.
2. Filter: "Line items" is not empty.
3. Filter: "Deal value" does not equal "Line items total".
4. Update record: on the triggering Deal, set "Deal value" to "Line items total".

Notes:
- Read every Deal attribute from the trigger's record, not from a lookup step.
- "Line items total" is a read-only currency attribute, so type the value in the Update record block as number-or-currency.
- If any attribute or the Closed Won / Closed Lost stages are missing, ask me which to use instead of guessing.
```

The third filter stops the workflow from triggering itself. Its own update to Deal value fires the trigger again, but the values now match, so the run stops there. The first two filters leave closed deals and deals without line items alone. To change the value of a deal that has line items, edit its line items instead, and use Discount % for discounts.

## Add line items to a deal

Reps create one line item per product or service that they're selling in that deal. A deal for licenses and an implementation package has two line items. Create line items from the deal's **Line items** tab, so each one is linked to the deal automatically.

- Open the deal and select the **Line items** tab.
- Click **New Line item**. If the deal already has line items, click **Add line item**.
- Select a **Product**, enter a **Quantity**, and optionally enter a **Discount %**.

Repeat these steps for each product on the deal. Name and Deal fill in automatically. Leave Locked price empty because the workflow fills it in with the product's List price after you select a product. To offer a lower price, enter a Discount % instead. Line total and Deal value then update automatically.

## Check that prices stay locked and Deal value syncs

Run three quick checks on your test deal:

- Change List price on a test product. Line items that already use it keep their Locked price, and Deal value doesn't change. If Lumora raised Platform license to $700, Ridgeway's line would keep $600.
- Move a deal to a won or lost stage, then edit one of its line items. Line items total should update, but Deal value shouldn’t.
- Type a different value into Deal value on an open deal with line items. It should change back to Line items total.

## Use Deal value in reports and forecasts

With Deal value calculated from line items, every report, view, and forecast that uses it is built on consistent numbers. The natural next step is to weight Deal value by stage probability. Learn how in [setting up a weighted pipeline](https://attio.com/help/reference/how-to-guides/setting-up-a-weighted-pipeline).

## FAQ

### Why is Locked price empty on some line items?

Line items created before the first workflow existed won't have a Locked price. To fill it in, clear the line item's **Product**, then select the product again. This triggers the workflow, which copies the product's current List price. If the product's price has changed since the deal was made, check that Locked price matches what was sold.

### Can I edit line items on a closed deal?

Yes, and Line items total updates, but Deal value doesn't. That keeps closed deals at the value they closed at. If the change should count, update Deal value by hand.

### Can I stop reps from changing line items or products on a deal?

No, anyone with access to edit line items can change them. If a rep types over Deal value on an open deal with line items, the third workflow changes it back. See the section on stopping reps from typing over Deal value.

### Does this work with more than one currency?

Each currency attribute uses one currency, set in its attribute settings, so every line item and deal in this setup shares the same currency. Formulas don't convert between currencies, so set List price, Locked price, Line items total, and Deal value to the same one. Otherwise, the number carries over unchanged. For example, a €5,000 Locked price becomes $5,000 in a Line items total set to US dollars.

### Why do my existing Deal value automations run more often after this setup?

Deal value updates every time a line item changes. Workflows or alerts that trigger on Deal value changes run each time, and they can run on a value partway through a rep's edits. Consider triggering them on a stage change instead, or adding a condition such as a minimum value.
