from odoo.tests.common import TransactionCase from odoo.tests import tagged from odoo.addons.fusion_accounting_assets.services.depreciation_methods import ( straight_line, declining_balance, units_of_production, ) @tagged('post_install', '-at_install') class TestStraightLine(TransactionCase): def test_total_equals_cost_minus_salvage(self): steps = straight_line(cost=10000, salvage_value=1000, n_periods=5) total = sum(s.period_amount for s in steps) self.assertAlmostEqual(total, 9000, places=2) def test_per_period_equal_except_last(self): steps = straight_line(cost=10000, salvage_value=0, n_periods=4) self.assertEqual([s.period_amount for s in steps], [2500.0] * 4) def test_last_period_absorbs_rounding(self): steps = straight_line(cost=10000, salvage_value=0, n_periods=3) total = sum(s.period_amount for s in steps) self.assertAlmostEqual(total, 10000, places=2) def test_zero_periods_returns_empty(self): self.assertEqual(straight_line(cost=10000, n_periods=0), []) def test_book_value_decreasing(self): steps = straight_line(cost=10000, salvage_value=1000, n_periods=5) for i in range(1, len(steps)): self.assertLess(steps[i].book_value_at_end, steps[i - 1].book_value_at_end) @tagged('post_install', '-at_install') class TestDecliningBalance(TransactionCase): def test_total_does_not_exceed_depreciable(self): steps = declining_balance(cost=10000, salvage_value=1000, n_periods=10, rate=0.20) total = sum(s.period_amount for s in steps) self.assertLessEqual(total, 9000.01) def test_does_not_go_below_salvage(self): steps = declining_balance(cost=10000, salvage_value=1000, n_periods=10, rate=0.50) for s in steps: self.assertGreaterEqual(s.book_value_at_end, 999.99) def test_zero_rate_returns_empty(self): self.assertEqual(declining_balance(cost=10000, n_periods=5, rate=0), []) def test_pathological_100pct_rate_one_period(self): steps = declining_balance(cost=10000, salvage_value=500, n_periods=10, rate=1.0) self.assertEqual(len(steps), 1) self.assertAlmostEqual(steps[0].period_amount, 9500, places=2) @tagged('post_install', '-at_install') class TestUnitsOfProduction(TransactionCase): def test_total_proportional_to_units_used(self): steps = units_of_production( cost=20000, salvage_value=2000, total_units_expected=10000, units_per_period=[1000, 2000, 3000, 4000], ) total = sum(s.period_amount for s in steps) self.assertAlmostEqual(total, 18000, places=1) def test_partial_use_partial_depreciation(self): steps = units_of_production( cost=10000, salvage_value=0, total_units_expected=1000, units_per_period=[200], ) self.assertAlmostEqual(steps[0].period_amount, 2000, places=2) def test_zero_total_units_returns_empty(self): self.assertEqual( units_of_production(cost=10000, total_units_expected=0, units_per_period=[100]), [], ) def test_does_not_overshoot_salvage(self): steps = units_of_production( cost=10000, salvage_value=1000, total_units_expected=1000, units_per_period=[2000], ) self.assertAlmostEqual(steps[0].period_amount, 9000, places=2)