Skip to content

Expense Category Documentation

Overview

The Expense Category model (expense.categ) provides a way to categorize and organize expense records in the system. Categories help with reporting, analysis, and budgeting by grouping similar types of expenses together.


Model Information

Model Name: expense.categ Display Name: Expense Category Key Fields: None (no unique constraint defined)

Features

  • ❌ Audit logging enabled (_audit_log)
  • ❌ Multi-company support (company_id)
  • ❌ Full-text content search (_content_search)
  • ✅ Simple lookup model for categorization

Key Fields Reference

All Fields

Field Type Required Description
name Char Category name displayed in selection lists
description Text Detailed description of what expenses belong to this category

Default Ordering

Records are ordered by name alphabetically:

_order = "name"

API Methods

1. Create Category

Method: create(vals, context)

Creates a new expense category.

Parameters:

vals = {
    "name": "Travel",              # Required: Category name
    "description": "Travel-related expenses including transport and accommodation"  # Optional
}

Returns: int - New record ID

Example:

# Create a new expense category
categ_id = get_model("expense.categ").create({
    "name": "Office Supplies",
    "description": "Stationery, paper, pens, and other office consumables"
})


2. Search Categories

Method: search(condition, context)

Search for expense categories.

Example:

# Find all categories
all_categs = get_model("expense.categ").search([])

# Find category by name
categ_ids = get_model("expense.categ").search([["name", "=", "Travel"]])

# Find categories containing 'Office'
categ_ids = get_model("expense.categ").search([["name", "ilike", "%Office%"]])


3. Browse Categories

Method: browse(ids, context)

Retrieve category records for reading.

Example:

# Get category details
categs = get_model("expense.categ").browse(categ_ids)
for categ in categs:
    print(f"Category: {categ.name}")
    print(f"Description: {categ.description}")


4. Update Category

Method: write(ids, vals, context)

Update existing category records.

Example:

# Update category description
get_model("expense.categ").write([categ_id], {
    "description": "Updated description for the category"
})


5. Delete Category

Method: delete(ids, context)

Delete expense categories.

Example:

# Delete a category (ensure no expenses reference it)
get_model("expense.categ").delete([categ_id])


Model Relationship Description
expense Many2One (categ_id) Individual expense records linked to this category

Common Use Cases

Use Case 1: Set Up Standard Expense Categories

# Create standard expense categories for a company
categories = [
    {"name": "Travel", "description": "Transportation, flights, accommodation"},
    {"name": "Meals", "description": "Business meals and entertainment"},
    {"name": "Office Supplies", "description": "Stationery and office consumables"},
    {"name": "Software", "description": "Software licenses and subscriptions"},
    {"name": "Training", "description": "Professional development and courses"},
    {"name": "Equipment", "description": "Hardware and equipment purchases"},
    {"name": "Communication", "description": "Phone, internet, and communication costs"},
    {"name": "Miscellaneous", "description": "Other uncategorized expenses"},
]

for cat in categories:
    get_model("expense.categ").create(cat)

Use Case 2: List All Categories for Dropdown

# Get all categories for a selection field
categ_ids = get_model("expense.categ").search([])
categs = get_model("expense.categ").search_browse([])

options = []
for categ in categs:
    options.append({
        "id": categ.id,
        "name": categ.name,
        "description": categ.description
    })

Use Case 3: Get Expenses by Category

# Find all expenses in a specific category
categ_id = get_model("expense.categ").search([["name", "=", "Travel"]])[0]
expense_ids = get_model("expense").search([["categ_id", "=", categ_id]])
expenses = get_model("expense").browse(expense_ids)

total = sum(exp.amount for exp in expenses)
print(f"Total Travel Expenses: {total}")

Best Practices

1. Use Descriptive Names

# Good: Clear and specific
get_model("expense.categ").create({
    "name": "Client Entertainment",
    "description": "Meals and activities with clients for business development"
})

# Bad: Vague and ambiguous
get_model("expense.categ").create({
    "name": "Other"
})

2. Maintain Consistent Naming Conventions

  • Use Title Case for category names
  • Keep names concise but descriptive
  • Add detailed descriptions for clarity

3. Check for Existing Categories Before Creating

# Check if category exists before creating
name = "Travel"
existing = get_model("expense.categ").search([["name", "=", name]])
if not existing:
    get_model("expense.categ").create({"name": name})

Troubleshooting

"Category name is required"

Cause: Attempting to create a category without a name Solution: Always provide the name field when creating a category

"Cannot delete category with linked expenses"

Cause: Trying to delete a category that has expenses referencing it Solution: Either reassign expenses to another category or delete the expenses first

"Duplicate category name"

Cause: Creating a category with a name that already exists (if custom validation added) Solution: Use a unique name or update the existing category


Testing Examples

Unit Test: Create and Retrieve Category

def test_create_expense_category():
    # Create category
    categ_id = get_model("expense.categ").create({
        "name": "Test Category",
        "description": "Category for testing"
    })

    # Verify creation
    assert categ_id is not None

    # Retrieve and verify
    categ = get_model("expense.categ").browse([categ_id])[0]
    assert categ.name == "Test Category"
    assert categ.description == "Category for testing"

    # Cleanup
    get_model("expense.categ").delete([categ_id])

Security Considerations

Permission Model

  • Read access typically granted to all users who can create expenses
  • Write/Delete access typically restricted to accounting or admin users

Data Access

  • Categories are shared across the system (no multi-company restriction)
  • Changes to categories affect all users

Version History

Last Updated: December 2024 Model Version: expense_categ.py Framework: Netforce


Additional Resources

  • Expense Documentation: expense
  • Expense Claim Documentation: expense.claim
  • Account Expense Documentation: account.expense

This documentation is generated for developer onboarding and reference purposes.