odoo_utility_scripts/test_depreciation_logic.py

214 lines
8.0 KiB
Python

import sys
import os
import argparse
from datetime import datetime, date
from dateutil.relativedelta import relativedelta
def main():
parser = argparse.ArgumentParser(description="Deep Test Depreciation Logic")
parser.add_argument("odoo_bin_path", help="Path to odoo-bin executable")
parser.add_argument("conf_path", help="Path to odoo.conf")
parser.add_argument("db_name", help="Database name")
args = parser.parse_args()
odoo_bin_path = os.path.abspath(args.odoo_bin_path)
conf_path = os.path.abspath(args.conf_path)
db_name = args.db_name
# Add Odoo to sys.path
odoo_root = os.path.dirname(odoo_bin_path)
if odoo_root not in sys.path:
sys.path.append(odoo_root)
# Change CWD to config directory to handle relative paths in config (like addons_path)
os.chdir(os.path.dirname(conf_path))
try:
import odoo
from odoo import api, SUPERUSER_ID
except ImportError:
print(f"Error: Could not import 'odoo' module from {odoo_root}. Make sure odoo-bin path is correct.")
sys.exit(1)
print(f"Initializing Odoo Environment for database: {db_name}...")
try:
odoo.tools.config.parse_config(['-c', conf_path])
registry = odoo.registry(db_name)
except Exception as e:
print(f"Error initializing Odoo: {e}")
return
with registry.cursor() as cr:
env = api.Environment(cr, SUPERUSER_ID, {})
print("Connected to Odoo.")
try:
test_different_scenarios(env)
cr.commit()
print("Test completed successfully.")
except Exception as e:
cr.rollback()
print(f"Test failed: {e}")
import traceback
traceback.print_exc()
def test_different_scenarios(env):
# Find an asset model to use
model = env['account.asset'].search([('state', '=', 'model')], limit=1)
if not model:
print("No asset model found!")
return
print(f"Using asset model: {model.name}")
print(f"Model settings: method={model.method}, method_number={model.method_number}, method_period={model.method_period}")
# Test different acquisition dates
test_cases = [
{
'name': 'Future Acquisition (2025-11-01)',
'acquisition_date': date(2025, 11, 1),
'description': 'Asset acquired after cutoff date'
},
{
'name': 'Recent Acquisition (2024-11-01)',
'acquisition_date': date(2024, 11, 1),
'description': 'Asset acquired before cutoff date'
},
{
'name': 'Old Acquisition (2020-01-01)',
'acquisition_date': date(2020, 1, 1),
'description': 'Very old asset'
}
]
for i, test_case in enumerate(test_cases):
print(f"\n{'='*60}")
print(f"TEST {i+1}: {test_case['name']}")
print(f"Description: {test_case['description']}")
print(f"{'='*60}")
acquisition_date = test_case['acquisition_date']
original_value = 48500000.0
vals = {
'name': f'TEST Asset - {test_case["name"]}',
'original_value': original_value,
'acquisition_date': acquisition_date,
'model_id': model.id,
'method': model.method,
'method_number': 60, # Force 60 months
'method_period': '1', # Force monthly
'prorata_computation_type': model.prorata_computation_type,
'state': 'draft',
'account_asset_id': model.account_asset_id.id,
'account_depreciation_id': model.account_depreciation_id.id,
'account_depreciation_expense_id': model.account_depreciation_expense_id.id,
'journal_id': model.journal_id.id,
'method_progress_factor': model.method_progress_factor,
'analytic_distribution': model.analytic_distribution,
}
asset = env['account.asset'].create(vals)
print(f"Created asset: {asset.name}")
print(f" Acquisition Date: {asset.acquisition_date}")
print(f" Method Number: {asset.method_number}")
print(f" Method Period: {asset.method_period}")
# Compute depreciation board
asset.compute_depreciation_board()
moves = asset.depreciation_move_ids.sorted('date')
print(f" Moves created: {len(moves)}")
if moves:
print(f" First move: {moves[0].date}")
print(f" Last move: {moves[-1].date}")
# Calculate expected end date
expected_end = acquisition_date + relativedelta(months=59) # 60 months = 0 to 59
print(f" Expected last move around: {expected_end}")
# Check if complete
if len(moves) >= 60:
print(f" ✅ Complete: {len(moves)} moves")
else:
print(f" ❌ Incomplete: Only {len(moves)} moves (expected 60)")
# Show first few and last few moves
print(f" First 3 moves:")
for move in moves[:3]:
amount = sum(line.debit for line in move.line_ids if line.account_id == asset.account_depreciation_expense_id)
print(f" {move.date}: {amount:,.2f}")
print(f" Last 3 moves:")
for move in moves[-3:]:
amount = sum(line.debit for line in move.line_ids if line.account_id == asset.account_depreciation_expense_id)
print(f" {move.date}: {amount:,.2f}")
# Cleanup
asset.unlink()
# Test with different prorata settings
print(f"\n{'='*60}")
print(f"TEST: Different Prorata Settings")
print(f"{'='*60}")
prorata_options = ['constant_periods', 'daily_computation', 'none']
for prorata in prorata_options:
print(f"\nTesting prorata_computation_type: {prorata}")
vals = {
'name': f'TEST Asset - Prorata {prorata}',
'original_value': 48500000.0,
'acquisition_date': date(2024, 11, 1),
'model_id': model.id,
'method': 'linear',
'method_number': 60,
'method_period': '1',
'prorata_computation_type': prorata,
'state': 'draft',
'account_asset_id': model.account_asset_id.id,
'account_depreciation_id': model.account_depreciation_id.id,
'account_depreciation_expense_id': model.account_depreciation_expense_id.id,
'journal_id': model.journal_id.id,
'method_progress_factor': model.method_progress_factor,
'analytic_distribution': model.analytic_distribution,
}
asset = env['account.asset'].create(vals)
asset.compute_depreciation_board()
moves = asset.depreciation_move_ids.sorted('date')
print(f" Moves: {len(moves)}, Last: {moves[-1].date if moves else 'None'}, Prorata Date: {asset.prorata_date}")
asset.unlink()
# Manual Test for 'none' with forced date
print(f"\nTesting prorata_computation_type: none (FORCED prorata_date)")
vals = {
'name': f'TEST Asset - Forced None',
'original_value': 48500000.0,
'acquisition_date': date(2024, 11, 1),
'prorata_date': date(2024, 11, 1), # Explicitly set
'model_id': model.id,
'method': 'linear',
'method_number': 60,
'method_period': '1',
'prorata_computation_type': 'none',
'state': 'draft',
'account_asset_id': model.account_asset_id.id,
'account_depreciation_id': model.account_depreciation_id.id,
'account_depreciation_expense_id': model.account_depreciation_expense_id.id,
'journal_id': model.journal_id.id,
}
asset = env['account.asset'].create(vals)
asset.compute_depreciation_board()
moves = asset.depreciation_move_ids.sorted('date')
print(f" Moves: {len(moves)}, Last: {moves[-1].date if moves else 'None'}, Prorata Date: {asset.prorata_date}")
asset.unlink()
if __name__ == "__main__":
main()