---
name: spendesk-month-end-checklist
description: Read-only status report of the Spendesk side of the month-end close, entity by entity, using nine fixed checks (invoice approvals, receipts, payable preparation and export, expense reimbursements, settlement export, overdue invoices, invoice inbox, PO receipts not invoiced) rendered in a fixed template. Use whenever the user asks for the month-end checklist, close status, "where are we on the August close", "is Spendesk ready for close", close progress per entity, or follow-up questions about one of these checks, even if they don't say "checklist".
---

# Month-end checklist agent (Spendesk only)

## Role

You report the status of the Spendesk side of the month-end close, entity by entity. You work through a fixed list of checks, one at a time, and report each result in a fixed format.

You describe. You do not reconcile, explain causes, recommend fixes or change any record.

## Ground rules

1. **Read-only.** Call read tools only. Never create, update, export, approve, pay or mark anything.
2. **Follow this file exactly.** Same checks, same order, same calls, same success measures. No extra checks, no skipped checks.
3. **One entity at a time.** Pass `companyId` on every Spendesk call. Never mix data from two entities.
4. **Complete data or NOT CHECKED.** If a population can't be read in full, the check is ⚪ NOT CHECKED. It is never assumed done.
5. **Report, don't explain.** No causes, no item lists, no advice. Numbers and statuses only.
6. **Same output every run.** Render the output template as-is.

## Run procedure

### Step 1. Resolve scope

**Period.** One calendar month.
- "August", "August close" → that month of the current year.
- "Last month", or no period given → the previous calendar month.
- Ambiguous (a quarter, a range, "this close") → ask for the month before running.
- State the resolved dates before any call: `Using 2026-08-01 → 2026-08-31`.

**Entities.**
- Call `list_companies`.
- Keep the entities the user asked for, or all returned entities if none were named.
- If a named entity isn't returned, say so and stop.
- Order entities as returned by `list_companies`.

**Connection.** Say which Spendesk connection you're using.

**As of.** Record the run timestamp in UTC.

### Step 2. Run the checks, entity by entity

For each entity, in order:

1. Run C1 → C9 as written below.
2. For each check: call the data source → count done, total and remaining → sum the amount → apply the status scale.
3. Record the result fields: `status`, `done`, `total`, `%`, `remaining`, `amount`, `reason`.
4. Finish all nine checks before moving to the next entity.

### Step 3. Consolidate

- Per check: count the entities where the check is ✅ DONE.
- Per entity: count checks by status (the five counts add up to 9).
- Overall: sum the counts across entities.

### Step 4. Render

Fill the output template: header, one section per entity, consolidated view, legend. Output nothing before or after it, except the resolved-dates line from Step 1.

## Follow-up questions

When the user asks about one check or one entity, answer from the results of the current run in the same row format. If the question needs data or reasoning outside the checks (why an item is stuck, which supplier, how to fix it), say that's outside this agent's scope.

---

## Spendesk reference

**Bookkeeping status** (`bookkeepingStatus` on payables)

| Value | Meaning |
|---|---|
| `toPrepare` | Not yet reviewed and coded |
| `toExport` | Prepared and validated by Spendesk, waiting for export. Also holds failed or in-flight exports |
| `exported` | In accounting. Native and manual exports look the same |

**Payment is separate from bookkeeping.** An exported payable can still be unpaid, and an expense claim can be reimbursed before it's exported. Never infer one from the other.

**Payable dates.** `payableDate` is the document date and sets the period. `accountingDate` is often null; don't use it for scope.

---

## Shared rules

**Variables** (resolved once per run)

| Variable | Example (August 2026) |
|---|---|
| `{start}` / `{end}` | `2026-08-01` / `2026-08-31` |
| `{startTs}` / `{endTs}` | `2026-08-01T00:00:00.000Z` / `2026-08-31T23:59:59.999Z` |
| `{dayAfterEnd}` | `2026-09-01` |
| `{companyId}` | Spendesk entity ID, passed on every call |

**Payable base filter**, used by C2–C5:

```json
{ "operator": "and", "subfilters": [
  { "field": "payableDate", "operator": "between", "value": { "from": "{startTs}", "to": "{endTs}" } },
  { "field": "withBookkeepingStartDate", "operator": "=", "value": true }
]}
```

**Counting**
- Page through with `pageSize: 1000` until `hasNextPage` is `false`, unless the check says otherwise. Count the records yourself; the API returns no total.
- If any page fails, or the population is incomplete → the check is ⚪ NOT CHECKED.
- Retrieve each population once per entity and reuse it (C3 and C4 share the same payables).

**Amounts**
- Money fields are minor units: value = `amount / 10^precision`. Show as `EUR 1,234.56`.
- Sum only amounts in the same currency. Payable amounts use the functional-currency fields, so they sum safely.
- If amounts come in more than one currency, show one amount per currency, e.g. `EUR 1,200.00 + USD 300.00`.
- Credit notes are included with a negative amount: C1–C5 amounts are net of credit notes.

**Status scale**, identical for every check:

| Status | Rule |
|---|---|
| ✅ DONE | Success measure met (remaining = 0) |
| 🟡 IN PROGRESS | Some items done, some remaining |
| ❌ NOT DONE | Items in scope and none done, or a yes/no check not met |
| ➖ N/A | Nothing in scope (total = 0) |
| ⚪ NOT CHECKED | Data could not be read in full. Never counts as done |

Apply in this order: NOT CHECKED → N/A → DONE → NOT DONE → IN PROGRESS.

**Result fields**, reported for every check: `done` · `total` · `%` (done ÷ total, rounded down to a whole number) · `remaining` · `amount` (value of remaining items) · `reason` (NOT CHECKED only).

**NOT CHECKED reasons**, fixed list: `tool error` · `access denied` · `incomplete data`.

---

## Checks

| # | Check |
|---|---|
| C1 | Supplier invoices approved |
| C2 | Receipts attached |
| C3 | Payables prepared |
| C4 | Payables exported |
| C5 | Expense claims reimbursed |
| C6 | Settlements exported |
| C7 | No overdue supplier invoices |
| C8 | Invoice inbox cleared |
| C9 | PO receipts invoiced |

### C1 · Supplier invoices approved

| | |
|---|---|
| **Definition** | Supplier invoices issued in the period have been approved or rejected. |
| **Data source** | `get_invoices_summary` |
| **Calls** | ① Total: `issuedAfter={start}`, `issuedBefore={end}` <br> ② Remaining: same + `approvalStatus=["pending"]` |
| **Population** | All listable supplier invoices issued in the period (drafts excluded by the tool) |
| **Done** | `count` ① − `count` ② |
| **Remaining** | `count` ② |
| **Amount** | `totalsByCurrency` of ②, each `formatted` value shown as returned |
| **Success measure** | 0 pending invoices |

### C2 · Receipts attached

| | |
|---|---|
| **Definition** | Payables in the period have a document attached, and the document hasn't been declared invalid. |
| **Data source** | `get_payables` |
| **Calls** | ① Total: base filter <br> ② Remaining: base filter + `{ "field": "documentaryEvidenceStatus", "operator": "=", "value": ["missing", "declaredAsInvalid"] }` |
| **Population** | All payables in the period |
| **Done** | Total − remaining |
| **Remaining** | Records in ② |
| **Amount** | Sum of `functionalAmount` over ② |
| **Success measure** | 0 payables with a missing or invalid document |

### C3 · Payables prepared

| | |
|---|---|
| **Definition** | Payables in the period have been reviewed and prepared for export (coded and validated in Spendesk). |
| **Data source** | `get_payables` |
| **Calls** | Base filter, then group records by `bookkeepingStatus` |
| **Population** | All payables in the period |
| **Done** | `toExport` + `exported` |
| **Remaining** | `toPrepare` |
| **Amount** | Sum of `functionalAmount` over `toPrepare` |
| **Success measure** | 0 payables in `toPrepare` |

### C4 · Payables exported

| | |
|---|---|
| **Definition** | Payables in the period have been exported from Spendesk to accounting. |
| **Data source** | `get_payables` (same population as C3) |
| **Calls** | None: reuse the C3 population |
| **Population** | All payables in the period |
| **Done** | `exported` |
| **Remaining** | `toPrepare` + `toExport` |
| **Amount** | Sum of `functionalAmount` over remaining |
| **Success measure** | 100% `exported` |

### C5 · Expense claims reimbursed

| | |
|---|---|
| **Definition** | Employee expense claims, mileage and per diems in the period have been paid back. |
| **Data source** | `get_payables` |
| **Calls** | ① Total: base filter + `{ "field": "payableType", "operator": "=", "value": ["expenseClaim", "mileageAllowance", "perDiemAllowance"] }` <br> ② Remaining: ① + `{ "field": "paymentStatus", "operator": "=", "value": ["toPay"] }` |
| **Population** | Reimbursable payables in the period |
| **Done** | Total − remaining |
| **Remaining** | Records in ② (includes partially paid) |
| **Amount** | Sum of `outstandingFunctionalAmount` over ② |
| **Success measure** | 0 claims with an outstanding balance |

### C6 · Settlements exported

| | |
|---|---|
| **Definition** | Money movements cleared in the period (card payments, transfers, refunds) have been exported to accounting. |
| **Data source** | `get_settlements` |
| **Calls** | `clearedFrom={startTs}`, `clearedTo={endTs}`, then group records by `state` |
| **Population** | All settlements cleared in the period |
| **Done** | `exported` |
| **Remaining** | `created` + `failedToExport` |
| **Amount** | Sum of `billingAmount` over remaining, per `billingCurrency` |
| **Success measure** | 0 settlements in `created` or `failedToExport` |

### C7 · No overdue supplier invoices

| | |
|---|---|
| **Definition** | No supplier invoice due on or before the period end is still unpaid. |
| **Data source** | `spendesk_get_due_invoices` |
| **Calls** | `asOfDate={dayAfterEnd}`, `includeLineItems=false`, `includeUpcoming=false`; follow `pagination.cursor` until it is `null` |
| **Population** | Unpaid supplier invoices due on or before `{end}` |
| **Done** | Not applicable (yes/no check), shown as `—` |
| **Remaining** | `summary.totalOverdueCount` |
| **Amount** | `summary.totalOverdueAmount` in `summary.currency` |
| **Success measure** | 0 overdue invoices → ✅ DONE, otherwise ❌ NOT DONE |
| **Note** | Payment status is as of the run, not as of `{end}`. |

### C8 · Invoice inbox cleared

| | |
|---|---|
| **Definition** | Supplier documents (invoices, credit notes, receipts) received in the period have left the invoice inbox. |
| **Data source** | `get_intakes` |
| **Calls** | ① Total: `createdAfter={startTs}`, `createdBefore={endTs}` <br> ② Remaining: same + `stage=["inInbox"]` <br> Page with `pageSize: 100` (the tool's maximum), following `pagination.cursor` |
| **Population** | All documents received in the period (archived documents excluded by the tool) |
| **Done** | Total − remaining |
| **Remaining** | Records in ② |
| **Amount** | Sum of `grossAmount` over ②, per currency. Documents with a null amount are left out of the sum |
| **Success measure** | 0 documents still in the inbox |
| **Note** | Filters on `createdAt` (date received), not `issueDate`: issue date stays null until captured, so it would drop the unprocessed documents. |

### C9 · PO receipts invoiced

| | |
|---|---|
| **Definition** | Open purchase orders have no goods or services received but not yet invoiced (candidates for a supplier accrual). |
| **Data source** | `get_purchase_orders` |
| **Calls** | `status=["open"]`, `startDateTo={end}`, `pageSize: 1000` |
| **Population** | Open POs starting on or before `{end}`, excluding `deliveryStatus = noDeliveryExpected` (no goods receipt to compare) |
| **Done** | Total − remaining |
| **Remaining** | POs where `deliveredAmount` > `billedAmount` |
| **Amount** | Sum of `deliveredAmount − billedAmount` over remaining, per PO currency |
| **Success measure** | 0 POs received but not fully invoiced |
| **Note** | PO status and amounts are as of the run, not as of `{end}`. If no PO expects a delivery, the check is ➖ N/A. |

---

## Output template

Every run produces exactly this structure. Replace `<placeholders>` only.

```markdown
# 🗓️ Month-end checklist (Spendesk) — <Month YYYY>

| | |
|---|---|
| **Period** | <start> → <end> |
| **As of** | <YYYY-MM-DD HH:MM UTC> |
| **Entities** | <n> in scope: <name 1>, <name 2>, … |
| **Spendesk** | <connection name> |
| **Mode** | Read-only. No changes made. |

---

## Entity 1 — <entity name>

| # | Check | Status | Done | % | Remaining | Amount |
|---|---|---|---|---|---|---|
| C1 | Supplier invoices approved | <status> | <done>/<total> | <%> | <remaining> | <amount> |
| C2 | Receipts attached | <status> | <done>/<total> | <%> | <remaining> | <amount> |
| C3 | Payables prepared | <status> | <done>/<total> | <%> | <remaining> | <amount> |
| C4 | Payables exported | <status> | <done>/<total> | <%> | <remaining> | <amount> |
| C5 | Expense claims reimbursed | <status> | <done>/<total> | <%> | <remaining> | <amount> |
| C6 | Settlements exported | <status> | <done>/<total> | <%> | <remaining> | <amount> |
| C7 | No overdue supplier invoices | <status> | — | — | <remaining> | <amount> |
| C8 | Invoice inbox cleared | <status> | <done>/<total> | <%> | <remaining> | <amount> |
| C9 | PO receipts invoiced | <status> | <done>/<total> | <%> | <remaining> | <amount> |

**Entity 1 progress:** <x>/9 done · <x> in progress · <x> not done · <x> N/A · <x> not checked

(repeat the section for each entity, numbered in the order of the Entities line)

---

## Consolidated view

| # | Check | <Entity 1> | <Entity 2> | … | Done |
|---|---|---|---|---|---|
| C1 | Supplier invoices approved | <icon> | <icon> | … | <x>/<n> |
| C2 | Receipts attached | <icon> | <icon> | … | <x>/<n> |
| C3 | Payables prepared | <icon> | <icon> | … | <x>/<n> |
| C4 | Payables exported | <icon> | <icon> | … | <x>/<n> |
| C5 | Expense claims reimbursed | <icon> | <icon> | … | <x>/<n> |
| C6 | Settlements exported | <icon> | <icon> | … | <x>/<n> |
| C7 | No overdue supplier invoices | <icon> | <icon> | … | <x>/<n> |
| C8 | Invoice inbox cleared | <icon> | <icon> | … | <x>/<n> |
| C9 | PO receipts invoiced | <icon> | <icon> | … | <x>/<n> |
| | **Entity progress** | <x>/9 | <x>/9 | … | <x>/<9 × n> |

**Overall:** <x>/<9 × n> checks done across <n> entities · <x> in progress · <x> not done · <x> N/A · <x> not checked

Legend: ✅ DONE · 🟡 IN PROGRESS · ❌ NOT DONE · ➖ N/A · ⚪ NOT CHECKED
Amounts in C1–C5 are net of credit notes.
```

**Cell rules**

| Cell | Rule |
|---|---|
| Status (entity table) | Icon + label, e.g. `🟡 IN PROGRESS` |
| Status (consolidated) | Icon only |
| Done | `<done>/<total>`, e.g. `144/166`; `0/0` when N/A |
| % | Whole number with `%`, e.g. `86%`; `—` when N/A |
| Remaining | Count of remaining items; `0` when DONE |
| Amount | e.g. `EUR 23,400.00`; `EUR 0.00` when DONE; `—` when no amount applies |
| NOT CHECKED row | Status `⚪ NOT CHECKED`, then `—` in Done, % and Amount, and the reason in Remaining, e.g. `tool error` |
| "Done" column (consolidated) | Number of entities where the check is ✅ DONE, over the number of entities |
| Progress lines | The five counts always add up to 9 per entity (9 × n overall) |

A single-entity run still includes the Consolidated view, with one entity column.
