Purchase orders and invoice linkage (payableId)
Analyzes purchase orders and their link to invoices via payableId. Explains why payableId=null does not necessarily mean no invoice exists.
79/100·🔍 Ad hoc·ExpertProcurementAP Manager
Budget & POsReconciliationget_purchase_orders
🎯 Skill purpose
Analyzes purchase orders and their link to invoices via payableId. Explains why payableId=null does not necessarily mean no invoice exists.
📊 What it produces
POs with invoice linkage status, committed amount, and explanation of cases without payableId.
⚡ Benefit
Before
Incorrect interpretation of payableId=null caused false missing invoice reports.
After
Correct understanding of PO-invoice linkage, zero false missing invoice detection.
# Instructions — Purchase Orders (POs)
## ⚠️ payableId=null ≠ "no invoice"
Each PO can have an `invoices[]` array with related invoices.
Each invoice has a `payableId` which can be:
- **UUID** → direct link to the payable (use `get_payable_by_id` for details)
- **null** → the invoice exists but cannot be resolved from its `requestId`
```json
// Invoice with payableId null — the invoice exists but is not linked:
{
"invoiceRequestId": "abc123",
"invoiceNumber": "INV-001",
"amount": { "amount": 150000, "currency": "EUR", "precision": 2 },
"status": "paid",
"payableId": null ← DO NOT conclude "no invoice"
}
```
→ In case of `payableId=null`, use `invoiceRequestId` or `invoiceNumber` for manual reconciliation.
## ⚠️ Multi-currency POs: do not sum across currencies
POs can be denominated in EUR, USD, GBP, etc. The `amount`, `billedAmount`, `deliveredAmount` fields are in the PO's currency.
→ Never add up POs in different currencies without conversion.
→ Display separately by currency or convert explicitly.
Live example: FullStory PO in USD ($21,267.89), Oracle PO in EUR (30,000 EUR).
## Step 1 — Active POs (status=open)
```json
{ "companyId": "...", "status": ["open"], "pageSize": 100 }
```
→ Returns ongoing POs that can still accept invoices.
→ `billingStatus: "lateInvoice"` → PO open but no invoice received recently.
→ `billingStatus: "partiallyBilled"` → invoices received but budget not exhausted.
## Step 2 — POs expiring soon
```json
{
"companyId": "...",
"endDateFrom": "YYYY-MM-DD",
"endDateTo": "YYYY-MM-DD",
"status": ["open"]
}
```
Example: POs expiring in the next 30 days = endDateFrom=today, endDateTo=today+30d.
## Step 3 — Calculating consumed budget
For each PO:
```
approved_budget = amount (in PO currency)
invoiced = billedAmount
delivered = deliveredAmount
net = billedAmount - creditNotes (= netAmount field)
consumption_rate = billedAmount / amount × 100
remaining_budget = amount - billedAmount
```
⚠️ A PO with `billedAmount > amount` is over budget.
## Step 4 — Accessing invoice details
For each PO with `invoices[]`:
1. If `payableId != null` → call `get_payable_by_id(payableId)` for full details
2. If `payableId == null` → note `invoiceNumber` + `invoiceRequestId` for manual reconciliation
## Live example (real data)
| PO | Description | Status | Amount | Invoiced |
|----|-------------|--------|--------|---------|
| Coworking Lyon | Coworking space | open | 26,026 EUR | 20,185 EUR (78%) |
| FullStory | SaaS subscription | open | $21,267 USD | $10,633 USD (50%) |
| Oracle | Annual subscription | open | 30,000 EUR | 0 EUR (0%) — lateInvoice |
| Coworking Lyon 2 | Extension | open | 35,424 EUR | 5,904 EUR (17%) |
Note: `payableId=null` not visible in this demo dataset — the risk is documented in the MCP spec but not testable here.
## Example prompt
- "Which POs expire in the next 30 days?" → endDateFrom/endDateTo + status=open
- "What is the consumption rate of our active POs?" → status=open + billedAmount/amount calculation
- "Find the invoices linked to the Oracle PO" → invoices[].payableId → get_payable_by_id
How to install this skill
/
- 1Download the file
s28-purchase-orders-payable-id.mdusing the button above. - 2Place the file in the
.claude/directory of your project (or~/.claude/for a global install).cp s28-purchase-orders-payable-id.md .claude/s28-purchase-orders-payable-id.md - 3Use 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_purchase_orders.Similar skills
★ Top
★ Top