diff --git a/models/ows_models.py b/models/ows_models.py index 6e5a81f..93613a3 100644 --- a/models/ows_models.py +++ b/models/ows_models.py @@ -14,35 +14,36 @@ class ResPartner(models.Model): ows_user_id = fields.One2many('ows.user', 'partner_id', string="OWS Benutzerdaten") - # ✳️ Zugriff auf Felder aus ows.user per compute + inverse (statt related) + # Alte Felder (weiterhin sichtbar für externe Programme) birthday = fields.Date( string="Geburtstag", compute='_compute_ows_user_fields', - inverse='_inverse_ows_user_fields', + inverse='_inverse_birthday', store=False ) - rfid_card = fields.Text( string="RFID Card ID", compute='_compute_ows_user_fields', - inverse='_inverse_ows_user_fields', + inverse='_inverse_rfid_card', store=False ) - security_briefing = fields.Boolean( string="Haftungsausschluss", compute='_compute_ows_user_fields', - inverse='_inverse_ows_user_fields', + inverse='_inverse_security_briefing', store=False ) - security_id = fields.Text( string="Haftungsausschluss ID", compute='_compute_ows_user_fields', - inverse='_inverse_ows_user_fields', + inverse='_inverse_security_id', store=False ) - + # Neue direkte vvow_* Felder + vvow_birthday = fields.Date(string="Geburtstag (vvow)") + vvow_rfid_card = fields.Text(string="RFID Card ID (vvow)") + vvow_security_briefing = fields.Boolean(string="Haftungsausschluss (vvow)") + vvow_security_id = fields.Text(string="Haftungsausschluss ID (vvow)") @api.depends('ows_user_id') def _compute_ows_user_fields(self): @@ -53,28 +54,76 @@ class ResPartner(models.Model): partner.security_briefing = user.security_briefing if user else False partner.security_id = user.security_id if user else False - def _inverse_ows_user_fields(self): + def _inverse_birthday(self): for partner in self: user = partner.ows_user_id[0] if partner.ows_user_id else False if user: user.birthday = partner.birthday + + def _inverse_rfid_card(self): + for partner in self: + user = partner.ows_user_id[0] if partner.ows_user_id else False + if user: user.rfid_card = partner.rfid_card + + def _inverse_security_briefing(self): + for partner in self: + user = partner.ows_user_id[0] if partner.ows_user_id else False + if user: user.security_briefing = partner.security_briefing + + def _inverse_security_id(self): + for partner in self: + user = partner.ows_user_id[0] if partner.ows_user_id else False + if user: user.security_id = partner.security_id + @api.model_create_multi def create(self, vals_list): partners = super().create(vals_list) for vals, partner in zip(vals_list, partners): self.env['ows.user'].create({ 'partner_id': partner.id, - 'birthday': vals.get('birthday'), - 'rfid_card': vals.get('rfid_card'), - 'security_briefing': vals.get('security_briefing'), - 'security_id': vals.get('security_id'), + 'birthday': vals.get('birthday') or vals.get('vvow_birthday'), + 'rfid_card': vals.get('rfid_card') or vals.get('vvow_rfid_card'), + 'security_briefing': vals.get('security_briefing') or vals.get('vvow_security_briefing'), + 'security_id': vals.get('security_id') or vals.get('vvow_security_id'), }) return partners + def write(self, vals): + res = super().write(vals) + for partner in self: + user = partner.ows_user_id[0] if partner.ows_user_id else False + if not user: + continue + + # Synchronisation alt -> user + if 'birthday' in vals: + user.birthday = vals['birthday'] + if 'rfid_card' in vals: + user.rfid_card = vals['rfid_card'] + if 'security_briefing' in vals: + user.security_briefing = vals['security_briefing'] + if 'security_id' in vals: + user.security_id = vals['security_id'] + + # Synchronisation vvow_* -> user + alt + if 'vvow_birthday' in vals: + user.birthday = vals['vvow_birthday'] + partner.birthday = vals['vvow_birthday'] + if 'vvow_rfid_card' in vals: + user.rfid_card = vals['vvow_rfid_card'] + partner.rfid_card = vals['vvow_rfid_card'] + if 'vvow_security_briefing' in vals: + user.security_briefing = vals['vvow_security_briefing'] + partner.security_briefing = vals['vvow_security_briefing'] + if 'vvow_security_id' in vals: + user.security_id = vals['vvow_security_id'] + partner.security_id = vals['vvow_security_id'] + return res + machine_access_ids = fields.One2many( 'ows.machine.access', 'partner_id', @@ -87,6 +136,7 @@ class ResPartner(models.Model): sanitize=False ) + @api.depends('machine_access_ids') def _compute_machine_access_html(self): areas = self.env['ows.machine.area'].search([], order="name") diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..d57d215 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +from . import test_res_partner diff --git a/tests/test_res_partner.py b/tests/test_res_partner.py new file mode 100644 index 0000000..6c88da7 --- /dev/null +++ b/tests/test_res_partner.py @@ -0,0 +1,138 @@ +## Testausführung +# odoo-bin -d deine_testdatenbank --test-enable --init open_workshop +## oder: +# /opt/odoo/odoo/odoo-bin -d hobbyhimmel --test-enable --test-tags /test_res_partner.py --stop-after-init --http-port=8070 --log-level=debug +# /opt/odoo/odoo/odoo-bin -d hobbyhimmel --test-enable --stop-after-init --test-tags open_workshop --log-level=debug --update open_workshop --http-port=8070 + +from odoo.tests.common import TransactionCase +from odoo.tests import tagged +import logging +_logger = logging.getLogger(__name__) + +@tagged('post_install', 'open_workshop', 'vvow') +class TestResPartnerVvowFields(TransactionCase): + + def setUp(self): + super().setUp() + self.partner_model = self.env['res.partner'] + self.user_model = self.env['ows.user'] + + def test_create_with_vvow_fields_creates_user(self): + partner = self.partner_model.create({ + 'name': 'Max Test', + 'vvow_birthday': '1990-01-01', + 'vvow_rfid_card': 'ABC12345', + 'vvow_security_briefing': True, + 'vvow_security_id': 'HB-001', + }) + + user = partner.ows_user_id + self.assertEqual(len(user), 1) + self.assertEqual(user.birthday.isoformat(), '1990-01-01') + self.assertEqual(user.rfid_card, 'ABC12345') + self.assertTrue(user.security_briefing) + self.assertEqual(user.security_id, 'HB-001') + + # Check that Fassade korrekt ausgerechnet ist + self.assertEqual(partner.birthday.isoformat(), '1990-01-01') + self.assertEqual(partner.rfid_card, 'ABC12345') + self.assertTrue(partner.security_briefing) + self.assertEqual(partner.security_id, 'HB-001') + + def test_write_vvow_fields_updates_user_and_fassade(self): + partner = self.partner_model.create({'name': 'Update Tester'}) + user = partner.ows_user_id + + partner.write({ + 'vvow_birthday': '1985-12-31', + 'vvow_rfid_card': 'NEW123', + 'vvow_security_briefing': False, + 'vvow_security_id': 'NEU-SEC', + }) + + self.assertEqual(user.birthday.isoformat(), '1985-12-31') + self.assertEqual(user.rfid_card, 'NEW123') + self.assertFalse(user.security_briefing) + self.assertEqual(user.security_id, 'NEU-SEC') + + # Sicherstellen, dass die berechneten Felder auch aktualisiert wurden + self.assertEqual(partner.birthday.isoformat(), '1985-12-31') + self.assertEqual(partner.rfid_card, 'NEW123') + self.assertFalse(partner.security_briefing) + self.assertEqual(partner.security_id, 'NEU-SEC') + + def test_change_fassade_field_updates_user(self): + partner = self.partner_model.create({ + 'name': 'Change Fassade', + 'vvow_security_briefing': True, + }) + user = partner.ows_user_id + + # Ändere security_briefing (die Fassade) + partner.write({'security_briefing': False}) + + # Muss sich im ows.user widerspiegeln + self.assertFalse(user.security_briefing) + + # vvow-Sync: vvow bleibt wie gehabt (wird nicht überschrieben) + self.assertTrue(partner.vvow_security_briefing) + + def test_change_and_read_consistency(self): + partner = self.partner_model.create({ + 'name': 'Read-Change-Test', + 'vvow_security_briefing': True, + }) + user = partner.ows_user_id + + # Ändere security_briefing über Fassade + partner.write({'security_briefing': False}) + self.assertFalse(user.security_briefing) + self.assertFalse(partner.security_briefing) + + # Lies vvow_* separat aus – sollte weiterhin den ursprünglichen vvow-Wert zeigen + self.assertTrue(partner.vvow_security_briefing) + + # Ändere vvow_* erneut – jetzt sollte alles wieder gesetzt werden + partner.write({'vvow_security_briefing': True}) + self.assertTrue(partner.security_briefing) + self.assertTrue(user.security_briefing) + + + def test_inverse_does_not_clear_unrelated_fields(self): + _logger.info("🔍 Starte Test für Feldsynchronisation") + # Schritt 1: Partner mit vvow_* Feldern erzeugen → soll automatisch ows.user erzeugen + partner = self.partner_model.create({ + 'name': 'Unabhängigkeits-Test', + 'vvow_birthday': '1995-05-05', + 'vvow_rfid_card': 'ABC999', + 'vvow_security_briefing': True, + 'vvow_security_id': 'SEC-XYZ', + }) + _logger.debug("✅ Partner angelegt: %s", partner.name) + + # Validierung: es wurde ein ows.user erzeugt + self.assertEqual(len(partner.ows_user_id), 1, "Kein ows.user erzeugt") + user = partner.ows_user_id + _logger.debug("👤 ows.user: %s", user.read(['birthday', 'security_id'])) + + # Sicherstellen, dass alle Felder korrekt gesetzt wurden + self.assertEqual(user.birthday.isoformat(), '1995-05-05') + self.assertEqual(user.rfid_card, 'ABC999') + self.assertTrue(user.security_briefing) + self.assertEqual(user.security_id, 'SEC-XYZ') + + # Schritt 2: Nur ein Feld über die Fassade ändern (inverse wird getriggert) + partner.write({'security_briefing': False}) + _logger.info("✏️ security_briefing auf False gesetzt") + + # Schritt 3: DB-Cache leeren + user.flush() + user.invalidate_cache() + + _logger.debug("📦 user nach write: %s", user.read(['birthday', 'security_id'])) + + # Schritt 4: Sicherstellen, dass die anderen Felder NICHT gelöscht wurden + self.assertEqual(user.birthday.isoformat(), '1995-05-05') + self.assertEqual(user.rfid_card, 'ABC999') + self.assertEqual(user.security_id, 'SEC-XYZ') + self.assertFalse(user.security_briefing)