Analyse spend by project or region

Breaks spend down along one custom analytical field (project, region…), month by month, without mixing fields together.

Finance Analyst📆 MonthlyIntermediateRead-only

Ask it like this

What is the spend by region over the last 12 months, month by month?

When to use it

When you want spend by project, region or any other analytical axis specific to your company.

What it produces

Company total, allocated and unallocated share on the field, then a table per value with amount, share, outstanding and highest month.

How it works

  1. 1Lists your analytical axes and lets you choose
  2. 2Gets the values of the chosen axis
  3. 3Breaks spend down by value, month by month
  4. 4Sets aside values from other axes so nothing gets mixed
  5. 5Works out the share of spend not allocated to this axis

What protects you

  • This skill only reads: it changes nothing in Spendesk
  • It acts with your permissions and your role, never beyond
  • The assistant cannot approve or pay
▸Technical detail85/100 · 3 tools
Spend analysisReportsget_analytical_fieldsget_analytical_field_valuesspendesk_analyze_spend

# Spend analysis by analytical field

## The central trap: `analyticalCode` mixes every field

`spendesk_analyze_spend` with `groupBy: ["analyticalCode"]` returns **the values of every analytical field in one list** — values of your custom fields, and expense categories too. A row does not say which field its value belongs to.

Verified live: over 12 months, the list mixed "France" (Region field), "IT & Technical fees" (an expense category) and "GM Budget" (Supplier Budget field). The rows added up to far more than the real total (EUR 113,720.26), because one payable carries one value per field and is therefore counted once per field. The `share` percentages are computed on that inflated sum.

**Rule: never add up or compare `analyticalCode` rows before restricting them to a single field.**

## Step 1 — Pick the field

```json
{ "tool": "get_analytical_fields", "params": {} }
```

Returns the fields with `id`, `name`, `type`. Archived fields are included: keep only those whose `archivedAt` is `null`. The expense categories field is not in this list (read it with `get_expense_categories`).

If the user did not name the field, list the active fields and ask which one to analyse.

## Step 2 — Get that field's values

```json
{ "tool": "get_analytical_field_values", "params": { "fieldId": "<field id>" } }
```

Keep the list of value `id`s: it is what isolates the field. Archived values are included (non-null `archivedAt`) — keep them for history, but flag them.

## Step 3 — Analyse, then keep only the field's rows

```json
{
  "tool": "spendesk_analyze_spend",
  "params": {
    "fromDate": "YYYY-MM-DD",
    "toDate": "YYYY-MM-DD",
    "groupBy": ["analyticalCode", "month"],
    "limit": 50
  }
}
```

- Put `analyticalCode` **first** in `groupBy`: it is the only position where rows carry only the amounts of that value.
- Raise `limit` to 50: with the default (10), the values of the field you want can end up buried in the "Others" row.
- In the response, **keep only the rows whose `id` is in the step 2 list**. Ignore the rest.
- Maximum period: 366 days. Beyond that, split and combine only once every call has succeeded.

## Step 4 — Work out the unallocated share

The field's total (sum of the rows kept) is lower than or equal to `summary.totalAmount`. The gap is spend **with no value on this field**: present it explicitly as "unallocated" — it is often the most useful figure for FP&A.

Recompute percentages yourself, on the field's total or on `summary.totalAmount` — do not reuse `share`.

## Variant — filter on one value

`filters.analyticalCodes: ["<value id>"]` restricts to payables carrying that value on at least one line. Careful: `summary.totalAmount` and every other dimension then count those payables **in full**, including their lines on other values. Only `analyticalCode` rows (placed first) are exact.

## Recommended output format

```
Spend by <field name> — from <date> to <date>
Company total: X EUR — allocated on this field: Y EUR (Z%) — unallocated: W EUR

| <Field> | Amount | Share | Of which outstanding | Highest month |
```

Amounts are in functional currency, including VAT, on the document date (not the accounting date). The MCP does not read budgets: for a variance against budget by project, the user supplies the figures.

## Example user prompts

- "What is the spend by region over the last 12 months, month by month?"
- "How much did we spend on the Tech project this quarter, and what share is not tied to any project?"
- "Compare spend by project between Q2 and Q3"

How to install this skill

/
  1. 1
    Download the file s72-analyse-par-champ-analytique.md using the button above.
  2. 2
    Place the file in the .claude/ directory of your project (or ~/.claude/ for a global install).
    cp s72-analyse-par-champ-analytique.md .claude/s72-analyse-par-champ-analytique.md
  3. 3
    Use in Claude Code — the skill is automatically discovered. Describe your need in natural language and Claude will apply the skill instructions.
💡 Make sure the Spendesk MCP is configured in your .claude/settings.json with the tools get_analytical_fields, get_analytical_field_values, spendesk_analyze_spend.

Similar skills

★ Top
95/100·🔍 Ad hoc·Expert

Audit what the MCP covers

Probes all available MCP tools, re-evaluates coverage of 50 persona use cases, detects new fields or tools, and regenerates the gap analysis report.

CFOControllerAP Manager
90/100·📅 Weekly·Beginner

Card requests via get_requests

Explains how to use get_requests for card requests and why expense reimbursements don't appear there. Avoids a frequent source of confusion between two distinct workflows.

ControllerFinance Analyst
90/100·🔍 Ad hoc·Intermediate

Active vs archived cost centers

Distinguishes active cost centers from archived ones with correct use of get_cost_centers. Avoids the counter-intuitive isArchived vs isActive naming convention pitfall.

ControllerFinance Analyst

Interested in AI Agent services or Custom Integrations?