expense-processing
Automates expense receipt capture, validation, and Odoo posting
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
Expense Processing Skill
Overview
This skill handles the complete expense management workflow from receipt capture through reimbursement, including OCR extraction, policy validation, and Odoo integration.
Capabilities
- Receipt image OCR via PaddleOCR
- AI-powered data extraction
- Policy compliance validation
- Automatic expense categorization
- Odoo hr.expense creation
- Approval workflow routing
- Reimbursement tracking
Workflow
Step 1: Receipt Capture
Input Methods:
- Mobile app upload
- Email forwarding (receipts@insightpulseai.net)
- Telegram bot
- Manual upload via Odoo
Supported Formats:
- Images: JPG, PNG, HEIC
- Documents: PDF (first page)
- Max size: 10MB
Step 2: OCR Extraction
PaddleOCR Endpoint: https://ocr.insightpulseai.net/api/ocr/receipt
Request:
{
"image": "<base64_encoded_image>",
"language": "en"
}
Response:
{
"text": "JOLLIBEE STORE 1234\n...",
"confidence": 0.95,
"regions": [...]
}
Step 3: AI Data Structuring
Claude Prompt:
Extract receipt data and return JSON:
- merchant_name: string
- merchant_tin: string (if visible)
- receipt_date: YYYY-MM-DD
- receipt_number: string
- subtotal: number
- vat_amount: number
- total_amount: number
- payment_method: cash|credit_card|gcash|paymaya|other
- expense_category: meals|transportation|supplies|communication|accommodation|other
- description: brief description
Step 4: Policy Validation
Approval Thresholds (PHP):
| Amount | Approval | Route |
|---|---|---|
| < 5,000 | Self | Auto-approve |
| 5,000 - 25,000 | Manager | Notify manager |
| 25,000 - 100,000 | Dept Head + Finance | Escalate |
| > 100,000 | CFO | Escalate + alert |
Policy Rules:
rules = [
Rule("amount_limit", lambda e: e.amount <= 100000, "Amount exceeds maximum"),
Rule("valid_category", lambda e: e.category in ALLOWED_CATEGORIES, "Invalid category"),
Rule("has_receipt", lambda e: e.receipt_image is not None, "Receipt required"),
Rule("or_required", lambda e: e.amount < 1000 or e.has_official_receipt, "OR required > 1000"),
Rule("not_weekend", lambda e: not e.is_personal, "Personal expenses not allowed"),
]
Step 5: Odoo Integration
hr.expense Creation:
{
"name": "Jollibee - Client Meeting Lunch",
"product_id": 1, // Meals category
"unit_amount": 1250.00,
"quantity": 1,
"date": "2026-01-06",
"employee_id": 77, // RIM
"payment_mode": "own_account",
"reference": "OR-12345678",
"description": "Client meeting with ACME Foods project team"
}
Category Mapping:
| Category | Odoo Product ID | Account |
|---|---|---|
| meals | 1 | 6210 - Meals & Entertainment |
| transportation | 2 | 6220 - Transportation |
| supplies | 3 | 6230 - Office Supplies |
| communication | 4 | 6240 - Communication |
| accommodation | 5 | 6250 - Travel & Lodging |
| other | 6 | 6290 - Miscellaneous |
Step 6: Approval Workflow
Odoo States:
draft → reported → submitted → approved → posted → done
↘ refused ↙
Notifications:
- On submit: Notify approver via Mattermost
- On approve/refuse: Notify employee
- On post: Update reimbursement queue
n8n Workflow Integration
The expense_receipt_capture.json workflow:
- Webhook receives image
- PaddleOCR extracts text
- Claude structures data
-
Policy check (IF node)
- Pass: Create expense in Odoo
- Fail: Alert to #finance-general
- Respond with result
Mattermost Notifications
Policy Violation Alert:
#### :warning: Policy Violation Alert
| Field | Value |
|:--|:--|
| **Amount** | PHP 7,500 |
| **Threshold** | PHP 5,000 |
| **Merchant** | Restaurant ABC |
| **Category** | meals |
**Action Required:** Manager approval needed
Expense Created:
#### :receipt: Expense Submitted
| Field | Value |
|:--|:--|
| **Employee** | Rey Meran (RIM) |
| **Amount** | PHP 1,250 |
| **Category** | Meals |
| **Status** | Pending Approval |
Receipt Requirements
Valid Receipt Elements
- Date of purchase
- Merchant/vendor name
- Itemized list
- Total amount
- OR number (for amounts > ₱1,000)
- VAT details (if applicable)
Common Issues
| Issue | Resolution |
|---|---|
| Faded receipt | Re-scan or request duplicate |
| Missing OR | Request from vendor |
| Foreign currency | Include exchange rate |
| Handwritten | Attach explanation |
Reimbursement Schedule
- Cutoff 1: Submit by 10th → Reimbursed on 15th
- Cutoff 2: Submit by 25th → Reimbursed on 30th
Error Handling
errors = {
"OCR_FAILED": "Could not extract text. Please re-upload clearer image.",
"INVALID_DATE": "Receipt date could not be parsed. Please enter manually.",
"CATEGORY_UNKNOWN": "Could not determine expense category. Please select.",
"EMPLOYEE_NOT_FOUND": "Employee not found in system. Contact HR.",
"DUPLICATE_RECEIPT": "This receipt may already exist. Please verify.",
}
Commands
| Command | Action |
|---|---|
/expense submit |
Start expense submission |
/expense status [id] |
Check expense status |
/expense history |
View recent expenses |
/expense policy |
Show expense policy |
Related Skills
Changelog
- v1.0.0 (2026-01-06): Initial release
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-28
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!