9.3 KiB
| name | version | description | trigger_conditions | |||
|---|---|---|---|---|---|---|
| accounting-module-example | 1.0.0 | Complete example of a compliant accounting module following the module development specification, demonstrating proper structure, initialization, CRUD definitions, and integration patterns. |
|
Accounting Module Example
Overview
This skill provides a complete reference implementation of an accounting module that fully complies with the module development specification. The accounting module demonstrates proper organization, initialization patterns, CRUD definitions, and integration with the ahserver ecosystem.
Module Structure Analysis
Core Directory Structure
accounting/ # Main module directory
├── accounting/ # Python package
│ ├── __init__.py # Python package marker
│ ├── init.py # Module initialization (load_accounting function)
│ ├── *.py # Core business logic files
├── json/ # CRUD definition files (.json)
│ ├── account.json
│ ├── accounting_log.json
│ ├── subject.json
│ ├── acc_detail.json
│ ├── acc_balance.json
│ ├── accounting_config.json
│ └── account_config.json
├── models/ # Database table definitions (.xlsx format in this example)
│ ├── account.xlsx
│ ├── acc_balance.xlsx
│ ├── acc_detail.xlsx
│ ├── subject.xlsx
│ └── ... (other table definitions)
├── wwwroot/ # Frontend scripts and resources
│ ├── *.ui # Jinja2 template files
│ ├── *.dspy # Controlled Python scripts
│ └── imgs/ # Image assets
├── init/ # Initialization data (not present in this example)
├── setup.py # Python packaging (legacy format)
├── requirements.txt # Dependencies
└── README.md # Module documentation
Key Implementation Patterns
1. Module Initialization (init.py)
The load_accounting() function properly exposes all necessary components through ServerEnv:
def load_accounting():
g = ServerEnv()
g.Accounting = Accounting # Configuration class
g.RechargeBiz = RechargeBiz # Business logic class
g.consume_accounting = consume_accounting # Async functions
g.write_bill = write_bill
g.openOwnerAccounts = openOwnerAccounts # Account opening functions
g.openProviderAccounts = openProviderAccounts
g.openResellerAccounts = openResellerAccounts
g.openCustomerAccounts = openCustomerAccounts
g.getAccountBalance = getAccountBalance # Balance query functions
g.getCustomerBalance = getCustomerBalance
g.getAccountByName = getAccountByName
g.get_account_total_amount = get_account_total_amount
g.recharge_accounting = recharge_accounting
g.get_accdetail = get_accdetail # Detail query functions
g.all_my_accounts = all_my_accounts
g.openRetailRelationshipAccounts = openRetailRelationshipAccounts
2. CRUD Definition Example (account.json)
Demonstrates list view configuration with subtables for related data:
{
"tblname": "account",
"title": "科目",
"params": {
"sortby": "name",
"browserfields": {
"exclouded": ["id"],
"cwidth": {}
},
"editexclouded": ["id"],
"subtables": [
{
"field": "accountid",
"title": "账户余额",
"subtable": "acc_balance"
},
{
"field": "accountid",
"title": "账户明细",
"subtable": "acc_detail"
},
{
"field": "accountid",
"title": "账户日志",
"subtable": "accounting_log"
}
]
}
}
3. Frontend Integration
- UI Files:
.uifiles in wwwroot/ use Jinja2 templating - Script Files:
.dspyfiles provide server-side logic - Assets: Static resources in wwwroot/imgs/
4. Business Logic Organization
Core functionality is organized into logical modules:
accounting_config.py: Configuration managementbill.py: Billing operationsopenaccount.py: Account creation workflowsgetaccount.py: Account queryingrecharge.py: Recharge processingconsume.py: Consumption processingledger.py: Ledger operations
Compliance Verification
✅ Module Development Specification Compliance
- Proper directory structure with accounting/, wwwroot/, json/, models/
- Correct init.py with load_accounting() function
- ServerEnv exposure of all required functions
- CRUD definitions in json/ directory
- Frontend resources in wwwroot/ directory
- Database table definitions in models/ directory
⚠️ Minor Deviations
- Uses
.xlsxformat for table definitions instead of.json(still valid internal format) - Uses
setup.pyinstead ofpyproject.toml(legacy but functional) - Missing
init/data.json(optional if no initialization data needed)
Usage as Reference Implementation
This accounting module serves as an excellent reference for:
- Module Structure: How to organize a complex business module
- Function Exposure: Proper ServerEnv usage patterns
- CRUD Configuration: Real-world CRUD definition examples
- Business Logic: Separation of concerns in accounting operations
- Frontend Integration: UI/script resource organization
Deep-Dive References
references/accounting-internals.md— PFBiz/Accounting class hierarchy, leg_accounting hot path, overdraft check pattern, credit limit extension, subject/account relationships, accounting_config table driving journal entriesreferences/coupon-system.md— platformbiz coupon/coupontype/coupon_log table structure, mintransamt (满减门槛) support, gap analysis for tiered discounts, integration plan with accounting modulereferences/credit-limit-multi-tenant.md— multi-tenant credit limit design: grant_orgid field, admin vs customer read views, migration SQL
Pitfalls
Balance update is NOT optional
Accounting = 写分录明细 + 写日志 + 修改账户余额. These three steps are the DEFINITION of accounting (记账), not optional add-ons. If an implementation only writes the detail record without updating the balance, it is incomplete by definition — do not characterize balance update as a "missing feature" or "nice to have". It IS the accounting.
Overdraft check belongs in the same transaction
The balance update and overdraft/credit-limit check must happen in the same DB context as the detail insert. Reading balance, checking credit limit, and writing the new balance must be atomic with the accounting record.
Integration Notes
- Integrates with sqlor-database-module for database operations
- Uses bricks-framework compatible UI templates
- Follows security patterns from user/org context handling
- Implements comprehensive accounting workflows (recharge, consume, billing, balance queries)
Integration Checklist for New Features
When adding any new entity/feature to the accounting module (or any Sage module), you MUST verify all four integration points:
- init.py — New functions/classes must be imported and exposed via
ServerEnvinload_<module>() - scripts/load_path.py — All new
.uiand.dspypages must have RBAC paths registered (in module's ownscripts/directory, not sage main repo) - wwwroot/global_menu.ui (sage main repo) — Menu entry for the new page
- json/.json — CRUD definition file (must conform to crud-definition-spec: root keys = tblname + params)
Missing any of these means the feature is invisible/unusable even if the code is correct. Always audit all four before declaring done.
Pitfalls
- Don't revert approved changes when context expands. If the user approves change A, and later says "also do B", that doesn't mean A was wrong. Build on A, don't undo it. User frustration: "为什么实际做却不按确认的做呢" — reverting approved work without asking.
- Read the full existing module before modifying. The accounting module has a complete system (PFBiz → Accounting → leg_accounting). Before adding features, read
accounting_config.py,creditlimit.py,consume.py, etc. to understand how they work together. Don't invent parallel implementations. - sageapi vs sage accounting are two layers. sage/pkgs/accounting/ is the core accounting engine (double-entry, legs, subjects). sageapi is a lightweight API gateway. Both may need credit_limit logic but in different ways — don't confuse them.
Learning Points
- How to expose both classes and functions through ServerEnv
- Pattern for async database query functions with proper context management
- Subtable relationships in CRUD definitions for master-detail scenarios
- Organization of complex business logic across multiple Python modules