Phase G of permissions overhaul.
G2: sale.order.action_confirm now requires group_fp_sales_manager
(spec Section 2.B). Sales Reps can save drafts but cannot move SOs
to 'sale' state. UserError raised with clear message if attempted.
G3: Fixed audit-finding-11 typo bug in 2 files. The original code
checked has_group('fusion_plating.group_fusion_plating_administrator'),
an xmlid that has NEVER existed - so the gate always returned False
and only the Manager-side check actually fired. Fixed both:
- fusion_plating_invoicing/models/res_partner.py:34
- fusion_plating_configurator/wizard/fp_direct_order_wizard.py:467
Both now check has_group('fusion_plating.group_fp_manager') which
transitively includes Owner via implied_ids.
G4: Swept all Python has_group() calls to reference new group xmlids.
Backward-compat keeps old refs working today (Phase A's implied_ids),
but the sweep ensures correctness after the 30-day rollback window
deletes old groups. Replacements:
group_fusion_plating_operator -> group_fp_technician
group_fusion_plating_supervisor -> group_fp_shop_manager_v2
group_fusion_plating_manager -> group_fp_manager
group_fusion_plating_admin -> group_fp_owner
group_fusion_plating_cgp_officer -> group_fp_quality_manager
group_fusion_plating_cgp_designated_official -> group_fp_owner
group_fp_estimator -> group_fp_sales_rep
group_fp_accounting -> group_fp_manager
group_fp_receiving -> group_fp_shop_manager_v2
group_fp_shop_manager (legacy) -> group_fp_manager
G1: test_sales_manager_gate.py covers the new confirm gate (SR
blocked, SMg allowed, Manager allowed via diamond implication).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
47 lines
1.9 KiB
Python
47 lines
1.9 KiB
Python
from odoo.tests.common import TransactionCase, tagged
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
@tagged('-at_install', 'post_install', 'fp_perms')
|
|
class TestSalesManagerGate(TransactionCase):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
Users = self.env['res.users'].with_context(no_reset_password=True)
|
|
self.u_sr = Users.create({
|
|
'login': 'gate_sr', 'name': 'Gate SR',
|
|
'email': 'gate_sr@example.com',
|
|
'groups_id': [(6, 0, [self.env.ref('fusion_plating.group_fp_sales_rep').id])],
|
|
})
|
|
self.u_smg = Users.create({
|
|
'login': 'gate_smg', 'name': 'Gate SMg',
|
|
'email': 'gate_smg@example.com',
|
|
'groups_id': [(6, 0, [self.env.ref('fusion_plating.group_fp_sales_manager').id])],
|
|
})
|
|
partner = self.env['res.partner'].create({'name': 'Gate Test Customer'})
|
|
product = self.env['product.product'].create({'name': 'Gate Test Product'})
|
|
self.so = self.env['sale.order'].create({
|
|
'partner_id': partner.id,
|
|
'order_line': [(0, 0, {
|
|
'product_id': product.id, 'product_uom_qty': 1, 'price_unit': 100,
|
|
})],
|
|
})
|
|
|
|
def test_sales_rep_cannot_confirm(self):
|
|
with self.assertRaises(UserError):
|
|
self.so.with_user(self.u_sr).action_confirm()
|
|
|
|
def test_sales_manager_can_confirm(self):
|
|
self.so.with_user(self.u_smg).action_confirm()
|
|
self.assertEqual(self.so.state, 'sale')
|
|
|
|
def test_manager_can_confirm(self):
|
|
# Manager implies Sales Manager via the diamond — should also be able to confirm
|
|
u_mgr = self.env['res.users'].with_context(no_reset_password=True).create({
|
|
'login': 'gate_mgr', 'name': 'Gate Mgr',
|
|
'email': 'gate_mgr@example.com',
|
|
'groups_id': [(6, 0, [self.env.ref('fusion_plating.group_fp_manager').id])],
|
|
})
|
|
self.so.with_user(u_mgr).action_confirm()
|
|
self.assertEqual(self.so.state, 'sale')
|