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:
```
committed_amount = amount (CURRENT committed amount in PO currency โ not the originally approved budget, which the tool does not return)
invoiced = billedAmount
delivered = deliveredAmount
net_of_vat = netAmount (net-of-VAT counterpart of amount; field absent when no net amount was declared โ never treat it as 0)
consumption_rate = billedAmount / amount ร 100
remaining_budget = amount - billedAmount
```
โ ๏ธ A budget overrun cannot be detected here: `amount` may be realigned to `billedAmount`. Say the originally approved budget is not available rather than reporting "no overruns".
## 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