feat(fusion_accounting_ai): 5 new asset management AI tools
Made-with: Cursor
This commit is contained in:
@@ -10,11 +10,13 @@ from .adp import TOOLS as ADP_TOOLS
|
|||||||
from .reporting import TOOLS as REPORTING_TOOLS
|
from .reporting import TOOLS as REPORTING_TOOLS
|
||||||
from .audit import TOOLS as AUDIT_TOOLS
|
from .audit import TOOLS as AUDIT_TOOLS
|
||||||
from .financial_reports import TOOLS as FINANCIAL_REPORTS_TOOLS
|
from .financial_reports import TOOLS as FINANCIAL_REPORTS_TOOLS
|
||||||
|
from .asset_management import TOOLS as ASSET_MANAGEMENT_TOOLS
|
||||||
|
|
||||||
TOOL_DISPATCH = {}
|
TOOL_DISPATCH = {}
|
||||||
for tools_dict in [
|
for tools_dict in [
|
||||||
BANK_RECON_TOOLS, HST_TOOLS, AR_TOOLS, AP_TOOLS, JOURNAL_TOOLS,
|
BANK_RECON_TOOLS, HST_TOOLS, AR_TOOLS, AP_TOOLS, JOURNAL_TOOLS,
|
||||||
MONTH_END_TOOLS, PAYROLL_TOOLS, INVENTORY_TOOLS, ADP_TOOLS,
|
MONTH_END_TOOLS, PAYROLL_TOOLS, INVENTORY_TOOLS, ADP_TOOLS,
|
||||||
REPORTING_TOOLS, AUDIT_TOOLS, FINANCIAL_REPORTS_TOOLS,
|
REPORTING_TOOLS, AUDIT_TOOLS, FINANCIAL_REPORTS_TOOLS,
|
||||||
|
ASSET_MANAGEMENT_TOOLS,
|
||||||
]:
|
]:
|
||||||
TOOL_DISPATCH.update(tools_dict)
|
TOOL_DISPATCH.update(tools_dict)
|
||||||
|
|||||||
77
fusion_accounting_ai/services/tools/asset_management.py
Normal file
77
fusion_accounting_ai/services/tools/asset_management.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
"""Fusion-engine-routed AI tools for asset management."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def fusion_list_assets(env, params):
|
||||||
|
if 'fusion.asset.engine' not in env.registry:
|
||||||
|
return {'error': 'fusion_accounting_assets not installed'}
|
||||||
|
from ..data_adapters import get_adapter
|
||||||
|
adapter = get_adapter(env, 'assets')
|
||||||
|
return adapter.list_assets(
|
||||||
|
state=params.get('state'),
|
||||||
|
limit=int(params.get('limit', 50)),
|
||||||
|
company_id=int(params['company_id']) if params.get('company_id') else env.company.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def fusion_get_asset_detail(env, params):
|
||||||
|
if 'fusion.asset.engine' not in env.registry:
|
||||||
|
return {'error': 'fusion_accounting_assets not installed'}
|
||||||
|
Asset = env['fusion.asset']
|
||||||
|
asset = Asset.browse(int(params['asset_id']))
|
||||||
|
if not asset.exists():
|
||||||
|
return {'error': 'Asset not found'}
|
||||||
|
return {
|
||||||
|
'asset': {
|
||||||
|
'id': asset.id, 'name': asset.name, 'state': asset.state,
|
||||||
|
'cost': asset.cost, 'book_value': asset.book_value,
|
||||||
|
'total_depreciated': asset.total_depreciated,
|
||||||
|
'method': asset.method, 'useful_life_years': asset.useful_life_years,
|
||||||
|
},
|
||||||
|
'depreciation_count': len(asset.depreciation_line_ids),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def fusion_compute_asset_schedule(env, params):
|
||||||
|
if 'fusion.asset.engine' not in env.registry:
|
||||||
|
return {'error': 'fusion_accounting_assets not installed'}
|
||||||
|
asset = env['fusion.asset'].browse(int(params['asset_id']))
|
||||||
|
return env['fusion.asset.engine'].compute_depreciation_schedule(
|
||||||
|
asset, recompute=bool(params.get('recompute', False)),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def fusion_dispose_asset(env, params):
|
||||||
|
if 'fusion.asset.engine' not in env.registry:
|
||||||
|
return {'error': 'fusion_accounting_assets not installed'}
|
||||||
|
from ..data_adapters import get_adapter
|
||||||
|
adapter = get_adapter(env, 'assets')
|
||||||
|
return adapter.dispose_asset(
|
||||||
|
asset_id=int(params['asset_id']),
|
||||||
|
sale_amount=float(params.get('sale_amount', 0)),
|
||||||
|
disposal_type=params.get('disposal_type', 'sale'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def fusion_suggest_asset_useful_life(env, params):
|
||||||
|
if 'fusion.asset.engine' not in env.registry:
|
||||||
|
return {'error': 'fusion_accounting_assets not installed'}
|
||||||
|
from ..data_adapters import get_adapter
|
||||||
|
adapter = get_adapter(env, 'assets')
|
||||||
|
return adapter.suggest_useful_life(
|
||||||
|
description=params.get('description', ''),
|
||||||
|
amount=float(params['amount']) if params.get('amount') else None,
|
||||||
|
partner_name=params.get('partner_name'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
TOOLS = {
|
||||||
|
'fusion_list_assets': fusion_list_assets,
|
||||||
|
'fusion_get_asset_detail': fusion_get_asset_detail,
|
||||||
|
'fusion_compute_asset_schedule': fusion_compute_asset_schedule,
|
||||||
|
'fusion_dispose_asset': fusion_dispose_asset,
|
||||||
|
'fusion_suggest_asset_useful_life': fusion_suggest_asset_useful_life,
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
'name': 'Fusion Accounting Assets',
|
'name': 'Fusion Accounting Assets',
|
||||||
'version': '19.0.1.0.15',
|
'version': '19.0.1.0.16',
|
||||||
'category': 'Accounting/Accounting',
|
'category': 'Accounting/Accounting',
|
||||||
'summary': 'AI-augmented asset management with depreciation schedules.',
|
'summary': 'AI-augmented asset management with depreciation schedules.',
|
||||||
'description': """
|
'description': """
|
||||||
|
|||||||
@@ -13,3 +13,4 @@ from . import test_fusion_asset_engine
|
|||||||
from . import test_engine_integration
|
from . import test_engine_integration
|
||||||
from . import test_assets_controller
|
from . import test_assets_controller
|
||||||
from . import test_assets_adapter
|
from . import test_assets_adapter
|
||||||
|
from . import test_asset_tools
|
||||||
|
|||||||
56
fusion_accounting_assets/tests/test_asset_tools.py
Normal file
56
fusion_accounting_assets/tests/test_asset_tools.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
"""Tests for the 5 fusion-asset AI tools."""
|
||||||
|
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
from odoo.tests import tagged
|
||||||
|
from odoo.tests.common import TransactionCase
|
||||||
|
|
||||||
|
from odoo.addons.fusion_accounting_ai.services.tools import asset_management as tools
|
||||||
|
|
||||||
|
|
||||||
|
@tagged('post_install', '-at_install')
|
||||||
|
class TestFusionAssetTools(TransactionCase):
|
||||||
|
|
||||||
|
def test_fusion_list_assets(self):
|
||||||
|
self.env['fusion.asset'].create({
|
||||||
|
'name': 'Tool Test', 'cost': 1000,
|
||||||
|
'acquisition_date': date(2026, 1, 1),
|
||||||
|
'method': 'straight_line', 'useful_life_years': 4,
|
||||||
|
})
|
||||||
|
result = tools.fusion_list_assets(self.env, {'company_id': self.env.company.id})
|
||||||
|
self.assertGreaterEqual(result.get('count', 0), 1)
|
||||||
|
|
||||||
|
def test_fusion_get_asset_detail(self):
|
||||||
|
asset = self.env['fusion.asset'].create({
|
||||||
|
'name': 'Detail Test', 'cost': 1500,
|
||||||
|
'acquisition_date': date(2026, 1, 1),
|
||||||
|
'method': 'straight_line', 'useful_life_years': 4,
|
||||||
|
})
|
||||||
|
result = tools.fusion_get_asset_detail(self.env, {'asset_id': asset.id})
|
||||||
|
self.assertEqual(result['asset']['name'], 'Detail Test')
|
||||||
|
|
||||||
|
def test_fusion_compute_schedule(self):
|
||||||
|
asset = self.env['fusion.asset'].create({
|
||||||
|
'name': 'Schedule Test', 'cost': 2000,
|
||||||
|
'acquisition_date': date(2026, 1, 1),
|
||||||
|
'method': 'straight_line', 'useful_life_years': 4,
|
||||||
|
})
|
||||||
|
result = tools.fusion_compute_asset_schedule(self.env, {'asset_id': asset.id})
|
||||||
|
self.assertEqual(result['lines_created'], 4)
|
||||||
|
|
||||||
|
def test_fusion_suggest_useful_life(self):
|
||||||
|
self.env['ir.config_parameter'].sudo().search([
|
||||||
|
('key', 'in', ['fusion_accounting.provider.asset_useful_life',
|
||||||
|
'fusion_accounting.provider.default'])
|
||||||
|
]).unlink()
|
||||||
|
result = tools.fusion_suggest_asset_useful_life(self.env, {
|
||||||
|
'description': 'desk',
|
||||||
|
})
|
||||||
|
self.assertEqual(result['useful_life_years'], 7)
|
||||||
|
|
||||||
|
def test_tools_registered_in_dispatch(self):
|
||||||
|
from odoo.addons.fusion_accounting_ai.services.tools import TOOL_DISPATCH
|
||||||
|
for tool_name in ['fusion_list_assets', 'fusion_get_asset_detail',
|
||||||
|
'fusion_compute_asset_schedule', 'fusion_dispose_asset',
|
||||||
|
'fusion_suggest_asset_useful_life']:
|
||||||
|
self.assertIn(tool_name, TOOL_DISPATCH)
|
||||||
Reference in New Issue
Block a user