diff --git a/fusion_accounting_core/models/__init__.py b/fusion_accounting_core/models/__init__.py index 8e2d2d1b..bcc7bba4 100644 --- a/fusion_accounting_core/models/__init__.py +++ b/fusion_accounting_core/models/__init__.py @@ -1 +1,3 @@ from . import ir_module_module +from . import account_move +from . import account_reconcile_model diff --git a/fusion_accounting_core/models/account_move.py b/fusion_accounting_core/models/account_move.py new file mode 100644 index 00000000..e4dd1c94 --- /dev/null +++ b/fusion_accounting_core/models/account_move.py @@ -0,0 +1,56 @@ +"""Shared-field-ownership declarations for account.move. + +Per the roadmap (Section 3.3), these fields exist in Odoo Enterprise's +account_accountant module. By declaring them here with identical schemas +and identical relation tables, fusion_accounting_core becomes a co-owner. +When Enterprise uninstalls, Odoo's module registry sees fusion still owns +the fields and preserves the columns / relation tables, so the data +(deferred revenue links, signing user, etc.) survives uninstall. + +The fields here have NO compute methods, NO defaults beyond what Enterprise +provides, NO views. They're pure schema-preservation declarations. Any +business logic that operates on these fields lives in Enterprise (when +present) or in a future fusion sub-module that opts to own that behavior. +""" + +from odoo import fields, models + + +class AccountMove(models.Model): + _inherit = "account.move" + + deferred_move_ids = fields.Many2many( + comodel_name='account.move', + relation='account_move_deferred_rel', + column1='original_move_id', + column2='deferred_move_id', + copy=False, + string="Deferred Entries", + ) + deferred_original_move_ids = fields.Many2many( + comodel_name='account.move', + relation='account_move_deferred_rel', + column1='deferred_move_id', + column2='original_move_id', + copy=False, + string="Original Invoices", + ) + deferred_entry_type = fields.Selection( + selection=[ + ('expense', 'Deferred Expense'), + ('revenue', 'Deferred Revenue'), + ], + copy=False, + string="Deferred Entry Type", + ) + + signing_user = fields.Many2one( + comodel_name='res.users', + copy=False, + string="Signing User", + ) + + payment_state_before_switch = fields.Char( + copy=False, + string="Payment State Before Switch", + ) diff --git a/fusion_accounting_core/models/account_reconcile_model.py b/fusion_accounting_core/models/account_reconcile_model.py new file mode 100644 index 00000000..4f35c837 --- /dev/null +++ b/fusion_accounting_core/models/account_reconcile_model.py @@ -0,0 +1,17 @@ +"""Shared-field-ownership for account.reconcile.model. + +Mirrors the single field Enterprise's account_accountant adds to the +Community account.reconcile.model: created_automatically. +""" + +from odoo import fields, models + + +class AccountReconcileModel(models.Model): + _inherit = "account.reconcile.model" + + created_automatically = fields.Boolean( + default=False, + copy=False, + string="Created Automatically", + ) diff --git a/fusion_accounting_core/tests/__init__.py b/fusion_accounting_core/tests/__init__.py index f1a2b5c5..10b90050 100644 --- a/fusion_accounting_core/tests/__init__.py +++ b/fusion_accounting_core/tests/__init__.py @@ -1 +1,2 @@ from . import test_enterprise_detection +from . import test_shared_field_ownership diff --git a/fusion_accounting_core/tests/test_shared_field_ownership.py b/fusion_accounting_core/tests/test_shared_field_ownership.py new file mode 100644 index 00000000..82fb24e1 --- /dev/null +++ b/fusion_accounting_core/tests/test_shared_field_ownership.py @@ -0,0 +1,32 @@ +from odoo.tests.common import TransactionCase, tagged + + +@tagged('post_install', '-at_install') +class TestSharedFieldOwnership(TransactionCase): + """Verify fusion_accounting_core declares the Enterprise extension fields + on account.move and account.reconcile.model, so they survive Enterprise uninstall.""" + + def test_account_move_deferred_fields_exist(self): + Move = self.env['account.move'] + for fname in ('deferred_move_ids', 'deferred_original_move_ids', 'deferred_entry_type'): + self.assertIn(fname, Move._fields, f"{fname!r} must exist on account.move") + + def test_account_move_signing_user_exists(self): + Move = self.env['account.move'] + self.assertIn('signing_user', Move._fields) + + def test_account_move_payment_state_before_switch_exists(self): + Move = self.env['account.move'] + self.assertIn('payment_state_before_switch', Move._fields) + + def test_account_reconcile_model_created_automatically_exists(self): + Model = self.env['account.reconcile.model'] + self.assertIn('created_automatically', Model._fields) + + def test_deferred_relation_table_name_matches_enterprise(self): + """The shared M2M relation table must be named identically to Enterprise's + so dual ownership works (Enterprise drops field => fusion preserves table).""" + f = self.env['account.move']._fields['deferred_move_ids'] + self.assertEqual(f.relation, 'account_move_deferred_rel') + self.assertEqual(f.column1, 'original_move_id') + self.assertEqual(f.column2, 'deferred_move_id')