From 357d1aadc8a432eb40e9be45826aaecc8dcead31 Mon Sep 17 00:00:00 2001 From: Bill Ballou Date: Wed, 14 Jan 2026 19:16:28 -0500 Subject: [PATCH] Add JSON templates for transaction entry Introduces templates/ directory with pre-built record structures that only include writable fields, preventing 400 errors from formula column writes. Templates: - bill-paid-credit-card.json: Invoice paid by business credit card - bill-paid-owner.json: Invoice paid by owner (reimbursement) - bill-paid-checking.json: Invoice paid from checking account - bill-unpaid.json: Invoice recorded but not yet paid - pay-existing-bill.json: Payment for existing open bill - direct-expense.json: Bank fees and minor expenses Also adds references/templates.md usage guide and updates SKILL.md with template references and formula column warnings. --- SKILL.md | 24 +++- references/templates.md | 187 +++++++++++++++++++++++++++ templates/bill-paid-checking.json | 178 +++++++++++++++++++++++++ templates/bill-paid-credit-card.json | 177 +++++++++++++++++++++++++ templates/bill-paid-owner.json | 177 +++++++++++++++++++++++++ templates/bill-unpaid.json | 115 ++++++++++++++++ templates/direct-expense.json | 92 +++++++++++++ templates/pay-existing-bill.json | 119 +++++++++++++++++ 8 files changed, 1067 insertions(+), 2 deletions(-) create mode 100644 references/templates.md create mode 100644 templates/bill-paid-checking.json create mode 100644 templates/bill-paid-credit-card.json create mode 100644 templates/bill-paid-owner.json create mode 100644 templates/bill-unpaid.json create mode 100644 templates/direct-expense.json create mode 100644 templates/pay-existing-bill.json diff --git a/SKILL.md b/SKILL.md index 04df10a..b72faac 100644 --- a/SKILL.md +++ b/SKILL.md @@ -11,11 +11,26 @@ Double-entry accounting for sole proprietorship. Every transaction creates balan | Task | Action | |------|--------| -| Record vendor invoice | Create Bill + BillLines + Transaction + TransactionLines, then audit | -| Record payment | Create payment Transaction + BillPayment, update Bill status | +| Record vendor invoice | Use template from `templates/`, then audit | +| Record payment | Use template from `templates/`, then audit | | Query balances | Use `sql_query` on Accounts table | | Generate reports | See [queries.md](references/queries.md) | +## Transaction Templates + +**Always use templates** when creating transactions to avoid errors with formula fields. + +| Scenario | Template | +|----------|----------| +| Invoice paid by credit card | [bill-paid-credit-card.json](templates/bill-paid-credit-card.json) | +| Invoice paid by owner | [bill-paid-owner.json](templates/bill-paid-owner.json) | +| Invoice paid from checking | [bill-paid-checking.json](templates/bill-paid-checking.json) | +| Invoice not yet paid | [bill-unpaid.json](templates/bill-unpaid.json) | +| Pay existing bill | [pay-existing-bill.json](templates/pay-existing-bill.json) | +| Direct expense (no bill) | [direct-expense.json](templates/direct-expense.json) | + +Templates contain only writable fields. See [templates.md](references/templates.md) for usage guide. + ## Recording Transactions: Decision Guide | Source Document | What to Create | @@ -110,11 +125,15 @@ After entering bills: | Mistake | Fix | |---------|-----| +| Writing to formula columns | Use templates - they only include writable fields | | Transaction not balanced | Ensure SUM(Debit) = SUM(Credit) | | Wrong debit/credit direction | Assets/Expenses: debit increases; Liabilities/Equity/Income: credit increases | | Posting to parent account | Post to leaf accounts (1001 not 1000) | | Missing EntryTransaction link | Always link Bill to Transaction | | Using string dates | Use Unix timestamps | +| SQL error on TransactionLines | Column `Transaction` is reserved; use `get_records` with filter | + +**Formula Columns (read-only):** Bills.Amount, Bills.AmountPaid, Bills.AmountDue, Transactions.Total, Transactions.IsBalanced ## Uploading Attachments @@ -171,6 +190,7 @@ For full audit queries and remediation: see [audit.md](references/audit.md) | File | Contents | |------|----------| +| [references/templates.md](references/templates.md) | Template usage guide | | [references/schema.md](references/schema.md) | Complete table schemas | | [references/workflows.md](references/workflows.md) | Detailed code examples | | [references/queries.md](references/queries.md) | SQL queries and financial reports | diff --git a/references/templates.md b/references/templates.md new file mode 100644 index 0000000..3c5c5cb --- /dev/null +++ b/references/templates.md @@ -0,0 +1,187 @@ +# Transaction Templates + +JSON templates for common accounting scenarios. Templates contain only **writable fields** to prevent errors when creating records. + +## Template Selection Guide + +| Scenario | Template | +|----------|----------| +| Vendor invoice paid by business credit card | `bill-paid-credit-card.json` | +| Vendor invoice paid by owner personally | `bill-paid-owner.json` | +| Vendor invoice paid from checking account | `bill-paid-checking.json` | +| Vendor invoice received but not yet paid | `bill-unpaid.json` | +| Recording payment for previously entered bill | `pay-existing-bill.json` | +| Bank fees, minor expenses without invoices | `direct-expense.json` | + +## Template Structure + +Each template contains: + +```json +{ + "_meta": { + "name": "Template name", + "description": "When to use this template", + "scenario": "Specific use case" + }, + "_variables": { + "variable_name": "description and type" + }, + "_sequence": [ + "Ordered steps to execute" + ], + "records": { + "record_name": { + "_doc": "Step documentation", + "_table": "Target table", + "_operation": "add_records or update_records", + "_requires": ["dependent variables"], + "payload": { ... } + } + }, + "journal_entries": { + "Summary of accounting entries" + } +} +``` + +## How to Use Templates + +### 1. Select the Appropriate Template + +Read the `_meta.scenario` to confirm you have the right template. + +### 2. Gather Required Variables + +Check `_variables` section for all required data: + +```json +"_variables": { + "vendor_id": "integer - Vendor record ID", + "bill_number": "string - Invoice/bill number from vendor", + "date_timestamp": "integer - Unix timestamp", + "amount": "number - Total amount including tax" +} +``` + +### 3. Follow the Sequence + +Execute steps in order from `_sequence`. Each step corresponds to a record in `records`: + +``` +1. Create Bill record → get bill_id +2. Create BillLine → links to bill_id +3. Create Transaction → get entry_txn_id +... +``` + +### 4. Substitute Variables + +Replace `{{variable}}` placeholders with actual values: + +**Template:** +```json +{ + "Vendor": "{{vendor_id}}", + "BillNumber": "{{bill_number}}", + "Amount": "{{amount}}" +} +``` + +**Substituted:** +```json +{ + "Vendor": 1, + "BillNumber": "INV-001", + "Amount": 45.47 +} +``` + +### 5. Track Generated IDs + +Some steps require IDs from previous steps (noted in `_requires`): + +- `bill_id` → returned from Bill creation +- `entry_txn_id` → returned from entry Transaction creation +- `payment_txn_id` → returned from payment Transaction creation + +### 6. Run Audit + +Always verify with audit queries after completing all steps. + +## Key Account IDs + +Quick reference for account substitution: + +| Account | ID | Code | Use For | +|---------|-----|------|---------| +| Accounts Payable | 4 | 2000 | All bill entries | +| Checking Account | 14 | 1001 | Checking payments | +| Business Credit Card | 19 | 2101 | Credit card payments | +| Due to Owner | 22 | 2203 | Owner paid personally | +| Software & Subscriptions | 36 | 5080 | SaaS, API costs | +| Bank & Merchant Fees | 30 | 5020 | Bank fees | + +## Formula Fields (Read-Only) + +**Never include these fields in `add_records` payloads:** + +| Table | Formula Fields | +|-------|----------------| +| Bills | Amount, AmountPaid, AmountDue | +| Transactions | Total, IsBalanced, Transaction_ID, Fiscal_Year | + +These are calculated automatically by Grist. + +## Example: Using bill-paid-credit-card.json + +**Scenario:** Anthropic invoice #43I1T40F-0018 for $45.47 paid by credit card. + +**Variables:** +``` +vendor_id = 1 (Anthropic) +bill_number = "43I1T40F-0018" +date_timestamp = 1768435200 (Jan 14, 2026) +due_date_timestamp = 1768435200 +amount = 45.47 +expense_account_id = 36 (Software & Subscriptions) +line_description = "API auto-recharge credits" +vendor_name = "Anthropic" +receipt_number = "2687-3787-3014" +``` + +**Execution:** +1. `add_records("Bills", [payload])` → bill_id = 26 +2. `add_records("BillLines", [payload])` → uses bill_id +3. `add_records("Transactions", [payload])` → entry_txn_id = 52 +4. `add_records("TransactionLines", [payload])` → uses entry_txn_id +5. `update_records("Bills", [link payload])` → link Bill to Transaction +6. `add_records("Transactions", [payload])` → payment_txn_id = 53 +7. `add_records("TransactionLines", [payload])` → uses payment_txn_id +8. `add_records("BillPayments", [payload])` → links bill to payment +9. `update_records("Bills", [{id: 26, fields: {Status: "Paid"}}])` +10. Upload attachments +11. Run audit + +## SQL Reserved Words + +When querying `TransactionLines`, the column `Transaction` is a SQL reserved word. Use `get_records` with filter instead of `sql_query`: + +```python +# Instead of (fails): +sql_query("SELECT * FROM TransactionLines WHERE Transaction = 52") + +# Use: +get_records("TransactionLines", filter={"Transaction": [52]}) +``` + +## Available Templates + +| File | Purpose | +|------|---------| +| [bill-paid-credit-card.json](../templates/bill-paid-credit-card.json) | Invoice paid by business credit card | +| [bill-paid-owner.json](../templates/bill-paid-owner.json) | Invoice paid by owner (reimbursement) | +| [bill-paid-checking.json](../templates/bill-paid-checking.json) | Invoice paid from checking account | +| [bill-unpaid.json](../templates/bill-unpaid.json) | Invoice recorded but not yet paid | +| [pay-existing-bill.json](../templates/pay-existing-bill.json) | Payment for previously entered bill | +| [direct-expense.json](../templates/direct-expense.json) | Direct expense without vendor bill | diff --git a/templates/bill-paid-checking.json b/templates/bill-paid-checking.json new file mode 100644 index 0000000..d55f457 --- /dev/null +++ b/templates/bill-paid-checking.json @@ -0,0 +1,178 @@ +{ + "_meta": { + "name": "Bill Paid from Checking Account", + "description": "Record a vendor bill paid directly from business checking account", + "scenario": "Invoice received and paid via check, ACH, or bank transfer", + "accounts": { + "expense": "The expense account to debit", + "checking": "Checking Account asset (14) - credits decrease cash balance" + } + }, + "_variables": { + "vendor_id": "integer - Vendor record ID", + "bill_number": "string - Invoice/bill number from vendor", + "date_timestamp": "integer - Unix timestamp for bill date", + "due_date_timestamp": "integer - Unix timestamp for due date", + "payment_date_timestamp": "integer - Unix timestamp for payment date (may differ from bill date)", + "amount": "number - Total amount including tax", + "expense_account_id": "integer - Expense account ID to debit", + "line_description": "string - Description for bill line", + "vendor_name": "string - Vendor name for transaction descriptions", + "check_number": "string - Check number or payment reference" + }, + "_sequence": [ + "1. Create Bill record → get bill_id", + "2. Create BillLine → links to bill_id", + "3. Create entry Transaction → get entry_txn_id", + "4. Create entry TransactionLines (Dr Expense, Cr AP)", + "5. Update Bill.EntryTransaction → link to entry_txn_id", + "6. Create payment Transaction → get payment_txn_id", + "7. Create payment TransactionLines (Dr AP, Cr Checking)", + "8. Create BillPayment record", + "9. Update Bill.Status → 'Paid'", + "10. Upload attachments (Invoice, Receipt)", + "11. Run audit checks" + ], + "records": { + "bill": { + "_doc": "Step 1: Create Bill header. Do NOT include Amount - it's a formula field.", + "_table": "Bills", + "_operation": "add_records", + "payload": { + "Vendor": "{{vendor_id}}", + "BillNumber": "{{bill_number}}", + "BillDate": "{{date_timestamp}}", + "DueDate": "{{due_date_timestamp}}", + "Status": "Open", + "Memo": "{{line_description}}" + } + }, + "bill_line": { + "_doc": "Step 2: Create BillLine. This populates the Bill.Amount formula.", + "_table": "BillLines", + "_operation": "add_records", + "_requires": ["bill_id"], + "payload": { + "Bill": "{{bill_id}}", + "Account": "{{expense_account_id}}", + "Description": "{{line_description}}", + "Amount": "{{amount}}" + } + }, + "entry_transaction": { + "_doc": "Step 3: Create entry transaction header.", + "_table": "Transactions", + "_operation": "add_records", + "payload": { + "Date": "{{date_timestamp}}", + "Description": "{{vendor_name}} - Invoice {{bill_number}}", + "Reference": "{{bill_number}}", + "Status": "Posted" + } + }, + "entry_transaction_lines": { + "_doc": "Step 4: Create entry transaction lines. Debit expense, credit AP.", + "_table": "TransactionLines", + "_operation": "add_records", + "_requires": ["entry_txn_id"], + "payload": [ + { + "Transaction": "{{entry_txn_id}}", + "Account": "{{expense_account_id}}", + "Debit": "{{amount}}", + "Credit": 0, + "Memo": "{{line_description}}" + }, + { + "Transaction": "{{entry_txn_id}}", + "Account": 4, + "Debit": 0, + "Credit": "{{amount}}", + "Memo": "Accounts Payable" + } + ] + }, + "link_bill_to_entry": { + "_doc": "Step 5: Link Bill to entry transaction.", + "_table": "Bills", + "_operation": "update_records", + "_requires": ["bill_id", "entry_txn_id"], + "payload": { + "id": "{{bill_id}}", + "fields": { + "EntryTransaction": "{{entry_txn_id}}" + } + } + }, + "payment_transaction": { + "_doc": "Step 6: Create payment transaction header.", + "_table": "Transactions", + "_operation": "add_records", + "payload": { + "Date": "{{payment_date_timestamp}}", + "Description": "Payment to {{vendor_name}}", + "Reference": "{{check_number}}", + "Status": "Cleared" + } + }, + "payment_transaction_lines": { + "_doc": "Step 7: Create payment transaction lines. Debit AP, credit Checking.", + "_table": "TransactionLines", + "_operation": "add_records", + "_requires": ["payment_txn_id"], + "payload": [ + { + "Transaction": "{{payment_txn_id}}", + "Account": 4, + "Debit": "{{amount}}", + "Credit": 0, + "Memo": "Accounts Payable" + }, + { + "Transaction": "{{payment_txn_id}}", + "Account": 14, + "Debit": 0, + "Credit": "{{amount}}", + "Memo": "Checking Account" + } + ] + }, + "bill_payment": { + "_doc": "Step 8: Create BillPayment linking bill to payment transaction.", + "_table": "BillPayments", + "_operation": "add_records", + "_requires": ["bill_id", "payment_txn_id"], + "payload": { + "Bill": "{{bill_id}}", + "Transaction": "{{payment_txn_id}}", + "Amount": "{{amount}}", + "PaymentDate": "{{payment_date_timestamp}}" + } + }, + "mark_paid": { + "_doc": "Step 9: Update Bill status to Paid.", + "_table": "Bills", + "_operation": "update_records", + "_requires": ["bill_id"], + "payload": { + "id": "{{bill_id}}", + "fields": { + "Status": "Paid" + } + } + } + }, + "journal_entries": { + "_doc": "Summary of journal entries created by this template", + "entry": { + "description": "Record expense and liability", + "debits": [{"account": "Expense Account", "amount": "{{amount}}"}], + "credits": [{"account": "Accounts Payable (2000)", "amount": "{{amount}}"}] + }, + "payment": { + "description": "Record payment from checking - decreases cash", + "debits": [{"account": "Accounts Payable (2000)", "amount": "{{amount}}"}], + "credits": [{"account": "Checking Account (1001)", "amount": "{{amount}}"}] + } + } +} diff --git a/templates/bill-paid-credit-card.json b/templates/bill-paid-credit-card.json new file mode 100644 index 0000000..7af22ab --- /dev/null +++ b/templates/bill-paid-credit-card.json @@ -0,0 +1,177 @@ +{ + "_meta": { + "name": "Bill Paid by Business Credit Card", + "description": "Record a vendor bill that was paid using the business credit card", + "scenario": "Invoice received and already paid via business credit card", + "accounts": { + "expense": "The expense account to debit (e.g., 36 for Software & Subscriptions)", + "credit_card": "Business Credit Card liability account (19)" + } + }, + "_variables": { + "vendor_id": "integer - Vendor record ID", + "bill_number": "string - Invoice/bill number from vendor", + "date_timestamp": "integer - Unix timestamp for bill and payment date", + "due_date_timestamp": "integer - Unix timestamp for due date (often same as date)", + "amount": "number - Total amount including tax", + "expense_account_id": "integer - Expense account ID to debit", + "line_description": "string - Description for bill line", + "vendor_name": "string - Vendor name for transaction descriptions", + "receipt_number": "string - Receipt/confirmation number from payment" + }, + "_sequence": [ + "1. Create Bill record → get bill_id", + "2. Create BillLine → links to bill_id", + "3. Create entry Transaction → get entry_txn_id", + "4. Create entry TransactionLines (Dr Expense, Cr AP)", + "5. Update Bill.EntryTransaction → link to entry_txn_id", + "6. Create payment Transaction → get payment_txn_id", + "7. Create payment TransactionLines (Dr AP, Cr Credit Card)", + "8. Create BillPayment record", + "9. Update Bill.Status → 'Paid'", + "10. Upload attachments (Invoice, Receipt)", + "11. Run audit checks" + ], + "records": { + "bill": { + "_doc": "Step 1: Create Bill header. Do NOT include Amount - it's a formula field.", + "_table": "Bills", + "_operation": "add_records", + "payload": { + "Vendor": "{{vendor_id}}", + "BillNumber": "{{bill_number}}", + "BillDate": "{{date_timestamp}}", + "DueDate": "{{due_date_timestamp}}", + "Status": "Open", + "Memo": "{{line_description}}" + } + }, + "bill_line": { + "_doc": "Step 2: Create BillLine. This populates the Bill.Amount formula.", + "_table": "BillLines", + "_operation": "add_records", + "_requires": ["bill_id"], + "payload": { + "Bill": "{{bill_id}}", + "Account": "{{expense_account_id}}", + "Description": "{{line_description}}", + "Amount": "{{amount}}" + } + }, + "entry_transaction": { + "_doc": "Step 3: Create entry transaction header.", + "_table": "Transactions", + "_operation": "add_records", + "payload": { + "Date": "{{date_timestamp}}", + "Description": "{{vendor_name}} - Invoice {{bill_number}}", + "Reference": "{{bill_number}}", + "Status": "Posted" + } + }, + "entry_transaction_lines": { + "_doc": "Step 4: Create entry transaction lines. Debit expense, credit AP.", + "_table": "TransactionLines", + "_operation": "add_records", + "_requires": ["entry_txn_id"], + "payload": [ + { + "Transaction": "{{entry_txn_id}}", + "Account": "{{expense_account_id}}", + "Debit": "{{amount}}", + "Credit": 0, + "Memo": "{{line_description}}" + }, + { + "Transaction": "{{entry_txn_id}}", + "Account": 4, + "Debit": 0, + "Credit": "{{amount}}", + "Memo": "Accounts Payable" + } + ] + }, + "link_bill_to_entry": { + "_doc": "Step 5: Link Bill to entry transaction.", + "_table": "Bills", + "_operation": "update_records", + "_requires": ["bill_id", "entry_txn_id"], + "payload": { + "id": "{{bill_id}}", + "fields": { + "EntryTransaction": "{{entry_txn_id}}" + } + } + }, + "payment_transaction": { + "_doc": "Step 6: Create payment transaction header.", + "_table": "Transactions", + "_operation": "add_records", + "payload": { + "Date": "{{date_timestamp}}", + "Description": "Payment to {{vendor_name}} - Business Credit Card", + "Reference": "{{receipt_number}}", + "Status": "Posted" + } + }, + "payment_transaction_lines": { + "_doc": "Step 7: Create payment transaction lines. Debit AP, credit Credit Card.", + "_table": "TransactionLines", + "_operation": "add_records", + "_requires": ["payment_txn_id"], + "payload": [ + { + "Transaction": "{{payment_txn_id}}", + "Account": 4, + "Debit": "{{amount}}", + "Credit": 0, + "Memo": "Accounts Payable" + }, + { + "Transaction": "{{payment_txn_id}}", + "Account": 19, + "Debit": 0, + "Credit": "{{amount}}", + "Memo": "Business Credit Card" + } + ] + }, + "bill_payment": { + "_doc": "Step 8: Create BillPayment linking bill to payment transaction.", + "_table": "BillPayments", + "_operation": "add_records", + "_requires": ["bill_id", "payment_txn_id"], + "payload": { + "Bill": "{{bill_id}}", + "Transaction": "{{payment_txn_id}}", + "Amount": "{{amount}}", + "PaymentDate": "{{date_timestamp}}" + } + }, + "mark_paid": { + "_doc": "Step 9: Update Bill status to Paid.", + "_table": "Bills", + "_operation": "update_records", + "_requires": ["bill_id"], + "payload": { + "id": "{{bill_id}}", + "fields": { + "Status": "Paid" + } + } + } + }, + "journal_entries": { + "_doc": "Summary of journal entries created by this template", + "entry": { + "description": "Record expense and liability", + "debits": [{"account": "Expense Account", "amount": "{{amount}}"}], + "credits": [{"account": "Accounts Payable (2000)", "amount": "{{amount}}"}] + }, + "payment": { + "description": "Record payment clearing AP and increasing credit card liability", + "debits": [{"account": "Accounts Payable (2000)", "amount": "{{amount}}"}], + "credits": [{"account": "Business Credit Card (2101)", "amount": "{{amount}}"}] + } + } +} diff --git a/templates/bill-paid-owner.json b/templates/bill-paid-owner.json new file mode 100644 index 0000000..2e0e36c --- /dev/null +++ b/templates/bill-paid-owner.json @@ -0,0 +1,177 @@ +{ + "_meta": { + "name": "Bill Paid by Owner (Reimbursement)", + "description": "Record a vendor bill that the owner paid personally (to be reimbursed later)", + "scenario": "Owner used personal funds to pay a business expense", + "accounts": { + "expense": "The expense account to debit", + "due_to_owner": "Due to Owner liability account (22) - credits increase amount owed to owner" + } + }, + "_variables": { + "vendor_id": "integer - Vendor record ID", + "bill_number": "string - Invoice/bill number from vendor", + "date_timestamp": "integer - Unix timestamp for bill and payment date", + "due_date_timestamp": "integer - Unix timestamp for due date", + "amount": "number - Total amount including tax", + "expense_account_id": "integer - Expense account ID to debit", + "line_description": "string - Description for bill line", + "vendor_name": "string - Vendor name for transaction descriptions", + "receipt_number": "string - Receipt/confirmation number (optional)" + }, + "_sequence": [ + "1. Create Bill record → get bill_id", + "2. Create BillLine → links to bill_id", + "3. Create entry Transaction → get entry_txn_id", + "4. Create entry TransactionLines (Dr Expense, Cr AP)", + "5. Update Bill.EntryTransaction → link to entry_txn_id", + "6. Create payment Transaction → get payment_txn_id", + "7. Create payment TransactionLines (Dr AP, Cr Due to Owner)", + "8. Create BillPayment record", + "9. Update Bill.Status → 'Paid'", + "10. Upload attachments (Invoice, Receipt)", + "11. Run audit checks" + ], + "records": { + "bill": { + "_doc": "Step 1: Create Bill header. Do NOT include Amount - it's a formula field.", + "_table": "Bills", + "_operation": "add_records", + "payload": { + "Vendor": "{{vendor_id}}", + "BillNumber": "{{bill_number}}", + "BillDate": "{{date_timestamp}}", + "DueDate": "{{due_date_timestamp}}", + "Status": "Open", + "Memo": "{{line_description}}" + } + }, + "bill_line": { + "_doc": "Step 2: Create BillLine. This populates the Bill.Amount formula.", + "_table": "BillLines", + "_operation": "add_records", + "_requires": ["bill_id"], + "payload": { + "Bill": "{{bill_id}}", + "Account": "{{expense_account_id}}", + "Description": "{{line_description}}", + "Amount": "{{amount}}" + } + }, + "entry_transaction": { + "_doc": "Step 3: Create entry transaction header.", + "_table": "Transactions", + "_operation": "add_records", + "payload": { + "Date": "{{date_timestamp}}", + "Description": "{{vendor_name}} - Invoice {{bill_number}}", + "Reference": "{{bill_number}}", + "Status": "Posted" + } + }, + "entry_transaction_lines": { + "_doc": "Step 4: Create entry transaction lines. Debit expense, credit AP.", + "_table": "TransactionLines", + "_operation": "add_records", + "_requires": ["entry_txn_id"], + "payload": [ + { + "Transaction": "{{entry_txn_id}}", + "Account": "{{expense_account_id}}", + "Debit": "{{amount}}", + "Credit": 0, + "Memo": "{{line_description}}" + }, + { + "Transaction": "{{entry_txn_id}}", + "Account": 4, + "Debit": 0, + "Credit": "{{amount}}", + "Memo": "Accounts Payable" + } + ] + }, + "link_bill_to_entry": { + "_doc": "Step 5: Link Bill to entry transaction.", + "_table": "Bills", + "_operation": "update_records", + "_requires": ["bill_id", "entry_txn_id"], + "payload": { + "id": "{{bill_id}}", + "fields": { + "EntryTransaction": "{{entry_txn_id}}" + } + } + }, + "payment_transaction": { + "_doc": "Step 6: Create payment transaction header.", + "_table": "Transactions", + "_operation": "add_records", + "payload": { + "Date": "{{date_timestamp}}", + "Description": "Owner payment - {{vendor_name}}", + "Reference": "{{receipt_number}}", + "Status": "Posted" + } + }, + "payment_transaction_lines": { + "_doc": "Step 7: Create payment transaction lines. Debit AP, credit Due to Owner.", + "_table": "TransactionLines", + "_operation": "add_records", + "_requires": ["payment_txn_id"], + "payload": [ + { + "Transaction": "{{payment_txn_id}}", + "Account": 4, + "Debit": "{{amount}}", + "Credit": 0, + "Memo": "Accounts Payable" + }, + { + "Transaction": "{{payment_txn_id}}", + "Account": 22, + "Debit": 0, + "Credit": "{{amount}}", + "Memo": "Due to Owner" + } + ] + }, + "bill_payment": { + "_doc": "Step 8: Create BillPayment linking bill to payment transaction.", + "_table": "BillPayments", + "_operation": "add_records", + "_requires": ["bill_id", "payment_txn_id"], + "payload": { + "Bill": "{{bill_id}}", + "Transaction": "{{payment_txn_id}}", + "Amount": "{{amount}}", + "PaymentDate": "{{date_timestamp}}" + } + }, + "mark_paid": { + "_doc": "Step 9: Update Bill status to Paid.", + "_table": "Bills", + "_operation": "update_records", + "_requires": ["bill_id"], + "payload": { + "id": "{{bill_id}}", + "fields": { + "Status": "Paid" + } + } + } + }, + "journal_entries": { + "_doc": "Summary of journal entries created by this template", + "entry": { + "description": "Record expense and liability", + "debits": [{"account": "Expense Account", "amount": "{{amount}}"}], + "credits": [{"account": "Accounts Payable (2000)", "amount": "{{amount}}"}] + }, + "payment": { + "description": "Record owner payment - increases amount business owes to owner", + "debits": [{"account": "Accounts Payable (2000)", "amount": "{{amount}}"}], + "credits": [{"account": "Due to Owner (2203)", "amount": "{{amount}}"}] + } + } +} diff --git a/templates/bill-unpaid.json b/templates/bill-unpaid.json new file mode 100644 index 0000000..e3ed504 --- /dev/null +++ b/templates/bill-unpaid.json @@ -0,0 +1,115 @@ +{ + "_meta": { + "name": "Unpaid Bill (Accounts Payable)", + "description": "Record a vendor bill that has not yet been paid", + "scenario": "Invoice received but payment will be made later", + "accounts": { + "expense": "The expense account to debit", + "accounts_payable": "Accounts Payable liability (4) - credits increase amount owed" + } + }, + "_variables": { + "vendor_id": "integer - Vendor record ID", + "bill_number": "string - Invoice/bill number from vendor", + "date_timestamp": "integer - Unix timestamp for bill date", + "due_date_timestamp": "integer - Unix timestamp for due date", + "amount": "number - Total amount including tax", + "expense_account_id": "integer - Expense account ID to debit", + "line_description": "string - Description for bill line", + "vendor_name": "string - Vendor name for transaction descriptions" + }, + "_sequence": [ + "1. Create Bill record → get bill_id", + "2. Create BillLine → links to bill_id", + "3. Create entry Transaction → get entry_txn_id", + "4. Create entry TransactionLines (Dr Expense, Cr AP)", + "5. Update Bill.EntryTransaction → link to entry_txn_id", + "6. Upload Invoice attachment", + "7. Run audit checks", + "NOTE: Bill remains in 'Open' status until payment is recorded" + ], + "records": { + "bill": { + "_doc": "Step 1: Create Bill header. Do NOT include Amount - it's a formula field.", + "_table": "Bills", + "_operation": "add_records", + "payload": { + "Vendor": "{{vendor_id}}", + "BillNumber": "{{bill_number}}", + "BillDate": "{{date_timestamp}}", + "DueDate": "{{due_date_timestamp}}", + "Status": "Open", + "Memo": "{{line_description}}" + } + }, + "bill_line": { + "_doc": "Step 2: Create BillLine. This populates the Bill.Amount formula.", + "_table": "BillLines", + "_operation": "add_records", + "_requires": ["bill_id"], + "payload": { + "Bill": "{{bill_id}}", + "Account": "{{expense_account_id}}", + "Description": "{{line_description}}", + "Amount": "{{amount}}" + } + }, + "entry_transaction": { + "_doc": "Step 3: Create entry transaction header.", + "_table": "Transactions", + "_operation": "add_records", + "payload": { + "Date": "{{date_timestamp}}", + "Description": "{{vendor_name}} - Invoice {{bill_number}}", + "Reference": "{{bill_number}}", + "Status": "Posted" + } + }, + "entry_transaction_lines": { + "_doc": "Step 4: Create entry transaction lines. Debit expense, credit AP.", + "_table": "TransactionLines", + "_operation": "add_records", + "_requires": ["entry_txn_id"], + "payload": [ + { + "Transaction": "{{entry_txn_id}}", + "Account": "{{expense_account_id}}", + "Debit": "{{amount}}", + "Credit": 0, + "Memo": "{{line_description}}" + }, + { + "Transaction": "{{entry_txn_id}}", + "Account": 4, + "Debit": 0, + "Credit": "{{amount}}", + "Memo": "Accounts Payable" + } + ] + }, + "link_bill_to_entry": { + "_doc": "Step 5: Link Bill to entry transaction.", + "_table": "Bills", + "_operation": "update_records", + "_requires": ["bill_id", "entry_txn_id"], + "payload": { + "id": "{{bill_id}}", + "fields": { + "EntryTransaction": "{{entry_txn_id}}" + } + } + } + }, + "journal_entries": { + "_doc": "Summary of journal entries created by this template", + "entry": { + "description": "Record expense and accounts payable liability", + "debits": [{"account": "Expense Account", "amount": "{{amount}}"}], + "credits": [{"account": "Accounts Payable (2000)", "amount": "{{amount}}"}] + } + }, + "_follow_up": { + "description": "When payment is made, use pay-existing-bill.json template", + "required_data": ["bill_id", "payment_date", "payment_method", "payment_reference"] + } +} diff --git a/templates/direct-expense.json b/templates/direct-expense.json new file mode 100644 index 0000000..dc9fd9a --- /dev/null +++ b/templates/direct-expense.json @@ -0,0 +1,92 @@ +{ + "_meta": { + "name": "Direct Expense (No Bill)", + "description": "Record an expense directly without creating a bill record", + "scenario": "Bank fees, minor expenses, or transactions without vendor invoices", + "when_to_use": [ + "Bank service fees", + "ATM fees", + "Minor cash purchases without receipts", + "Automatic deductions with no invoice" + ], + "when_not_to_use": [ + "Vendor invoices - use bill templates instead", + "Expenses needing AP tracking", + "Purchases requiring receipt documentation" + ] + }, + "_variables": { + "date_timestamp": "integer - Unix timestamp for transaction date", + "amount": "number - Transaction amount", + "expense_account_id": "integer - Expense account ID to debit", + "payment_account_id": "integer - Payment source account ID (14=Checking, 19=Credit Card)", + "description": "string - Transaction description", + "reference": "string - Reference number (statement line, confirmation, etc.)", + "memo": "string - Additional notes (optional)" + }, + "_sequence": [ + "1. Create Transaction header → get txn_id", + "2. Create TransactionLines (Dr Expense, Cr Payment Account)", + "3. Run audit check (verify IsBalanced = true)" + ], + "records": { + "transaction": { + "_doc": "Step 1: Create transaction header.", + "_table": "Transactions", + "_operation": "add_records", + "payload": { + "Date": "{{date_timestamp}}", + "Description": "{{description}}", + "Reference": "{{reference}}", + "Status": "Cleared", + "Memo": "{{memo}}" + } + }, + "transaction_lines": { + "_doc": "Step 2: Create transaction lines. Debit expense, credit payment account.", + "_table": "TransactionLines", + "_operation": "add_records", + "_requires": ["txn_id"], + "payload": [ + { + "Transaction": "{{txn_id}}", + "Account": "{{expense_account_id}}", + "Debit": "{{amount}}", + "Credit": 0, + "Memo": "{{description}}" + }, + { + "Transaction": "{{txn_id}}", + "Account": "{{payment_account_id}}", + "Debit": 0, + "Credit": "{{amount}}", + "Memo": "{{description}}" + } + ] + } + }, + "journal_entries": { + "_doc": "Summary of journal entry created by this template", + "entry": { + "description": "Record direct expense", + "debits": [{"account": "Expense Account", "amount": "{{amount}}"}], + "credits": [{"account": "Payment Account (Checking/Credit Card)", "amount": "{{amount}}"}] + } + }, + "examples": { + "bank_fee": { + "description": "Monthly bank service fee", + "expense_account_id": 30, + "payment_account_id": 14, + "expense_account_name": "Bank & Merchant Fees (5020)", + "payment_account_name": "Checking Account (1001)" + }, + "credit_card_fee": { + "description": "Credit card annual fee", + "expense_account_id": 30, + "payment_account_id": 19, + "expense_account_name": "Bank & Merchant Fees (5020)", + "payment_account_name": "Business Credit Card (2101)" + } + } +} diff --git a/templates/pay-existing-bill.json b/templates/pay-existing-bill.json new file mode 100644 index 0000000..24fc362 --- /dev/null +++ b/templates/pay-existing-bill.json @@ -0,0 +1,119 @@ +{ + "_meta": { + "name": "Pay Existing Bill", + "description": "Record payment for a bill that was previously entered as unpaid", + "scenario": "Bill was recorded earlier with Status='Open', now recording the payment", + "prerequisite": "Bill must already exist with EntryTransaction linked" + }, + "_variables": { + "bill_id": "integer - Existing Bill record ID", + "payment_date_timestamp": "integer - Unix timestamp for payment date", + "amount": "number - Payment amount (usually matches Bill.AmountDue)", + "payment_account_id": "integer - Payment source: 14=Checking, 19=Credit Card, 22=Due to Owner", + "payment_account_name": "string - Account name for transaction memo", + "payment_reference": "string - Check number, confirmation code, etc.", + "vendor_name": "string - Vendor name for transaction description" + }, + "_sequence": [ + "1. Verify bill exists and has AmountDue > 0", + "2. Create payment Transaction → get payment_txn_id", + "3. Create payment TransactionLines (Dr AP, Cr Payment Account)", + "4. Create BillPayment record", + "5. Update Bill.Status → 'Paid' (if fully paid)", + "6. Upload Receipt attachment if available", + "7. Run audit checks" + ], + "_pre_check": { + "_doc": "Verify bill status before proceeding", + "query": "SELECT id, BillNumber, Amount, AmountDue, Status FROM Bills WHERE id = {{bill_id}}", + "expected": "AmountDue > 0 and Status = 'Open'" + }, + "records": { + "payment_transaction": { + "_doc": "Step 2: Create payment transaction header.", + "_table": "Transactions", + "_operation": "add_records", + "payload": { + "Date": "{{payment_date_timestamp}}", + "Description": "Payment to {{vendor_name}}", + "Reference": "{{payment_reference}}", + "Status": "Cleared" + } + }, + "payment_transaction_lines": { + "_doc": "Step 3: Create payment transaction lines. Debit AP, credit payment account.", + "_table": "TransactionLines", + "_operation": "add_records", + "_requires": ["payment_txn_id"], + "payload": [ + { + "Transaction": "{{payment_txn_id}}", + "Account": 4, + "Debit": "{{amount}}", + "Credit": 0, + "Memo": "Accounts Payable" + }, + { + "Transaction": "{{payment_txn_id}}", + "Account": "{{payment_account_id}}", + "Debit": 0, + "Credit": "{{amount}}", + "Memo": "{{payment_account_name}}" + } + ] + }, + "bill_payment": { + "_doc": "Step 4: Create BillPayment linking bill to payment transaction.", + "_table": "BillPayments", + "_operation": "add_records", + "_requires": ["bill_id", "payment_txn_id"], + "payload": { + "Bill": "{{bill_id}}", + "Transaction": "{{payment_txn_id}}", + "Amount": "{{amount}}", + "PaymentDate": "{{payment_date_timestamp}}" + } + }, + "mark_paid": { + "_doc": "Step 5: Update Bill status to Paid (only if AmountDue becomes 0).", + "_table": "Bills", + "_operation": "update_records", + "_requires": ["bill_id"], + "_condition": "Only if Bill.AmountDue = 0 after payment", + "payload": { + "id": "{{bill_id}}", + "fields": { + "Status": "Paid" + } + } + } + }, + "journal_entries": { + "_doc": "Journal entry created by this template", + "payment": { + "description": "Record payment clearing accounts payable", + "debits": [{"account": "Accounts Payable (2000)", "amount": "{{amount}}"}], + "credits": [{"account": "Payment Account", "amount": "{{amount}}"}] + } + }, + "payment_account_options": { + "checking": { + "id": 14, + "code": "1001", + "name": "Checking Account", + "type": "Asset" + }, + "credit_card": { + "id": 19, + "code": "2101", + "name": "Business Credit Card", + "type": "Liability" + }, + "owner_paid": { + "id": 22, + "code": "2203", + "name": "Due to Owner", + "type": "Liability" + } + } +}