Public release from ruodoo-project: 19.0 - 2026-05-10 21:19:01 UTC
This commit is contained in:
1
account_move_templates/tests/__init__.py
Normal file
1
account_move_templates/tests/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import test_template
|
||||
200
account_move_templates/tests/test_template.py
Normal file
200
account_move_templates/tests/test_template.py
Normal file
@ -0,0 +1,200 @@
|
||||
"""
|
||||
Tests for Template_Engine (account_move_templates).
|
||||
|
||||
Validates: Requirements 3.1, 3.2, 3.3, 3.4, 3.5
|
||||
"""
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _get_account(env, account_type='asset_current'):
|
||||
"""Return an existing account of the given type, or create one."""
|
||||
account = env['account.account'].search(
|
||||
[('account_type', '=', account_type)], limit=1
|
||||
)
|
||||
if not account:
|
||||
account = env['account.account'].create({
|
||||
'name': f'Test Account ({account_type})',
|
||||
'code': f'TST{account_type[:4].upper()}',
|
||||
'account_type': account_type,
|
||||
})
|
||||
return account
|
||||
|
||||
|
||||
def _make_template(env, name='Test Template', lines=None):
|
||||
"""Create an AccountMoveTemplate with the given lines.
|
||||
|
||||
lines: list of dicts with keys: account_id, move_type, percent, line_type
|
||||
"""
|
||||
vals = {'name': name}
|
||||
if lines is not None:
|
||||
vals['line_ids'] = [(0, 0, line) for line in lines]
|
||||
return env['account.move.template'].create(vals)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# TestMoveTemplateValidation
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestMoveTemplateValidation(TransactionCase):
|
||||
"""Validates: Requirements 3.1, 3.2, 3.3, 3.4"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.account_debit = _get_account(self.env, 'asset_current')
|
||||
self.account_credit = _get_account(self.env, 'liability_current')
|
||||
|
||||
def _line(self, move_type, percent, account=None):
|
||||
if account is None:
|
||||
account = self.account_debit if move_type == 'debit' else self.account_credit
|
||||
return {
|
||||
'account_id': account.id,
|
||||
'move_type': move_type,
|
||||
'percent': percent,
|
||||
'line_type': 'product',
|
||||
}
|
||||
|
||||
def test_no_lines_raises_validation_error(self):
|
||||
"""Req 3.1 — template without lines raises ValidationError."""
|
||||
with self.assertRaises(ValidationError):
|
||||
_make_template(self.env, name='Empty Template', lines=[])
|
||||
|
||||
def test_imbalanced_percentages_raises_validation_error(self):
|
||||
"""Req 3.2 — debit sum != credit sum raises ValidationError."""
|
||||
with self.assertRaises(ValidationError):
|
||||
_make_template(self.env, name='Imbalanced', lines=[
|
||||
self._line('debit', 60.0),
|
||||
self._line('credit', 40.0),
|
||||
])
|
||||
|
||||
def test_balanced_percentages_saves_without_error(self):
|
||||
"""Req 3.3 — debit sum == credit sum saves without error."""
|
||||
template = _make_template(self.env, name='Balanced', lines=[
|
||||
self._line('debit', 100.0),
|
||||
self._line('credit', 100.0),
|
||||
])
|
||||
self.assertTrue(template.id, "Template should be saved with a valid ID")
|
||||
|
||||
def test_percent_below_minimum_raises_validation_error(self):
|
||||
"""Req 3.4 — percent < 0.01 raises ValidationError."""
|
||||
with self.assertRaises(ValidationError):
|
||||
_make_template(self.env, name='Low Percent', lines=[
|
||||
self._line('debit', 0.001),
|
||||
self._line('credit', 0.001),
|
||||
])
|
||||
|
||||
def test_percent_above_maximum_raises_validation_error(self):
|
||||
"""Req 3.4 — percent > 100.0 raises ValidationError."""
|
||||
with self.assertRaises(ValidationError):
|
||||
_make_template(self.env, name='High Percent', lines=[
|
||||
self._line('debit', 101.0),
|
||||
self._line('credit', 101.0),
|
||||
])
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# TestMoveTemplateWizard
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestMoveTemplateWizard(TransactionCase):
|
||||
"""Validates: Requirement 3.5"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.account_debit = _get_account(self.env, 'asset_current')
|
||||
self.account_credit = _get_account(self.env, 'liability_current')
|
||||
|
||||
# Create a balanced template: 100% debit / 100% credit
|
||||
self.template = self.env['account.move.template'].create({
|
||||
'name': 'Wizard Test Template',
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'account_id': self.account_debit.id,
|
||||
'move_type': 'debit',
|
||||
'percent': 100.0,
|
||||
'line_type': 'product',
|
||||
}),
|
||||
(0, 0, {
|
||||
'account_id': self.account_credit.id,
|
||||
'move_type': 'credit',
|
||||
'percent': 100.0,
|
||||
'line_type': 'product',
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
# Create a source document that uses the mixin (account.move itself
|
||||
# does not use the mixin, so we create a minimal move to act as source)
|
||||
self.source_move = self.env['account.move'].create({
|
||||
'move_type': 'entry',
|
||||
'state': 'draft',
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'account_id': self.account_debit.id,
|
||||
'debit': 0.0,
|
||||
'credit': 0.0,
|
||||
'name': 'Source line',
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
def test_apply_template_creates_draft_move_with_correct_distribution(self):
|
||||
"""Req 3.5 — applying template via wizard creates a draft account.move
|
||||
with correct account distribution."""
|
||||
base_amount = 1000.0
|
||||
|
||||
wizard = self.env['account.move.template.wizard'].create({
|
||||
'res_model': 'account.move',
|
||||
'res_id': self.source_move.id,
|
||||
'template_id': self.template.id,
|
||||
'amount': base_amount,
|
||||
})
|
||||
|
||||
# Trigger onchange to populate draft lines
|
||||
wizard._onchange_compute_draft_lines()
|
||||
|
||||
# Verify draft lines were computed
|
||||
self.assertEqual(len(wizard.draft_line_ids), 2,
|
||||
"Wizard should have 2 draft lines (one debit, one credit)")
|
||||
|
||||
debit_line = wizard.draft_line_ids.filtered(lambda l: l.move_type == 'debit')
|
||||
credit_line = wizard.draft_line_ids.filtered(lambda l: l.move_type == 'credit')
|
||||
|
||||
self.assertAlmostEqual(debit_line.amount, base_amount,
|
||||
msg="Debit line amount should equal base_amount * 100%")
|
||||
self.assertAlmostEqual(credit_line.amount, base_amount,
|
||||
msg="Credit line amount should equal base_amount * 100%")
|
||||
|
||||
# Post the wizard — creates the account.move
|
||||
wizard.action_post()
|
||||
|
||||
# Reload source move and check linked moves
|
||||
self.source_move.invalidate_recordset()
|
||||
linked_moves = self.source_move.move_ids
|
||||
|
||||
self.assertTrue(linked_moves, "A new account.move should be linked to the source")
|
||||
|
||||
new_move = linked_moves[-1]
|
||||
self.assertEqual(new_move.state, 'draft',
|
||||
"Created move should be in draft state")
|
||||
|
||||
move_lines = new_move.line_ids
|
||||
debit_move_line = move_lines.filtered(lambda l: l.debit > 0)
|
||||
credit_move_line = move_lines.filtered(lambda l: l.credit > 0)
|
||||
|
||||
self.assertTrue(debit_move_line, "Move should have a debit line")
|
||||
self.assertTrue(credit_move_line, "Move should have a credit line")
|
||||
|
||||
self.assertAlmostEqual(debit_move_line[0].debit, base_amount,
|
||||
msg="Debit amount on move line should match base_amount")
|
||||
self.assertAlmostEqual(credit_move_line[0].credit, base_amount,
|
||||
msg="Credit amount on move line should match base_amount")
|
||||
|
||||
self.assertEqual(debit_move_line[0].account_id, self.account_debit,
|
||||
"Debit line should use the debit account from template")
|
||||
self.assertEqual(credit_move_line[0].account_id, self.account_credit,
|
||||
"Credit line should use the credit account from template")
|
||||
Reference in New Issue
Block a user