Account Model (account.account)¶
Overview¶
The Account model (account.account) represents the chart of accounts—the complete listing of all accounts in the general ledger. Each account is a container for journal entry lines and tracks specific types of assets, liabilities, equity, revenue, or expenses. Accounts form a hierarchical structure with parent accounts providing grouping and rollup capabilities. This model is fundamental to the accounting system, as every financial transaction ultimately posts to accounts, and all financial reports derive from account balances.
Model Information¶
Model Name: account.account
Display Name: Account
Key Fields: code, company_id
Source File: netforce_account/models/account_account.py
Features¶
- ✅ Audit logging enabled (
_audit_log = True) - ✅ Multi-company support (
_multi_company = True) - ✅ Full-text content search (
_content_search = True) - ✅ Unique key constraint per company (
_key = ["code", "company_id"]) - ✅ Export name field:
code(_export_name_field = "code") - ✅ Indexed code field for performance
Understanding Key Fields¶
What are Key Fields?¶
For the account.account model, the key fields are:
This means the combination of these fields must be unique:
- code - The account code (e.g., "101", "40100")
- company_id - The company owning this account
Why Key Fields Matter¶
Uniqueness Guarantee - Key fields prevent duplicate accounts:
# Examples of valid combinations:
Company A, Code "101" ✅ Valid (Cash account)
Company A, Code "401" ✅ Valid (Revenue account)
Company B, Code "101" ✅ Valid (different company)
# This would fail - duplicate key:
Company A, Code "101" ❌ ERROR: Account code already exists!
Account Types¶
Accounts are organized into categories based on their financial statement classification:
Asset Types¶
| Type | Code | Description | Normal Balance |
|---|---|---|---|
| Cash | cash |
Cash on hand | Debit |
| Cheque | cheque |
Cheque accounts | Debit |
| Bank Account | bank |
Bank accounts | Debit |
| Receivable | receivable |
Accounts receivable (AR) | Debit |
| Current Asset | cur_asset |
Other current assets | Debit |
| Fixed Asset | fixed_asset |
Property, plant, equipment | Debit |
| Non-current Asset | noncur_asset |
Long-term assets | Debit |
| Supplier Deposit | sup_deposit |
Deposits paid to suppliers | Debit |
Liability Types¶
| Type | Code | Description | Normal Balance |
|---|---|---|---|
| Payable | payable |
Accounts payable (AP) | Credit |
| Customer Deposit | cust_deposit |
Deposits received from customers | Credit |
| Current Liability | cur_liability |
Short-term liabilities | Credit |
| Non-current Liability | noncur_liability |
Long-term liabilities | Credit |
Equity Types¶
| Type | Code | Description | Normal Balance |
|---|---|---|---|
| Equity | equity |
Owner's equity, retained earnings | Credit |
Income Types¶
| Type | Code | Description | Normal Balance |
|---|---|---|---|
| Revenue | revenue |
Operating revenue | Credit |
| Other Income | other_income |
Non-operating income | Credit |
Expense Types¶
| Type | Code | Description | Normal Balance |
|---|---|---|---|
| Cost of Sales | cost_sales |
Direct costs (COGS) | Debit |
| Expense | expense |
Operating expenses | Debit |
| Other Expense | other_expense |
Non-operating expenses | Debit |
Special Types¶
| Type | Code | Description |
|---|---|---|
| View | view |
Parent/header account (no posting) |
| Other | other |
Miscellaneous accounts |
Bank Account Types¶
For accounts with type of cash, cheque, or bank, you can specify additional bank type:
| Bank Type | Code | Description |
|---|---|---|
| Bank Account | bank |
Standard bank account |
| Credit Card | credit_card |
Credit card account |
| PayPal | paypal |
PayPal account |
Key Fields Reference¶
Core Fields¶
| Field | Type | Required | Description |
|---|---|---|---|
code |
Char | ✅ | Account code (unique per company) |
name |
Char(256) | ✅ | Account name |
type |
Selection | ✅ | Account type (asset, liability, etc.) |
parent_id |
Many2One | ❌ | Parent account (for hierarchy) |
currency_id |
Many2One | ✅ | Account currency |
company_id |
Many2One | ❌ | Owning company |
active |
Boolean | ❌ | Whether account is active |
Bank-Specific Fields¶
| Field | Type | Description |
|---|---|---|
bank_type |
Selection | Bank account subtype |
bank_name |
Char | Name of bank |
bank_no |
Char | Bank account number |
creditcard_no |
Char | Credit card number |
Configuration Fields¶
| Field | Type | Description |
|---|---|---|
tax_id |
Many2One | Default tax rate for this account |
fixed_asset_type_id |
Many2One | Fixed asset type (for fixed asset accounts) |
sequence_id |
Many2One | Number sequence |
description |
Text | Account description/notes |
Requirements/Validation Fields¶
| Field | Type | Description |
|---|---|---|
require_contact |
Boolean | Line must have contact |
require_tax_no |
Boolean | Line must have tax number |
require_track |
Boolean | Line must have tracking category |
require_track2 |
Boolean | Line must have secondary tracking |
Payment Configuration¶
| Field | Type | Description |
|---|---|---|
enable_payment |
Boolean | Enable payments to this account |
enable_adjust |
Boolean | Enable adjustments to this account |
Balance Fields (Computed)¶
| Field | Type | Description |
|---|---|---|
balance |
Decimal | Current accounting balance |
debit |
Decimal | Total debits |
credit |
Decimal | Total credits |
balance_cur |
Decimal | Balance in account currency |
balance_statement |
Decimal | Latest bank statement balance |
balance_90d |
Json | Balance history for last 90 days |
Relationship Fields¶
| Field | Type | Description |
|---|---|---|
move_lines |
One2Many | Journal entry lines |
statements |
One2Many | Bank statements |
comments |
One2Many | Comments/messages |
Analytics Fields¶
| Field | Type | Description |
|---|---|---|
unrec_num |
Integer | Number of unreconciled items |
company_currency_id |
Many2One | Company currency (computed) |
hide_details |
Boolean | Hide from detail reports |
API Methods¶
1. Create Account¶
Method: create(vals, context)
Creates a new account in the chart of accounts.
Parameters:
vals = {
"code": "10100", # Required: Account code
"name": "Petty Cash", # Required: Account name
"type": "cash", # Required: Account type
"currency_id": 1, # Required: Currency ID
"parent_id": 101, # Optional: Parent account
"tax_id": 5, # Optional: Default tax
"require_contact": False, # Optional: Validation rules
"active": True # Optional: Active status
}
Returns: int - New account ID
Example:
# Create cash account
account_id = get_model("account.account").create({
"code": "10100",
"name": "Petty Cash",
"type": "cash",
"currency_id": base_currency_id,
"parent_id": cash_parent_id
})
2. Get Account Balance¶
Method: get_balance(ids, context)
Calculates account balance with flexible filtering options.
Parameters:
- ids (list): Account IDs
Context Options:
context = {
"date_from": "2025-01-01", # Start date filter
"date_to": "2025-01-31", # End date filter
"track_id": 10, # Filter by tracking category
"track2_id": 20, # Filter by secondary tracking
"currency_id": 2, # Convert to this currency
"contact_id": 123, # Filter by contact
"contact_type": "customer", # Filter by contact type
"bank_rec_state": "reconciled", # Filter by reconciliation
"excl_date_to": True, # Exclude date_to from range
"journal_id": 5, # Filter by journal
"no_close": True, # Exclude closing entries
"nocache": True # Skip cache
}
Returns: dict - Account ID → balance data
Balance Data Structure:
{
account_id: {
"debit": 10000.00, # Total debits
"credit": 5000.00, # Total credits
"balance": 5000.00, # Net balance (debit - credit)
"balance_cur": 5000.00 # Balance in account currency
}
}
Example:
# Get account balance for January 2025
balances = get_model("account.account").get_balance(
[account_id],
context={
"date_from": "2025-01-01",
"date_to": "2025-01-31"
}
)
print(f"Balance: {balances[account_id]['balance']}")
# Get balance by department
balances = get_model("account.account").get_balance(
[expense_account_id],
context={
"track_id": marketing_dept_id,
"date_to": "2025-01-31"
}
)
# Get customer receivables
balances = get_model("account.account").get_balance(
[ar_account_id],
context={
"contact_type": "customer",
"date_to": "2025-01-31"
}
)
3. Get 90-Day Balance History¶
Method: get_balance_90d(ids, context)
Returns daily balance data for the last 90 days (for charting).
Parameters:
- ids (list): Account IDs
- nocache (bool): Skip cache (default False)
Returns: dict - Account ID → array of [timestamp, balance] pairs
Example:
# Get balance history for chart
history = get_model("account.account").get_balance_90d([account_id])
data = history[account_id]
# data = [[1704067200000, 5000.00], [1704153600000, 5250.00], ...]
4. Get Statement Balance¶
Method: get_balance_statement(ids, context)
Returns the latest bank statement balance for bank accounts.
Parameters:
- ids (list): Account IDs
Returns: dict - Account ID → statement balance
Example:
# Get latest statement balance
stmt_bal = get_model("account.account").get_balance_statement([bank_account_id])
print(f"Statement balance: {stmt_bal[bank_account_id]}")
5. Auto Bank Reconcile¶
Method: auto_bank_reconcile(ids, context)
Automatically matches bank statement lines with journal entry lines.
Parameters:
- ids (list): Bank account IDs
Behavior: - Finds unreconciled statement lines and move lines - Matches by amount and date (within max_days tolerance) - Links matching items - Returns count of matches found
Returns: dict with flash message
Example:
# Auto-match bank transactions
result = get_model("account.account").auto_bank_reconcile([bank_account_id])
print(result["flash"]) # "15 matches found"
6. Reconcile All Matched¶
Method: reconcile_all_matched(ids, context)
Reconciles all statement lines that have matching move lines.
Parameters:
- ids (list): Account IDs
Behavior: - Finds unreconciled statement lines with move lines - Reconciles each matched line
Example:
7. Delete Account¶
Method: delete(ids, context)
Deletes accounts from the chart.
Parameters:
- ids (list): Account IDs to delete
Behavior: - Validates account is not used in posted journal entries - Deletes draft journal entries using this account - Deletes account
Returns: None
Example:
Validation Errors: - "This account can't be deleted because it is used in some posted accounting transactions"
8. Name Search¶
Method: name_search(name, condition, limit, context)
Searches accounts by code or name with smart matching.
Parameters:
- name (str): Search term
- condition (list): Additional search conditions
- limit (int): Maximum results
Behavior: - If name is numeric: searches code starting with number - Otherwise: searches name (partial) or code (starts with)
Returns: List of (id, name) tuples
Example:
# Search by code
results = get_model("account.account").name_search("101")
# Returns accounts with codes starting with "101"
# Search by name
results = get_model("account.account").name_search("cash")
# Returns accounts with "cash" in name or code starting with "cash"
9. Name Get¶
Method: name_get(ids, context)
Returns formatted account names with codes.
Parameters:
- ids (list): Account IDs
Returns: List of (id, "[code] name") tuples
Example:
names = get_model("account.account").name_get([account_id])
# Returns: [(123, "[10100] Petty Cash")]
Search Functions¶
Search by Code¶
# Find account by exact code
condition = [["code", "=", "10100"]]
# Find accounts with code starting with "101"
condition = [["code", "=ilike", "101%"]]
Search by Type¶
# Find all bank accounts
condition = [["type", "=", "bank"]]
# Find all asset accounts
condition = [["type", "in", ["cash", "bank", "receivable", "cur_asset"]]]
Search by Parent¶
Search Active Accounts¶
Computed Fields Functions¶
get_balance(ids, context)¶
Calculates account balances with comprehensive filtering: - Sums debits and credits from posted journal entry lines - Supports date ranges, tracking, contacts, reconciliation status - Handles currency conversion - Uses field cache for performance
get_balance_90d(ids, context)¶
Generates daily balance data for last 90 days: - Starts with balance from 90 days ago - Adds/subtracts each day's transactions - Returns time-series data for charting - Cached with daily refresh
get_balance_statement(ids, context)¶
Returns latest bank statement balance: - Queries most recent statement line - Used for bank reconciliation
get_unrec_num(ids, context)¶
Counts unreconciled bank statement lines per account.
get_company_currency(ids, context)¶
Returns the company's base currency for each account.
Account Hierarchy¶
Accounts can form a parent-child hierarchy using parent_id:
1000 - Assets (view)
├── 1010 - Current Assets (view)
│ ├── 1011 - Cash on Hand
│ ├── 1012 - Checking Account
│ └── 1020 - Accounts Receivable (view)
│ ├── 1021 - Domestic AR
│ └── 1022 - Foreign AR
└── 1100 - Fixed Assets (view)
├── 1110 - Equipment
└── 1120 - Vehicles
View Accounts: - Type = "view" - Used for grouping and rollup - Cannot be posted to directly - Balance is sum of children
Detail Accounts: - Any type except "view" - Can be posted to - Leaf nodes in the hierarchy
Best Practices¶
1. Use Meaningful Account Codes¶
# Bad: Non-descriptive codes
{
"code": "1",
"name": "Cash"
}
# Good: Structured codes
{
"code": "10100", # Assets - Current - Cash - Petty Cash
"name": "Petty Cash"
}
2. Set Appropriate Account Type¶
# Good: Correct type for usage
{
"code": "12000",
"name": "Accounts Receivable",
"type": "receivable", # Enables AR tracking
"require_contact": True # Enforce contact requirement
}
3. Use Hierarchy for Organization¶
# Create parent account
parent_id = get_model("account.account").create({
"code": "4000",
"name": "Revenue",
"type": "view", # View account (no posting)
"currency_id": base_currency_id
})
# Create child accounts
get_model("account.account").create({
"code": "4010",
"name": "Product Sales",
"type": "revenue",
"parent_id": parent_id,
"currency_id": base_currency_id
})
get_model("account.account").create({
"code": "4020",
"name": "Service Revenue",
"type": "revenue",
"parent_id": parent_id,
"currency_id": base_currency_id
})
4. Set Default Taxes¶
# Good: Set default tax for common usage
{
"code": "40100",
"name": "Product Sales",
"type": "revenue",
"tax_id": vat_7_percent_id, # Default tax
"currency_id": base_currency_id
}
5. Use Validation Flags Appropriately¶
# Good: Enforce data quality
{
"code": "12000",
"name": "Accounts Receivable",
"type": "receivable",
"require_contact": True, # Must have customer
"require_track": True, # Must have department
"currency_id": base_currency_id
}
Related Models¶
| Model | Relationship | Description |
|---|---|---|
account.move.line |
One2Many | Journal entry lines posting to account |
account.statement |
One2Many | Bank statements (for bank accounts) |
account.tax.rate |
Many2One | Default tax rate |
account.track.categ |
Many2One | Tracking categories (via move lines) |
account.fixed.asset.type |
Many2One | Fixed asset type |
currency |
Many2One | Account currency |
company |
Many2One | Owning company |
sequence |
Many2One | Number sequence |
message |
One2Many | Comments |
Common Use Cases¶
Use Case 1: Create Standard Chart of Accounts¶
# Create account hierarchy
accounts = [
# Assets
{"code": "1000", "name": "Assets", "type": "view", "parent": None},
{"code": "1010", "name": "Current Assets", "type": "view", "parent": "1000"},
{"code": "10100", "name": "Petty Cash", "type": "cash", "parent": "1010"},
{"code": "10200", "name": "Bank Account", "type": "bank", "parent": "1010"},
{"code": "12000", "name": "Accounts Receivable", "type": "receivable", "parent": "1010"},
# Liabilities
{"code": "2000", "name": "Liabilities", "type": "view", "parent": None},
{"code": "2010", "name": "Current Liabilities", "type": "view", "parent": "2000"},
{"code": "21000", "name": "Accounts Payable", "type": "payable", "parent": "2010"},
# Equity
{"code": "3000", "name": "Equity", "type": "view", "parent": None},
{"code": "30000", "name": "Retained Earnings", "type": "equity", "parent": "3000"},
# Revenue
{"code": "4000", "name": "Revenue", "type": "view", "parent": None},
{"code": "40100", "name": "Product Sales", "type": "revenue", "parent": "4000"},
{"code": "40200", "name": "Service Revenue", "type": "revenue", "parent": "4000"},
# Expenses
{"code": "5000", "name": "Expenses", "type": "view", "parent": None},
{"code": "50100", "name": "Cost of Goods Sold", "type": "cost_sales", "parent": "5000"},
{"code": "51000", "name": "Salaries", "type": "expense", "parent": "5000"},
{"code": "52000", "name": "Rent", "type": "expense", "parent": "5000"},
]
# Create accounts in order
account_map = {}
for acc_def in accounts:
parent_id = account_map.get(acc_def["parent"]) if acc_def["parent"] else None
acc_id = get_model("account.account").create({
"code": acc_def["code"],
"name": acc_def["name"],
"type": acc_def["type"],
"parent_id": parent_id,
"currency_id": base_currency_id
})
account_map[acc_def["code"]] = acc_id
print(f"Created {len(accounts)} accounts")
Use Case 2: Generate Trial Balance Report¶
from datetime import datetime
# Get all detail accounts (non-view)
accounts = get_model("account.account").search_browse([
["type", "!=", "view"],
["active", "=", True]
], order="code")
# Calculate balances
end_date = "2025-01-31"
print("TRIAL BALANCE")
print(f"As of {end_date}")
print("=" * 80)
print(f"{'Code':<10} {'Account Name':<40} {'Debit':>15} {'Credit':>15}")
print("-" * 80)
total_debit = 0
total_credit = 0
for account in accounts:
balance_data = get_model("account.account").get_balance(
[account.id],
context={"date_to": end_date}
)[account.id]
debit = balance_data["debit"]
credit = balance_data["credit"]
if debit != 0 or credit != 0:
print(f"{account.code:<10} {account.name:<40} {debit:>15,.2f} {credit:>15,.2f}")
total_debit += debit
total_credit += credit
print("-" * 80)
print(f"{'TOTAL':<50} {total_debit:>15,.2f} {total_credit:>15,.2f}")
print("=" * 80)
# Verify balance
if abs(total_debit - total_credit) < 0.01:
print("✓ Trial balance is balanced")
else:
print(f"✗ Trial balance is OUT OF BALANCE by {abs(total_debit - total_credit):.2f}")
Use Case 3: Generate Balance Sheet¶
# Define balance sheet structure
bs_structure = {
"Assets": ["cash", "cheque", "bank", "receivable", "cur_asset", "fixed_asset", "noncur_asset"],
"Liabilities": ["payable", "cust_deposit", "cur_liability", "noncur_liability"],
"Equity": ["equity"]
}
date = "2025-01-31"
print("BALANCE SHEET")
print(f"As of {date}")
print("=" * 80)
section_totals = {}
for section, types in bs_structure.items():
print(f"\n{section.upper()}")
print("-" * 80)
accounts = get_model("account.account").search_browse([
["type", "in", types],
["active", "=", True]
], order="code")
section_total = 0
for account in accounts:
balance_data = get_model("account.account").get_balance(
[account.id],
context={"date_to": date}
)[account.id]
balance = balance_data["balance"]
if balance != 0:
print(f" {account.code} - {account.name:<50} {balance:>15,.2f}")
section_total += balance
print("-" * 80)
print(f" Total {section:<53} {section_total:>15,.2f}")
section_totals[section] = section_total
# Calculate totals
total_assets = section_totals["Assets"]
total_liabilities = section_totals["Liabilities"]
total_equity = section_totals["Equity"]
total_liab_equity = total_liabilities + total_equity
print("\n" + "=" * 80)
print(f"TOTAL ASSETS{' '*50} {total_assets:>15,.2f}")
print(f"TOTAL LIABILITIES & EQUITY{' '*38} {total_liab_equity:>15,.2f}")
print("=" * 80)
if abs(total_assets - total_liab_equity) < 0.01:
print("✓ Balance sheet is balanced")
else:
print(f"✗ Balance sheet is OUT OF BALANCE by {abs(total_assets - total_liab_equity):.2f}")
Use Case 4: Bank Reconciliation Workflow¶
# 1. Import bank statement
bank_account_id = 102 # Bank account
statement_id = get_model("account.statement").create({
"account_id": bank_account_id,
"date": "2025-01-31",
"balance_start": 10000.00,
"balance_end": 12500.00
})
# Import statement lines (from CSV/API/etc.)
# ... (statement line import code)
# 2. Auto-reconcile matching transactions
result = get_model("account.account").auto_bank_reconcile([bank_account_id])
print(result["flash"]) # "25 matches found"
# 3. Manually review unmatched items
account = get_model("account.account").browse(bank_account_id)
print(f"Unreconciled items: {account.unrec_num}")
# 4. Reconcile all matched items
get_model("account.account").reconcile_all_matched([bank_account_id])
# 5. Check reconciliation status
accounting_bal = get_model("account.account").get_balance([bank_account_id])[bank_account_id]["balance"]
statement_bal = get_model("account.account").get_balance_statement([bank_account_id])[bank_account_id]
print(f"Accounting balance: {accounting_bal:,.2f}")
print(f"Statement balance: {statement_bal:,.2f}")
print(f"Difference: {abs(accounting_bal - statement_bal):,.2f}")
Use Case 5: Analyze Expenses by Department¶
# Get all expense accounts
expense_accounts = get_model("account.account").search_browse([
["type", "in", ["cost_sales", "expense", "other_expense"]],
["active", "=", True]
])
# Get all departments (tracking categories)
departments = get_model("account.track.categ").search_browse([
["type", "=", "1"] # Type 1 = primary tracking (departments)
])
print("EXPENSE ANALYSIS BY DEPARTMENT")
print("Period: January 2025")
print("=" * 100)
print(f"{'Account':<50} {'Dept 1':>15} {'Dept 2':>15} {'Dept 3':>15} {'Total':>15}")
print("-" * 100)
for account in expense_accounts:
row_data = [account.code + " - " + account.name]
row_total = 0
for dept in departments:
balance_data = get_model("account.account").get_balance(
[account.id],
context={
"date_from": "2025-01-01",
"date_to": "2025-01-31",
"track_id": dept.id
}
)[account.id]
amount = balance_data["balance"]
row_data.append(f"{amount:>15,.2f}")
row_total += amount
row_data.append(f"{row_total:>15,.2f}")
if row_total != 0:
print(f"{row_data[0]:<50} " + " ".join(row_data[1:]))
print("=" * 100)
Use Case 6: Currency Conversion for Foreign Accounts¶
# Get USD bank account balance in both USD and base currency (THB)
usd_account_id = 105
# Balance in account currency (USD)
balance_usd = get_model("account.account").get_balance([usd_account_id])[usd_account_id]
print(f"USD Account Balance (USD): {balance_usd['balance_cur']:,.2f}")
# Balance in base currency (THB)
settings = get_model("settings").browse(1)
base_currency_id = settings.currency_id.id
balance_thb = get_model("account.account").get_balance(
[usd_account_id],
context={"currency_id": base_currency_id}
)[usd_account_id]
print(f"USD Account Balance (THB): {balance_thb['balance']:,.2f}")
# Calculate effective exchange rate
if balance_usd['balance_cur'] != 0:
effective_rate = balance_thb['balance'] / balance_usd['balance_cur']
print(f"Effective exchange rate: {effective_rate:.4f}")
Performance Tips¶
1. Use Field Cache¶
Balance calculations are cached for performance:
# First call: queries database
balance1 = get_model("account.account").get_balance([account_id])
# Second call: uses cache (much faster)
balance2 = get_model("account.account").get_balance([account_id])
# Force refresh: use nocache
balance3 = get_model("account.account").get_balance(
[account_id],
context={"nocache": True}
)
2. Batch Balance Queries¶
# Good: Query multiple accounts at once
account_ids = [101, 102, 103, 104, 105]
balances = get_model("account.account").get_balance(account_ids)
# Bad: Query one at a time
for account_id in account_ids:
balance = get_model("account.account").get_balance([account_id])
3. Use Indexed Fields¶
Code field is indexed for fast lookups:
Troubleshooting¶
"This account can't be deleted because it is used in some posted accounting transactions"¶
Cause: Account has posted journal entries
Solution: Cannot delete accounts with transaction history. Consider deactivating instead: active = False
Balance doesn't match expected value¶
Cause: Journal entries not posted, or filtering issue
Solution: Verify all entries are posted, check date filters in context
"Missing currency for account"¶
Cause: Account created without currency_id
Solution: Always set currency_id when creating accounts
Auto-reconcile not finding matches¶
Cause: Date tolerance too strict or amounts don't match exactly
Solution: Adjust bank_reconcile_max_days in settings, verify amounts match
View account appearing in trial balance¶
Cause: Incorrect query filter
Solution: Filter by type != "view" to exclude parent accounts
Testing Examples¶
Unit Test: Create Account and Check Balance¶
def test_account_balance():
# Create account
account_id = get_model("account.account").create({
"code": "99999",
"name": "Test Account",
"type": "other",
"currency_id": 1
})
# Initial balance should be zero
balance = get_model("account.account").get_balance([account_id])
assert balance[account_id]["balance"] == 0
# Create journal entry
move_id = get_model("account.move").create({
"journal_id": 1,
"date": "2025-01-15",
"narration": "Test",
"lines": [
("create", {"account_id": account_id, "debit": 1000, "credit": 0}),
("create", {"account_id": 401, "debit": 0, "credit": 1000})
]
})
get_model("account.move").post([move_id])
# Check balance
balance = get_model("account.account").get_balance(
[account_id],
context={"nocache": True}
)
assert balance[account_id]["balance"] == 1000
assert balance[account_id]["debit"] == 1000
assert balance[account_id]["credit"] == 0
# Cleanup
move = get_model("account.move").browse(move_id)
move.void()
get_model("account.account").delete([account_id])
Security Considerations¶
Permission Model¶
account_view: View accountsaccount_create: Create accountsaccount_edit: Edit accountsaccount_delete: Delete accounts
Data Access¶
- Multi-company: Users only see accounts for their company
- Audit log: All changes tracked
- Deletion restricted: Cannot delete accounts with history
Configuration Settings¶
Required Settings¶
| Setting | Location | Description |
|---|---|---|
currency_id |
Settings | Base currency for all accounts |
Optional Settings¶
| Setting | Default | Description |
|---|---|---|
bank_reconcile_max_days |
30 | Max days for auto-reconcile matching |
Integration Points¶
Internal Modules¶
- Journal Entries: All transactions post to accounts
- Invoices: Use AR/AP accounts
- Payments: Use bank/cash accounts
- Fixed Assets: Use fixed asset accounts
- Bank Statements: Reconcile with bank accounts
- Tracking: Filter by tracking categories
- Reports: Source for all financial reports
Version History¶
Last Updated: November 7, 2025
Model File: netforce_account/models/account_account.py
Framework: Netforce
Document Version: 1.0.0
Complexity: ⭐⭐⭐⭐⭐ (Very High - Core configuration)
Additional Resources¶
- Journal Entry Line Documentation:
account.move.line - Balance Documentation:
account.balance - Statement Documentation:
account.statement - Currency Documentation:
currency
Support & Feedback¶
For issues or questions about this module: 1. Verify account type matches usage 2. Check currency is set 3. Use nocache for latest balances 4. Review account hierarchy 5. Test queries in development environment
This documentation is generated for developer onboarding and reference purposes.