> For the complete documentation index, see [llms.txt](https://docs.agilecase.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.agilecase.com/developer-documentation/case-scripting/calculated-fields/building-a-multi-part-total.md).

# Building a Multi-Part Total

A calculated field split into helper functions — several inputs, a tier, VAT and fixed charges composed into one total.

Real quotes are made of parts. Some are entered, some are banded, some are per-unit, and only some attract VAT. Written as one expression this becomes unreadable within a month; split into named functions it stays legible, and each part can be checked on its own.

## The scenario

A charity quotes for a fundraising gala. The total is a venue charge banded from the venue's list price, plus the catering package, plus a per-guest fee, plus a service fee and an admin fee, with VAT on everything except the venue and catering.

| Setting          | Value                                                                                                          |
| ---------------- | -------------------------------------------------------------------------------------------------------------- |
| Calculated field | `6101` Event quote total                                                                                       |
| Inputs           | `6102` guest count, `6103` venue list price, `6104` catering package fee, `6105` service fee, `6106` admin fee |
| Per guest        | £7                                                                                                             |
| VAT              | 20%, on the per-guest, service and admin lines                                                                 |

## The script

```javascript
function money(id) {
    var raw = Service.CustomField(id).ValueAsText
        .replace("£", "")
        .replace(/,/g, "");

    var value = parseFloat(raw);

    return isNaN(value) ? 0 : value;
}

function venueBand() {
    var price = money(6103);

    if (price > 5000) { return 550; }
    if (price > 2000) { return 330; }
    if (price > 0)    { return 80; }
    return 0;
}

function calc() {
    var guests = money(6102);
    var catering = money(6104);
    var service = money(6105);
    var admin = money(6106);

    var perGuest = guests * 7;
    var vat = (perGuest + service + admin) * 0.2;

    return String((venueBand() + catering + perGuest + service + admin + vat).toFixed(2));
}
```

## One function for reading money

Every input needs the same treatment: strip the currency symbol, strip the separators, convert, and fall back to zero when the field is empty or unreadable. Doing that five times in `calc()` is five chances to leave one out.

`money(id)` does it once. The `isNaN` fallback matters more than it looks: without it, a single empty field would make `perGuest` `NaN`, and `NaN` spreads through every addition that follows, so the whole quote would come out as `NaN` rather than as a total missing one line.

## One function per part

`venueBand()` is separated for a different reason. It is the part most likely to change — bands are renegotiated, prices move — and having it alone in a named function means that change touches five lines that are obviously about venue pricing, rather than a clause buried in a long expression.

`calc()` then reads as the quote reads: parts, then VAT, then the sum. Anyone can check it against the pricing sheet without unpicking any arithmetic.

Only `calc()` is called by AgileCase. Everything else in the script is yours to organise, and there is no cost to defining as many functions as the calculation needs.

## Which lines carry VAT

The VAT line is the one to get wrong, so it is written to be read:

```javascript
var vat = (perGuest + service + admin) * 0.2;
```

The three names inside the brackets are the VAT-bearing lines, and the two that are absent are the ones that are not. Multiplying a running total by `1.2` somewhere in the middle of the sum would give the same answer today and be impossible to check the day the treatment of one line changes.

{% hint style="warning" %}
`toFixed(2)` rounds only at the end, which is right for a quote. If your figures have to reconcile line by line against another system that rounds each line, round each part as you calculate it instead — the two approaches differ by a penny often enough to be noticed.
{% endhint %}

## Where the total can be used

Because this is a calculated field rather than a label, the total is available as a merge field in the quote document itself, and through the [Case Data API](/developer-documentation/case-data-api.md). It is recalculated every time it is read, so a document produced after the guest count changes carries the new figure without anyone reworking the case.
