AgentSkillsCN

expense-processing

自动完成费用收据的采集、验证与Odoo记账。

SKILL.md
--- frontmatter
name: expense-processing
description: Automates expense receipt capture, validation, and Odoo posting
version: 1.0.0
author: InsightPulse AI
tags: [expense, receipt, ocr, reimbursement, hr]

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:

Supported Formats:

  • Images: JPG, PNG, HEIC
  • Documents: PDF (first page)
  • Max size: 10MB

Step 2: OCR Extraction

PaddleOCR Endpoint: https://ocr.insightpulseai.com/api/ocr/receipt

Request:

json
{
  "image": "<base64_encoded_image>",
  "language": "en"
}

Response:

json
{
  "text": "JOLLIBEE STORE 1234\n...",
  "confidence": 0.95,
  "regions": [...]
}

Step 3: AI Data Structuring

Claude Prompt:

code
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):

AmountApprovalRoute
< 5,000SelfAuto-approve
5,000 - 25,000ManagerNotify manager
25,000 - 100,000Dept Head + FinanceEscalate
> 100,000CFOEscalate + alert

Policy Rules:

python
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:

json
{
  "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:

CategoryOdoo Product IDAccount
meals16210 - Meals & Entertainment
transportation26220 - Transportation
supplies36230 - Office Supplies
communication46240 - Communication
accommodation56250 - Travel & Lodging
other66290 - Miscellaneous

Step 6: Approval Workflow

Odoo States:

code
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:

  1. Webhook receives image
  2. PaddleOCR extracts text
  3. Claude structures data
  4. Policy check (IF node)
    • Pass: Create expense in Odoo
    • Fail: Alert to #finance-general
  5. Respond with result

Mattermost Notifications

Policy Violation Alert:

markdown
#### :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:

markdown
#### :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

IssueResolution
Faded receiptRe-scan or request duplicate
Missing ORRequest from vendor
Foreign currencyInclude exchange rate
HandwrittenAttach explanation

Reimbursement Schedule

  • Cutoff 1: Submit by 10th → Reimbursed on 15th
  • Cutoff 2: Submit by 25th → Reimbursed on 30th

Error Handling

python
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

CommandAction
/expense submitStart expense submission
/expense status [id]Check expense status
/expense historyView recent expenses
/expense policyShow expense policy

Related Skills

Changelog

  • v1.0.0 (2026-01-06): Initial release