feat(plating-quality): split Manager vs Quality Manager permissions
Phase C of permissions overhaul (spec Section 2.C).
Manager keeps reactive Quality (NCR/Hold/Check/Cert/RMA — already gated
via Phase B sweep). QM gains exclusive write/create/unlink on strategic
Quality records:
- fusion.plating.capa: Manager → read-only (1,0,0,0); QM → full
- fusion.plating.audit: same split (if model present)
- fp.approved.vendor.list: same split (if model present)
- fusion.plating.customer.spec: same split
- Doc Control models: same split
Plus FAIR/Nadcap cert restriction via two new ir.rule records on
fp.certificate:
- Manager: write/create/unlink on certs where cert_type NOT in
('fair', 'nadcap')
- QM: write/create/unlink on all certs (overrides via OR within group)
- Read access unchanged for both (perm_read=False on the rules)
Tests in fusion_plating/tests/test_quality_split.py verify each side
of the split. Models that may not exist on all DBs (audit, AVL) use
skipTest gracefully.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
{
|
||||
'name': 'Fusion Plating',
|
||||
'version': '19.0.21.0.1',
|
||||
'version': '19.0.21.0.2',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': 'Core plating / metal finishing ERP: facilities, processes, tanks, baths, jobs, operators.',
|
||||
'description': """
|
||||
|
||||
@@ -5,3 +5,4 @@ from . import test_fp_job_step_state_machine
|
||||
from . import test_simple_recipe_flatten
|
||||
from . import test_role_groups
|
||||
from . import test_acl_migration
|
||||
from . import test_quality_split
|
||||
|
||||
90
fusion_plating/fusion_plating/tests/test_quality_split.py
Normal file
90
fusion_plating/fusion_plating/tests/test_quality_split.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from odoo.tests.common import TransactionCase, tagged
|
||||
from odoo.exceptions import AccessError
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install', 'fp_perms')
|
||||
class TestQualitySplit(TransactionCase):
|
||||
"""Section 2.C of spec: Manager handles reactive Quality;
|
||||
QM exclusively owns CAPA close, Audit, AVL, Customer Spec, FAIR/Nadcap signing."""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
Users = self.env['res.users'].with_context(no_reset_password=True)
|
||||
self.u_mgr = Users.create({
|
||||
'login': 'qsplit_mgr', 'name': 'QSplit Mgr',
|
||||
'email': 'qsplit_mgr@example.com',
|
||||
'groups_id': [(6, 0, [self.env.ref('fusion_plating.group_fp_manager').id])],
|
||||
})
|
||||
self.u_qm = Users.create({
|
||||
'login': 'qsplit_qm', 'name': 'QSplit QM',
|
||||
'email': 'qsplit_qm@example.com',
|
||||
'groups_id': [(6, 0, [self.env.ref('fusion_plating.group_fp_quality_manager').id])],
|
||||
})
|
||||
|
||||
# CAPA: Manager read-only, QM full
|
||||
def test_manager_can_read_capa(self):
|
||||
self.env['fusion.plating.capa'].with_user(self.u_mgr).check_access_rights('read')
|
||||
|
||||
def test_manager_cannot_write_capa(self):
|
||||
with self.assertRaises(AccessError):
|
||||
self.env['fusion.plating.capa'].with_user(self.u_mgr).check_access_rights('write')
|
||||
|
||||
def test_manager_cannot_create_capa(self):
|
||||
with self.assertRaises(AccessError):
|
||||
self.env['fusion.plating.capa'].with_user(self.u_mgr).check_access_rights('create')
|
||||
|
||||
def test_qm_can_write_capa(self):
|
||||
self.env['fusion.plating.capa'].with_user(self.u_qm).check_access_rights('write')
|
||||
|
||||
# Audit: Manager read-only, QM full
|
||||
def test_manager_can_read_audit(self):
|
||||
Audit = self.env.get('fusion.plating.audit')
|
||||
if not Audit:
|
||||
self.skipTest('fusion.plating.audit model not available')
|
||||
Audit.with_user(self.u_mgr).check_access_rights('read')
|
||||
|
||||
def test_manager_cannot_write_audit(self):
|
||||
Audit = self.env.get('fusion.plating.audit')
|
||||
if not Audit:
|
||||
self.skipTest('fusion.plating.audit model not available')
|
||||
with self.assertRaises(AccessError):
|
||||
Audit.with_user(self.u_mgr).check_access_rights('write')
|
||||
|
||||
def test_qm_can_write_audit(self):
|
||||
Audit = self.env.get('fusion.plating.audit')
|
||||
if not Audit:
|
||||
self.skipTest('fusion.plating.audit model not available')
|
||||
Audit.with_user(self.u_qm).check_access_rights('write')
|
||||
|
||||
# NCR: Manager full
|
||||
def test_manager_can_create_ncr(self):
|
||||
self.env['fusion.plating.ncr'].with_user(self.u_mgr).check_access_rights('create')
|
||||
|
||||
def test_manager_can_write_ncr(self):
|
||||
self.env['fusion.plating.ncr'].with_user(self.u_mgr).check_access_rights('write')
|
||||
|
||||
# Hold: Manager full
|
||||
def test_manager_can_create_hold(self):
|
||||
self.env['fusion.plating.quality.hold'].with_user(self.u_mgr).check_access_rights('create')
|
||||
|
||||
# AVL: Manager read-only, QM full
|
||||
def test_manager_can_read_avl(self):
|
||||
Avl = self.env.get('fp.approved.vendor.list')
|
||||
if not Avl:
|
||||
self.skipTest('fp.approved.vendor.list model not available')
|
||||
Avl.with_user(self.u_mgr).check_access_rights('read')
|
||||
|
||||
def test_manager_cannot_write_avl(self):
|
||||
Avl = self.env.get('fp.approved.vendor.list')
|
||||
if not Avl:
|
||||
self.skipTest('fp.approved.vendor.list model not available')
|
||||
with self.assertRaises(AccessError):
|
||||
Avl.with_user(self.u_mgr).check_access_rights('write')
|
||||
|
||||
# Customer Spec: Manager read-only, QM full
|
||||
def test_manager_can_read_customer_spec(self):
|
||||
self.env['fusion.plating.customer.spec'].with_user(self.u_mgr).check_access_rights('read')
|
||||
|
||||
def test_manager_cannot_write_customer_spec(self):
|
||||
with self.assertRaises(AccessError):
|
||||
self.env['fusion.plating.customer.spec'].with_user(self.u_mgr).check_access_rights('write')
|
||||
Reference in New Issue
Block a user