customer_cogs_expense_account/tests/test_customer_account_fields.py
2025-11-25 21:43:35 +07:00

252 lines
9.8 KiB
Python

# -*- coding: utf-8 -*-
from odoo.tests import tagged
from odoo.tests.common import TransactionCase
from hypothesis import given, strategies as st, settings
@tagged('post_install', '-at_install')
class TestCustomerAccountFields(TransactionCase):
"""
Property-based tests for customer account fields on res.partner model.
Tests Properties 1, 2, and 3 from the design document.
"""
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
# Use the default company
cls.company = cls.env.company
# Create income accounts for testing
cls.income_account_1 = cls.env['account.account'].create({
'name': 'Test Income Account 1',
'code': 'TINC001',
'account_type': 'income',
})
cls.income_account_2 = cls.env['account.account'].create({
'name': 'Test Income Account 2',
'code': 'TINC002',
'account_type': 'income',
})
# Create expense accounts for testing
cls.expense_account_1 = cls.env['account.account'].create({
'name': 'Test Expense Account 1',
'code': 'TEXP001',
'account_type': 'expense',
})
cls.expense_account_2 = cls.env['account.account'].create({
'name': 'Test Expense Account 2',
'code': 'TEXP002',
'account_type': 'expense',
})
@settings(max_examples=100)
@given(
customer_name=st.text(min_size=1, max_size=50, alphabet=st.characters(blacklist_categories=('Cs', 'Cc'))),
)
def test_property_1_customer_account_field_visibility(self, customer_name):
"""
**Feature: customer-cogs-expense-account, Property 1: Customer account field visibility**
For any customer form view in the Accounting page, the income account and expense account
fields should be visible in the Accounting Entries section below the Account Payable field.
**Validates: Requirements 1.1, 1.2**
"""
# Create a customer
partner = self.env['res.partner'].with_company(self.company).create({
'name': customer_name,
'company_id': self.company.id,
})
# Verify that the fields exist on the model
self.assertIn(
'property_account_income_customer_id',
partner._fields,
"Income account field should exist on res.partner model"
)
self.assertIn(
'property_account_expense_customer_id',
partner._fields,
"Expense account field should exist on res.partner model"
)
# Verify field properties
income_field = partner._fields['property_account_income_customer_id']
expense_field = partner._fields['property_account_expense_customer_id']
# Check that fields are Many2one to account.account
self.assertEqual(
income_field.type,
'many2one',
"Income account field should be Many2one type"
)
self.assertEqual(
income_field.comodel_name,
'account.account',
"Income account field should reference account.account"
)
self.assertEqual(
expense_field.type,
'many2one',
"Expense account field should be Many2one type"
)
self.assertEqual(
expense_field.comodel_name,
'account.account',
"Expense account field should reference account.account"
)
# Verify fields are company-dependent (property fields)
self.assertTrue(
income_field.company_dependent,
"Income account field should be company-dependent"
)
self.assertTrue(
expense_field.company_dependent,
"Expense account field should be company-dependent"
)
# Verify fields are accessible (can read/write)
partner.write({
'property_account_income_customer_id': self.income_account_1.id,
'property_account_expense_customer_id': self.expense_account_1.id,
})
self.assertEqual(
partner.property_account_income_customer_id.id,
self.income_account_1.id,
"Income account field should be readable and writable"
)
self.assertEqual(
partner.property_account_expense_customer_id.id,
self.expense_account_1.id,
"Expense account field should be readable and writable"
)
@settings(max_examples=100)
@given(
customer_name=st.text(min_size=1, max_size=50, alphabet=st.characters(blacklist_categories=('Cs', 'Cc'))),
)
def test_property_2_customer_account_persistence(self, customer_name):
"""
**Feature: customer-cogs-expense-account, Property 2: Customer account persistence**
For any customer record with income or expense accounts set,
saving and reloading the record should preserve the account values.
**Validates: Requirements 1.5, 1.6**
"""
# Create a customer with income and expense accounts
partner = self.env['res.partner'].with_company(self.company).create({
'name': customer_name,
'company_id': self.company.id,
'property_account_income_customer_id': self.income_account_1.id,
'property_account_expense_customer_id': self.expense_account_1.id,
})
# Flush to database
partner.flush_recordset()
# Reload the partner from database
partner_reloaded = self.env['res.partner'].browse(partner.id)
# Verify accounts are preserved
self.assertEqual(
partner_reloaded.property_account_income_customer_id.id,
self.income_account_1.id,
"Income account should be preserved after save and reload"
)
self.assertEqual(
partner_reloaded.property_account_expense_customer_id.id,
self.expense_account_1.id,
"Expense account should be preserved after save and reload"
)
@settings(max_examples=100)
@given(
customer_name=st.text(min_size=1, max_size=50, alphabet=st.characters(blacklist_categories=('Cs', 'Cc'))),
has_income=st.booleans(),
has_expense=st.booleans(),
)
def test_property_3_empty_account_acceptance(self, customer_name, has_income, has_expense):
"""
**Feature: customer-cogs-expense-account, Property 3: Empty account acceptance**
For any customer record, leaving income or expense account fields empty
should not trigger validation errors.
**Validates: Requirements 1.7, 1.8**
"""
# Prepare account values (may be empty)
income_account_id = self.income_account_1.id if has_income else False
expense_account_id = self.expense_account_1.id if has_expense else False
# Create partner with potentially empty accounts
partner = self.env['res.partner'].with_company(self.company).create({
'name': customer_name,
'company_id': self.company.id,
'property_account_income_customer_id': income_account_id,
'property_account_expense_customer_id': expense_account_id,
})
# Verify partner was created successfully
self.assertTrue(partner.id, "Partner should be created even with empty account fields")
# Verify the account values match what was set
if has_income:
self.assertEqual(partner.property_account_income_customer_id.id, self.income_account_1.id)
else:
self.assertFalse(partner.property_account_income_customer_id, "Income account should be empty")
if has_expense:
self.assertEqual(partner.property_account_expense_customer_id.id, self.expense_account_1.id)
else:
self.assertFalse(partner.property_account_expense_customer_id, "Expense account should be empty")
def test_helper_methods(self):
"""
Test the helper methods _get_customer_income_account() and _get_customer_expense_account().
"""
# Create partner with accounts
partner_with_accounts = self.env['res.partner'].with_company(self.company).create({
'name': 'Partner With Accounts',
'company_id': self.company.id,
'property_account_income_customer_id': self.income_account_1.id,
'property_account_expense_customer_id': self.expense_account_1.id,
})
# Test helper methods return correct accounts
self.assertEqual(
partner_with_accounts._get_customer_income_account().id,
self.income_account_1.id,
"Helper method should return income account"
)
self.assertEqual(
partner_with_accounts._get_customer_expense_account().id,
self.expense_account_1.id,
"Helper method should return expense account"
)
# Create partner without accounts
partner_without_accounts = self.env['res.partner'].with_company(self.company).create({
'name': 'Partner Without Accounts',
'company_id': self.company.id,
})
# Test helper methods return False when no accounts set
self.assertFalse(
partner_without_accounts._get_customer_income_account(),
"Helper method should return False when no income account set"
)
self.assertFalse(
partner_without_accounts._get_customer_expense_account(),
"Helper method should return False when no expense account set"
)