- Add separate Invoice and Receipt columns to Bills table for clearer document organization - Update upload-attachment.sh to accept column parameter (defaults to Invoice, use Receipt for payment confirmations) - Update all documentation examples and workflows - Add receipt upload step to payment workflows - Update validation checklist to verify both fields 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
608 lines
18 KiB
Markdown
608 lines
18 KiB
Markdown
---
|
|
name: grist-accounting
|
|
description: Use when working with the Grist double-entry accounting system - recording transactions, entering bills, tracking vendors, querying account balances, or generating financial reports
|
|
---
|
|
|
|
# Grist Double-Entry Accounting System
|
|
|
|
## Overview
|
|
|
|
A complete double-entry accounting system for sole proprietorship service businesses. Every transaction creates balanced journal entries (debits = credits). Account balances roll up through parent-child hierarchy.
|
|
|
|
## MCP Tools Available
|
|
|
|
| Tool | Purpose |
|
|
|------|---------|
|
|
| `mcp__grist-accounting__list_documents` | List accessible Grist documents |
|
|
| `mcp__grist-accounting__list_tables` | List tables in a document |
|
|
| `mcp__grist-accounting__describe_table` | Get column schema for a table |
|
|
| `mcp__grist-accounting__get_records` | Fetch records (with optional filter, sort, limit) |
|
|
| `mcp__grist-accounting__add_records` | Insert new records, returns `{"inserted_ids": [...]}` |
|
|
| `mcp__grist-accounting__update_records` | Update existing records by ID |
|
|
| `mcp__grist-accounting__delete_records` | Delete records by ID |
|
|
| `mcp__grist-accounting__sql_query` | Run read-only SQL queries |
|
|
|
|
The document name is `accounting` for all operations.
|
|
|
|
## Date Handling
|
|
|
|
All date fields use **Unix timestamps** (seconds since 1970-01-01 UTC).
|
|
|
|
| Date | Timestamp |
|
|
|------|-----------|
|
|
| Oct 1, 2025 | 1759363200 |
|
|
| Nov 1, 2025 | 1762041600 |
|
|
| Dec 1, 2025 | 1764633600 |
|
|
| Jan 1, 2026 | 1767312000 |
|
|
|
|
Python: `int(datetime(2025, 10, 1).timestamp())`
|
|
|
|
## Complete Table Schemas
|
|
|
|
### Accounts
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| Code | Text | Account number (e.g., "5080") |
|
|
| Name | Text | Account name |
|
|
| Type | Choice | "Asset", "Liability", "Equity", "Income", "Expense" |
|
|
| Parent | Ref:Accounts | Parent account for hierarchy (0 = top-level) |
|
|
| Description | Text | |
|
|
| IsActive | Bool | |
|
|
| Balance | Formula | Calculated from transactions |
|
|
|
|
### Vendors
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| Name | Text | Vendor name |
|
|
| DefaultExpenseAccount | Ref:Accounts | Auto-fills on bill lines |
|
|
| PaymentTerms | Choice | "Due on Receipt", "Net 15", "Net 30" |
|
|
| Notes | Text | |
|
|
| IsActive | Bool | |
|
|
| Balance | Formula | Sum of unpaid bills |
|
|
|
|
### Items
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| Name | Text | Item name (e.g., "Software Subscription") |
|
|
| DefaultAccount | Ref:Accounts | Expense account for this item |
|
|
| DefaultDescription | Text | Auto-fills on bill lines |
|
|
| IsActive | Bool | |
|
|
|
|
### Bills
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| Vendor | Ref:Vendors | Required |
|
|
| BillNumber | Text | Invoice number from vendor |
|
|
| BillDate | Date | Unix timestamp |
|
|
| DueDate | Date | Unix timestamp |
|
|
| Status | Choice | "Open", "Partial", "Paid" |
|
|
| Memo | Text | |
|
|
| EntryTransaction | Ref:Transactions | Link to journal entry |
|
|
| Invoice | Attachments | Vendor invoice document (use `["L", id]` format) |
|
|
| Receipt | Attachments | Payment receipt/confirmation (use `["L", id]` format) |
|
|
| Amount | Formula | Sum of BillLines.Amount |
|
|
| AmountPaid | Formula | Sum of BillPayments.Amount |
|
|
| AmountDue | Formula | Amount - AmountPaid |
|
|
|
|
### BillLines
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| Bill | Ref:Bills | Required |
|
|
| Item | Ref:Items | Optional - auto-fills Account/Description |
|
|
| Account | Ref:Accounts | Expense account |
|
|
| Description | Text | |
|
|
| Amount | Numeric | Line item amount |
|
|
|
|
### Transactions
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| Date | Date | Unix timestamp |
|
|
| Description | Text | Transaction description |
|
|
| Reference | Text | Check number, invoice reference, etc. |
|
|
| Status | Choice | "Draft", "Posted", "Cleared" |
|
|
| Memo | Text | |
|
|
| Total | Formula | Sum of debits |
|
|
| IsBalanced | Formula | True if debits = credits |
|
|
|
|
### TransactionLines
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| Transaction | Ref:Transactions | Required |
|
|
| Account | Ref:Accounts | Required |
|
|
| Debit | Numeric | Debit amount (or 0) |
|
|
| Credit | Numeric | Credit amount (or 0) |
|
|
| Memo | Text | |
|
|
|
|
### BillPayments
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| Bill | Ref:Bills | Required |
|
|
| Transaction | Ref:Transactions | Payment journal entry |
|
|
| Amount | Numeric | Payment amount |
|
|
| PaymentDate | Date | Unix timestamp |
|
|
|
|
## Key Account IDs
|
|
|
|
| ID | Code | Name | Type |
|
|
|----|------|------|------|
|
|
| 4 | 2000 | Accounts Payable | Liability |
|
|
| 14 | 1001 | Checking Account | Asset |
|
|
| 22 | 2203 | Due to Owner | Liability |
|
|
| 36 | 5080 | Software & Subscriptions | Expense |
|
|
|
|
Query all accounts:
|
|
```sql
|
|
SELECT id, Code, Name, Type FROM Accounts WHERE IsActive = true ORDER BY Code
|
|
```
|
|
|
|
## Account Types
|
|
|
|
| Type | Normal Balance | Increases With | Examples |
|
|
|------|----------------|----------------|----------|
|
|
| Asset | Debit | Debit | Cash, AR, Prepaid |
|
|
| Liability | Credit | Credit | AP, Credit Cards, Due to Owner |
|
|
| Equity | Credit | Credit | Owner's Investment, Draws, Retained Earnings |
|
|
| Income | Credit | Credit | Service Revenue, Interest Income |
|
|
| Expense | Debit | Debit | Rent, Utilities, Office Supplies |
|
|
|
|
## Complete Workflows
|
|
|
|
### Create a Vendor
|
|
|
|
```python
|
|
add_records("Vendors", [{
|
|
"Name": "Acme Corp",
|
|
"DefaultExpenseAccount": 36, # Software & Subscriptions
|
|
"PaymentTerms": "Due on Receipt",
|
|
"Notes": "Software vendor",
|
|
"IsActive": True
|
|
}])
|
|
# Returns: {"inserted_ids": [vendor_id]}
|
|
```
|
|
|
|
### Create Items for Common Purchases
|
|
|
|
```python
|
|
add_records("Items", [{
|
|
"Name": "Monthly Software",
|
|
"DefaultAccount": 36,
|
|
"DefaultDescription": "Monthly SaaS subscription",
|
|
"IsActive": True
|
|
}])
|
|
```
|
|
|
|
### Complete Bill Entry (5 Steps)
|
|
|
|
**Step 1: Create Bill Header**
|
|
```python
|
|
add_records("Bills", [{
|
|
"Vendor": 1, # vendor_id
|
|
"BillNumber": "INV-001",
|
|
"BillDate": 1759708800, # Unix timestamp
|
|
"DueDate": 1759708800,
|
|
"Status": "Open",
|
|
"Memo": "October services"
|
|
}])
|
|
# Returns: {"inserted_ids": [bill_id]}
|
|
```
|
|
|
|
**Step 2: Create Bill Line(s)**
|
|
```python
|
|
add_records("BillLines", [{
|
|
"Bill": 1, # bill_id from step 1
|
|
"Item": 1, # optional - auto-fills Account/Description
|
|
"Account": 36, # expense account
|
|
"Description": "Monthly subscription",
|
|
"Amount": 100.00
|
|
}])
|
|
```
|
|
|
|
**Step 3: Create Journal Entry**
|
|
```python
|
|
# Transaction header
|
|
add_records("Transactions", [{
|
|
"Date": 1759708800,
|
|
"Description": "Acme Corp - October services",
|
|
"Reference": "INV-001",
|
|
"Status": "Posted"
|
|
}])
|
|
# Returns: {"inserted_ids": [txn_id]}
|
|
|
|
# Transaction lines: Debit expense, Credit AP
|
|
add_records("TransactionLines", [
|
|
{"Transaction": 1, "Account": 36, "Debit": 100.00, "Credit": 0, "Memo": "Monthly subscription"},
|
|
{"Transaction": 1, "Account": 4, "Debit": 0, "Credit": 100.00, "Memo": "Monthly subscription"}
|
|
])
|
|
```
|
|
|
|
**Step 4: Link Bill to Transaction**
|
|
```python
|
|
update_records("Bills", [{"id": 1, "fields": {"EntryTransaction": 1}}])
|
|
```
|
|
|
|
**Step 5: Upload Invoice (if available)**
|
|
|
|
If an invoice PDF is available, upload and link it to the Invoice field:
|
|
```bash
|
|
# Get session token, then upload to Invoice field
|
|
bash /path/to/scripts/upload-attachment.sh invoice.pdf Bills 1 $TOKEN Invoice
|
|
```
|
|
|
|
Or for batch uploads, use a script (see Batch Operations).
|
|
|
|
### Pay Bill from Checking Account
|
|
|
|
```python
|
|
# Step 1: Create payment transaction
|
|
add_records("Transactions", [{
|
|
"Date": 1760832000,
|
|
"Description": "Payment - Acme Corp INV-001",
|
|
"Reference": "Check #1001",
|
|
"Status": "Cleared"
|
|
}])
|
|
# Returns: {"inserted_ids": [txn_id]}
|
|
|
|
# Step 2: Debit AP, Credit Checking
|
|
add_records("TransactionLines", [
|
|
{"Transaction": 2, "Account": 4, "Debit": 100.00, "Credit": 0, "Memo": "Pay INV-001"},
|
|
{"Transaction": 2, "Account": 14, "Debit": 0, "Credit": 100.00, "Memo": "Pay INV-001"}
|
|
])
|
|
|
|
# Step 3: Create BillPayment record
|
|
add_records("BillPayments", [{
|
|
"Bill": 1,
|
|
"Transaction": 2,
|
|
"Amount": 100.00,
|
|
"PaymentDate": 1760832000
|
|
}])
|
|
|
|
# Step 4: Update bill status
|
|
update_records("Bills", [{"id": 1, "fields": {"Status": "Paid"}}])
|
|
|
|
# Step 5: Upload receipt (if available)
|
|
bash /path/to/scripts/upload-attachment.sh receipt.pdf Bills 1 $TOKEN Receipt
|
|
```
|
|
|
|
### Pay Bill via Owner Reimbursement
|
|
|
|
When the owner pays a business expense personally:
|
|
|
|
```python
|
|
# Step 1: Create payment transaction
|
|
add_records("Transactions", [{
|
|
"Date": 1760832000,
|
|
"Description": "Owner payment - Acme Corp INV-001",
|
|
"Reference": "Owner Reimb",
|
|
"Status": "Posted"
|
|
}])
|
|
|
|
# Step 2: Debit AP, Credit Due to Owner (not Checking)
|
|
add_records("TransactionLines", [
|
|
{"Transaction": 2, "Account": 4, "Debit": 100.00, "Credit": 0, "Memo": "Pay INV-001"},
|
|
{"Transaction": 2, "Account": 22, "Debit": 0, "Credit": 100.00, "Memo": "Owner paid"}
|
|
])
|
|
|
|
# Step 3: Create BillPayment record
|
|
add_records("BillPayments", [{
|
|
"Bill": 1,
|
|
"Transaction": 2,
|
|
"Amount": 100.00,
|
|
"PaymentDate": 1760832000
|
|
}])
|
|
|
|
# Step 4: Update bill status
|
|
update_records("Bills", [{"id": 1, "fields": {"Status": "Paid"}}])
|
|
|
|
# Step 5: Upload receipt (if available)
|
|
bash /path/to/scripts/upload-attachment.sh receipt.pdf Bills 1 $TOKEN Receipt
|
|
```
|
|
|
|
### Reimburse Owner
|
|
|
|
When business pays back the owner:
|
|
|
|
```python
|
|
add_records("Transactions", [{
|
|
"Date": 1762041600,
|
|
"Description": "Owner reimbursement",
|
|
"Reference": "Transfer",
|
|
"Status": "Cleared"
|
|
}])
|
|
|
|
add_records("TransactionLines", [
|
|
{"Transaction": 3, "Account": 22, "Debit": 500.00, "Credit": 0, "Memo": "Reimburse owner"},
|
|
{"Transaction": 3, "Account": 14, "Debit": 0, "Credit": 500.00, "Memo": "Reimburse owner"}
|
|
])
|
|
```
|
|
|
|
## Batch Operations
|
|
|
|
When entering multiple bills efficiently:
|
|
|
|
1. **Create all Bills first** → collect inserted IDs
|
|
2. **Create all BillLines** referencing bill IDs
|
|
3. **Create all Transactions** → collect inserted IDs
|
|
4. **Create all TransactionLines** referencing transaction IDs
|
|
5. **Update all Bills** with EntryTransaction links in one call
|
|
6. (If paying) Create payment transactions, lines, and BillPayments
|
|
7. **Upload invoice attachments** if files are available
|
|
|
|
### Batch Attachment Uploads
|
|
|
|
When invoice files are available, upload them after bill entry:
|
|
|
|
1. Request session token with write permission (1 hour TTL for batch work)
|
|
2. Create a mapping of bill_id → invoice file path
|
|
3. Loop: upload each file, link to corresponding bill
|
|
|
|
```bash
|
|
# Example batch upload pattern for invoices
|
|
TOKEN=$(request_session_token with write permission)
|
|
for each (bill_id, invoice_path):
|
|
curl -X POST -H "Authorization: Bearer $TOKEN" \
|
|
-F "file=@$invoice_path" \
|
|
https://grist-mcp.bballou.com/api/v1/attachments
|
|
# Returns attachment_id
|
|
update_records("Bills", [{"id": bill_id, "fields": {"Invoice": ["L", attachment_id]}}])
|
|
|
|
# For receipts (after payment):
|
|
update_records("Bills", [{"id": bill_id, "fields": {"Receipt": ["L", attachment_id]}}])
|
|
```
|
|
|
|
Example batch update:
|
|
```python
|
|
update_records("Bills", [
|
|
{"id": 1, "fields": {"EntryTransaction": 1}},
|
|
{"id": 2, "fields": {"EntryTransaction": 2}},
|
|
{"id": 3, "fields": {"EntryTransaction": 3}}
|
|
])
|
|
```
|
|
|
|
## Common Queries
|
|
|
|
### Unpaid Bills by Vendor
|
|
```sql
|
|
SELECT v.Name, b.BillNumber, b.BillDate, b.Amount, b.AmountDue
|
|
FROM Bills b
|
|
JOIN Vendors v ON b.Vendor = v.id
|
|
WHERE b.Status IN ('Open', 'Partial')
|
|
ORDER BY b.DueDate
|
|
```
|
|
|
|
### Bills Summary by Vendor
|
|
```sql
|
|
SELECT v.Name as Vendor, COUNT(b.id) as Bills, SUM(b.Amount) as Total, SUM(b.AmountDue) as Due
|
|
FROM Bills b
|
|
JOIN Vendors v ON b.Vendor = v.id
|
|
GROUP BY v.Name
|
|
ORDER BY Total DESC
|
|
```
|
|
|
|
### Account Balances (Non-Zero)
|
|
```sql
|
|
SELECT Code, Name, Type, Balance
|
|
FROM Accounts
|
|
WHERE Balance != 0
|
|
ORDER BY Code
|
|
```
|
|
|
|
### Owner Reimbursement Balance
|
|
```sql
|
|
SELECT Balance FROM Accounts WHERE Code = '2203'
|
|
```
|
|
|
|
### Expense Summary by Account
|
|
```sql
|
|
SELECT a.Code, a.Name, a.Balance
|
|
FROM Accounts a
|
|
WHERE a.Type = 'Expense' AND a.Balance != 0
|
|
ORDER BY a.Balance DESC
|
|
```
|
|
|
|
### Transaction History for Account
|
|
```sql
|
|
SELECT t.Date, t.Description, t.Reference, tl.Debit, tl.Credit
|
|
FROM TransactionLines tl
|
|
JOIN Transactions t ON tl.Transaction = t.id
|
|
WHERE tl.Account = 36
|
|
ORDER BY t.Date DESC
|
|
```
|
|
|
|
### Verify All Transactions Balance
|
|
```sql
|
|
SELECT id, Description, Total, IsBalanced
|
|
FROM Transactions
|
|
WHERE IsBalanced = false
|
|
```
|
|
|
|
## Financial Reports
|
|
|
|
### Balance Sheet
|
|
|
|
Shows Assets = Liabilities + Equity at a point in time.
|
|
|
|
**Important:** Parent accounts roll up child balances. Query only top-level parents (Parent = 0) to avoid double-counting.
|
|
|
|
```sql
|
|
-- Assets, Liabilities, Equity (top-level only)
|
|
SELECT Code, Name, Type, Balance
|
|
FROM Accounts
|
|
WHERE Type IN ('Asset', 'Liability', 'Equity')
|
|
AND Parent = 0
|
|
ORDER BY Type, Code
|
|
```
|
|
|
|
```sql
|
|
-- Net Income (for Equity section)
|
|
-- Query leaf expense accounts only (no children)
|
|
SELECT
|
|
COALESCE(SUM(CASE WHEN Type = 'Income' THEN Balance ELSE 0 END), 0) -
|
|
COALESCE(SUM(CASE WHEN Type = 'Expense' THEN Balance ELSE 0 END), 0) as NetIncome
|
|
FROM Accounts
|
|
WHERE Type IN ('Income', 'Expense')
|
|
AND id NOT IN (SELECT DISTINCT Parent FROM Accounts WHERE Parent != 0)
|
|
```
|
|
|
|
**Presentation:**
|
|
| **Assets** | |
|
|
|---|---:|
|
|
| Cash & Bank Accounts | $X.XX |
|
|
| Accounts Receivable | $X.XX |
|
|
| **Total Assets** | **$X.XX** |
|
|
|
|
| **Liabilities** | |
|
|
|---|---:|
|
|
| Accounts Payable | $X.XX |
|
|
| Due to Owner | $X.XX |
|
|
| **Total Liabilities** | **$X.XX** |
|
|
|
|
| **Equity** | |
|
|
|---|---:|
|
|
| Retained Earnings | $X.XX |
|
|
| Net Income (Loss) | $X.XX |
|
|
| **Total Equity** | **$X.XX** |
|
|
|
|
| **Total Liabilities + Equity** | **$X.XX** |
|
|
|
|
### Income Statement
|
|
|
|
Shows Revenue - Expenses = Net Income for a period.
|
|
|
|
```sql
|
|
-- All income and expense accounts (leaf accounts only)
|
|
SELECT Code, Name, Type, Balance
|
|
FROM Accounts
|
|
WHERE Type IN ('Income', 'Expense')
|
|
AND Balance != 0
|
|
AND id NOT IN (SELECT DISTINCT Parent FROM Accounts WHERE Parent != 0)
|
|
ORDER BY Type DESC, Code
|
|
```
|
|
|
|
**Presentation:**
|
|
| **Income** | |
|
|
|---|---:|
|
|
| Service Revenue | $X.XX |
|
|
| **Total Income** | **$X.XX** |
|
|
|
|
| **Expenses** | |
|
|
|---|---:|
|
|
| Software & Subscriptions | $X.XX |
|
|
| Professional Services | $X.XX |
|
|
| **Total Expenses** | **$X.XX** |
|
|
|
|
| **Net Income (Loss)** | **$X.XX** |
|
|
|
|
### Trial Balance
|
|
|
|
Lists all accounts with non-zero balances. Debits should equal Credits.
|
|
|
|
```sql
|
|
SELECT
|
|
Code,
|
|
Name,
|
|
Type,
|
|
CASE WHEN Type IN ('Asset', 'Expense') THEN Balance ELSE 0 END as Debit,
|
|
CASE WHEN Type IN ('Liability', 'Equity', 'Income') THEN Balance ELSE 0 END as Credit
|
|
FROM Accounts
|
|
WHERE Balance != 0
|
|
AND id NOT IN (SELECT DISTINCT Parent FROM Accounts WHERE Parent != 0)
|
|
ORDER BY Code
|
|
```
|
|
|
|
### Accounts Payable Aging
|
|
|
|
```sql
|
|
SELECT
|
|
v.Name as Vendor,
|
|
b.BillNumber,
|
|
b.BillDate,
|
|
b.DueDate,
|
|
b.AmountDue,
|
|
CASE
|
|
WHEN b.DueDate >= strftime('%s', 'now') THEN 'Current'
|
|
WHEN b.DueDate >= strftime('%s', 'now') - 2592000 THEN '1-30 Days'
|
|
WHEN b.DueDate >= strftime('%s', 'now') - 5184000 THEN '31-60 Days'
|
|
ELSE '60+ Days'
|
|
END as Aging
|
|
FROM Bills b
|
|
JOIN Vendors v ON b.Vendor = v.id
|
|
WHERE b.Status IN ('Open', 'Partial')
|
|
ORDER BY b.DueDate
|
|
```
|
|
|
|
## Validation Checklist
|
|
|
|
After entering bills, verify:
|
|
|
|
- [ ] Total bills match expected: `SELECT SUM(Amount) FROM Bills`
|
|
- [ ] All transactions balanced: `SELECT * FROM Transactions WHERE IsBalanced = false`
|
|
- [ ] AP balance correct: `SELECT Balance FROM Accounts WHERE Code = '2000'`
|
|
- [ ] Expense accounts increased appropriately
|
|
- [ ] Vendor balances reflect unpaid bills
|
|
- [ ] Invoices attached: `SELECT id, BillNumber FROM Bills WHERE Invoice IS NULL`
|
|
- [ ] Receipts attached for paid bills: `SELECT id, BillNumber FROM Bills WHERE Status = 'Paid' AND Receipt IS NULL`
|
|
|
|
## Common Mistakes
|
|
|
|
| Mistake | Fix |
|
|
|---------|-----|
|
|
| Transaction not balanced | Ensure SUM(Debit) = SUM(Credit) before saving |
|
|
| Wrong debit/credit direction | Assets/Expenses increase with debit; Liabilities/Equity/Income increase with credit |
|
|
| Posting to parent account | Post to leaf accounts (1001 Checking, not 1000 Cash) |
|
|
| Forgetting AP entry for bills | Bills need both the expense debit AND the AP credit |
|
|
| Missing EntryTransaction link | Always update Bill.EntryTransaction after creating journal entry |
|
|
| Bill status not updated | Manually set Status to "Paid" after full payment |
|
|
| Using string dates | Dates must be Unix timestamps (seconds), not strings |
|
|
| Missing invoice/receipt | Upload invoice after bill entry, receipt after payment |
|
|
|
|
## Uploading Attachments
|
|
|
|
Attachments (invoices, receipts) are uploaded via the HTTP proxy endpoint, not MCP tools. This is efficient for binary files.
|
|
|
|
### Workflow
|
|
|
|
1. **Request session token** with write permission via MCP
|
|
2. **Upload file** via `POST /api/v1/attachments` with multipart/form-data
|
|
3. **Link attachment** to record via `update_records`
|
|
|
|
### Upload Script
|
|
|
|
Use `scripts/upload-attachment.sh` in this skill directory:
|
|
|
|
```bash
|
|
# Get session token first (via MCP request_session_token tool)
|
|
# Then run:
|
|
bash scripts/upload-attachment.sh invoice.pdf Bills 13 # Invoice column (default)
|
|
bash scripts/upload-attachment.sh invoice.pdf Bills 13 $TOKEN # With token
|
|
bash scripts/upload-attachment.sh receipt.pdf Bills 13 $TOKEN Receipt # Receipt column
|
|
|
|
# Environment variable for custom endpoint:
|
|
GRIST_MCP_URL=https://custom.example.com bash scripts/upload-attachment.sh ...
|
|
```
|
|
|
|
Run `bash scripts/upload-attachment.sh` without arguments for full usage.
|
|
|
|
### Linking Attachments Manually
|
|
|
|
Grist attachment columns use format: `["L", attachment_id]`
|
|
|
|
```python
|
|
# Link invoice to bill
|
|
update_records("Bills", [{"id": 13, "fields": {"Invoice": ["L", 1]}}])
|
|
|
|
# Link receipt to bill (after payment)
|
|
update_records("Bills", [{"id": 13, "fields": {"Receipt": ["L", 2]}}])
|
|
```
|
|
|
|
## Formula Columns (Auto-Calculated)
|
|
|
|
| Table.Column | Description |
|
|
|--------------|-------------|
|
|
| Accounts.Balance | OwnBalance + ChildrenBalance |
|
|
| Transactions.IsBalanced | True if sum of debits = sum of credits |
|
|
| Transactions.Total | Sum of debit amounts |
|
|
| Bills.Amount | Sum of BillLines.Amount |
|
|
| Bills.AmountPaid | Sum of BillPayments.Amount |
|
|
| Bills.AmountDue | Amount - AmountPaid |
|
|
| Vendors.Balance | Sum of AmountDue for unpaid bills |
|