skills/egadams/receipt-scanning-tools/SKILL.md
This skill helps you work with the receipt scanning tools in the nonprofit_finance_db project. It includes manual entry tools, automated OCR scanning, and database integration for tracking receipts...
npx skillsauth add aiskillstore/marketplace receipt-scanning-toolsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill helps you work with the receipt scanning tools in the nonprofit_finance_db project. It includes manual entry tools, automated OCR scanning, and database integration for tracking receipts and expenses.
# Virtual environment location (IMPORTANT!)
VENV_PATH=/home/adamsl/planner/.venv
# Always activate before running Python scripts:
source /home/adamsl/planner/.venv/bin/activate
PROJECT_ROOT=/home/adamsl/planner/nonprofit_finance_db
TOOLS_DIR=/home/adamsl/planner/nonprofit_finance_db/receipt_scanning_tools
Receipt Tools:
receipt_scanning_tools/receipt_tools_menu.py - Main menu for all receipt toolsreceipt_scanning_tools/manual_entry.py - Manual receipt entry CLI toolreceipt_scanning_tools/delete_expenses_by_date.py - Delete expenses by date toolBackend Services:
app/services/receipt_parser.py - Receipt parsing serviceapp/services/receipt_engine.py - AI-powered OCR engineapp/api/receipt_endpoints.py - REST API endpointsapp/models/receipt_models.py - Data modelsapp/db/pool.py - Database connection pool-- Actual schema (no category_path column!)
CREATE TABLE categories (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
parent_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (parent_id) REFERENCES categories(id)
);
-- To get full category path, use recursive query:
WITH RECURSIVE category_hierarchy AS (
SELECT id, name, parent_id, name as full_path
FROM categories
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.name, c.parent_id,
CONCAT(ch.full_path, ' > ', c.name) as full_path
FROM categories c
INNER JOIN category_hierarchy ch ON c.parent_id = ch.id
)
SELECT * FROM category_hierarchy ORDER BY full_path;
CREATE TABLE merchants (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL UNIQUE,
category VARCHAR(100),
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_name (name),
INDEX idx_category (category)
);
-- Categories for church non-profit:
-- Gifts and Love Offerings: Guiding Light, Mel Trotter Ministries,
-- Salvation Army, Samaritan Purse, Jews for Jesus,
-- Intercessors for America, Segals in Israel,
-- Chosen People, Columbia Orphanage, Right to Life,
-- Johnsons in Dominican Republic, Jewish Voice
-- Ministers and Workers: EG Adams, Snowplow Person
-- Presents for ROL Friends and Members: James Abney, Cliff Baker, Annie Baker,
-- Karen Cook, Richard Meninga, Karen Roark,
-- Hannah Schneider, Rebecca Esposito,
-- Karen Vander Vliet, Mark Vander Vliet,
-- Alexander Vander Vliet, John Roark,
-- Joshua McKay, Eddie Hoekstra, Ian Gonzalez
-- Food & Supplies: Meijer, Gordon Foods, Walmart, Target, Costco,
-- Sams Club, Kroger, Aldi, Family Fare, Spartan Stores
CREATE TABLE expenses (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
org_id BIGINT UNSIGNED NOT NULL,
expense_date DATE NOT NULL,
amount DECIMAL(12,2) NOT NULL,
category_id BIGINT UNSIGNED,
merchant_id BIGINT UNSIGNED, -- Links to merchants table
method ENUM('CASH','CARD','BANK','OTHER'),
description VARCHAR(255),
receipt_url VARCHAR(500),
paid_by_contact_id BIGINT UNSIGNED,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (org_id) REFERENCES organizations(id),
FOREIGN KEY (category_id) REFERENCES categories(id),
FOREIGN KEY (merchant_id) REFERENCES merchants(id)
);
CREATE TABLE receipt_metadata (
id INT PRIMARY KEY AUTO_INCREMENT,
expense_id INT NOT NULL,
model_name VARCHAR(100),
confidence_score DECIMAL(3,2),
raw_response TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (expense_id) REFERENCES expenses(id)
);
# Connect to database (with venv activated)
source /home/adamsl/planner/.venv/bin/activate
cd /home/adamsl/planner/nonprofit_finance_db
# Check categories structure
python3 -c "
from app.db import get_connection
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute('DESCRIBE categories')
for row in cursor.fetchall():
print(row)
"
# View categories with hierarchy
python3 -c "
from app.db import get_connection
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute('''
WITH RECURSIVE category_hierarchy AS (
SELECT id, name, parent_id, name as full_path, 0 as level
FROM categories
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.name, c.parent_id,
CONCAT(ch.full_path, \" > \", c.name) as full_path,
ch.level + 1
FROM categories c
INNER JOIN category_hierarchy ch ON c.parent_id = ch.id
)
SELECT id, name, full_path FROM category_hierarchy ORDER BY full_path
''')
for row in cursor.fetchall():
print(f'{row[0]:3d} | {row[1]:30s} | {row[2]}')
"
# Always activate venv first!
source /home/adamsl/planner/.venv/bin/activate
cd /home/adamsl/planner/nonprofit_finance_db
# Run main receipt tools menu (RECOMMENDED)
python3 receipt_scanning_tools/receipt_tools_menu.py
# Or run individual tools directly:
python3 receipt_scanning_tools/manual_entry.py
python3 receipt_scanning_tools/delete_expenses_by_date.py
# Other services:
python3 api_server.py # API server
python3 scripts/view_transactions.py # Transaction viewer
Merchant Selection Features:
When you encounter column errors like "Unknown column 'category_path'":
Check actual table schema:
from app.db import get_connection
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute('DESCRIBE categories')
print(cursor.fetchall())
Update query to use actual columns
Use recursive CTE for hierarchical path if needed
receipt_scanning_tools/from app.db import get_connectionmanual_entry.pychmod +x receipt_scanning_tools/your_tool.py# Environment variables in .env file
DB_HOST=127.0.0.1
DB_PORT=3306
NON_PROFIT_USER=adamsl
NON_PROFIT_PASSWORD=<password>
NON_PROFIT_DB_NAME=nonprofit_finance
# For AI-powered OCR
GEMINI_API_KEY=<your_key>
from app.db import get_connection
def get_merchants():
"""Fetch merchants from database"""
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute("""
SELECT id, name, category
FROM merchants
ORDER BY name
""")
return cursor.fetchall()
from app.db import get_connection
def add_merchant(name, category="Food & Supplies"):
"""Add a new merchant to the database"""
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute("""
INSERT INTO merchants (name, category)
VALUES (%s, %s)
""", (name, category))
conn.commit()
return cursor.lastrowid
from app.db import get_connection
def get_categories_with_path():
"""Fetch categories with full hierarchical path"""
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute("""
WITH RECURSIVE category_hierarchy AS (
SELECT id, name, parent_id, name as full_path
FROM categories
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.name, c.parent_id,
CONCAT(ch.full_path, ' > ', c.name) as full_path
FROM categories c
INNER JOIN category_hierarchy ch ON c.parent_id = ch.id
)
SELECT id, name, full_path
FROM category_hierarchy
ORDER BY full_path
""")
return cursor.fetchall()
from app.db import get_connection
from datetime import datetime
def save_expense(org_id, date, amount, category_id, description):
"""Save expense to database"""
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute("""
INSERT INTO expenses (
org_id, expense_date, amount, category_id,
payment_method, description, created_at
)
VALUES (%s, %s, %s, %s, %s, %s, %s)
""", (
org_id,
date,
amount,
category_id,
"CASH",
description,
datetime.now()
))
conn.commit()
return cursor.lastrowid
from rich.console import Console
from rich.table import Table
from rich.prompt import Prompt, FloatPrompt, Confirm
from rich import box
console = Console()
# Display table
table = Table(box=box.ROUNDED, show_header=True)
table.add_column("ID", style="cyan")
table.add_column("Name", style="yellow")
table.add_row("1", "Groceries")
console.print(table)
# Get user input
amount = FloatPrompt.ask("Enter amount")
confirm = Confirm.ask("Save this?")
Cause: Query assumes column that doesn't exist in schema
Fix: Use recursive CTE to build hierarchical path, or just use name column
Cause: Virtual environment not activated
Fix: source /home/adamsl/planner/.venv/bin/activate
Cause: Database not initialized or connection failed Fix:
.envpython3 scripts/init_db.pyapp.* modulesCause: Wrong working directory or Python path Fix:
# Add to top of script
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
source /home/adamsl/planner/.venv/bin/activate
cd /home/adamsl/planner/nonprofit_finance_db
python3 -c "from app.db import get_connection; print('✓ Database connection OK')"
python3 -c "
from app.db import get_connection
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute('SELECT id, expense_date, amount, description FROM expenses ORDER BY id DESC LIMIT 5')
for row in cursor.fetchall():
print(row)
"
python3 -c "
from app.db import get_connection
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute('SELECT COUNT(*) FROM categories')
print(f'Total categories: {cursor.fetchone()[0]}')
"
development
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.