Two related issues that hid the Fusion Repairs app from the Apps menu
for admin users:
1. Custom security groups don't auto-include admin
The Repairs User / Dispatcher / Manager groups are new custom groups.
Having base.group_user or base.group_system on its own does NOT grant
membership in custom child groups - implied chains only flow one way
(child -> parent). Admin therefore had no Repairs groups, so the
top-level "Fusion Repairs" menu (gated on group_fusion_repairs_user)
was hidden from them.
Fix: extend base.group_system with implied_ids that include
group_fusion_repairs_manager. Manager already implies Dispatcher
implies User, so admin (= base.group_system) now automatically gets
the whole chain on install / upgrade with no manual user editing.
Verified via odoo-shell:
admin.has_group('fusion_repairs.group_fusion_repairs_user') == True
admin.has_group('fusion_repairs.group_fusion_repairs_dispatcher') == True
admin.has_group('fusion_repairs.group_fusion_repairs_manager') == True
menu_fusion_repairs_root._filter_visible_menus() == ir.ui.menu(2735,)
2. Missing static/description/icon.png
The manifest referenced fusion_repairs,static/description/icon.png
via web_icon on the top-level menu but the file did not exist. Odoo
handles missing icons gracefully but the apps list ends up rendering
without a tile graphic. Copied fusion_tasks/static/description/icon.png
as a placeholder; replace with a custom asset whenever desired.
Verified: /fusion_repairs/static/description/icon.png returns
HTTP 200 with 43989 bytes after restart.
Bumped manifest version to 19.0.1.0.1 to bust the asset bundle hash so
clients pick up the new icon without a manual cache clear.
Co-authored-by: Cursor <cursoragent@cursor.com>
100 lines
5.6 KiB
XML
100 lines
5.6 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
<!-- ==================================================================== -->
|
|
<!-- MODULE CATEGORY -->
|
|
<!-- ==================================================================== -->
|
|
<record id="module_category_fusion_repairs" model="ir.module.category">
|
|
<field name="name">Fusion Repairs</field>
|
|
<field name="sequence">47</field>
|
|
</record>
|
|
|
|
<!-- ==================================================================== -->
|
|
<!-- FUSION REPAIRS PRIVILEGE (Odoo 19 res.groups.privilege pattern) -->
|
|
<!-- ==================================================================== -->
|
|
<record id="res_groups_privilege_fusion_repairs" model="res.groups.privilege">
|
|
<field name="name">Fusion Repairs</field>
|
|
<field name="sequence">47</field>
|
|
<field name="category_id" ref="module_category_fusion_repairs"/>
|
|
</record>
|
|
|
|
<!-- ==================================================================== -->
|
|
<!-- GROUPS -->
|
|
<!-- ==================================================================== -->
|
|
<record id="group_fusion_repairs_user" model="res.groups">
|
|
<field name="name">Repairs: User (CS Intake)</field>
|
|
<field name="privilege_id" ref="res_groups_privilege_fusion_repairs"/>
|
|
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
|
<field name="comment">CS / front-office staff who take repair intake calls and view repairs.</field>
|
|
</record>
|
|
|
|
<record id="group_fusion_repairs_dispatcher" model="res.groups">
|
|
<field name="name">Repairs: Dispatcher</field>
|
|
<field name="privilege_id" ref="res_groups_privilege_fusion_repairs"/>
|
|
<field name="implied_ids" eval="[(4, ref('group_fusion_repairs_user'))]"/>
|
|
<field name="comment">Assigns technicians to repairs, reschedules visits, manages parts pre-pull picklists.</field>
|
|
</record>
|
|
|
|
<record id="group_fusion_repairs_manager" model="res.groups">
|
|
<field name="name">Repairs: Manager</field>
|
|
<field name="privilege_id" ref="res_groups_privilege_fusion_repairs"/>
|
|
<field name="implied_ids" eval="[(4, ref('group_fusion_repairs_dispatcher'))]"/>
|
|
<field name="comment">Configures intake templates, pricing, maintenance contracts, on-call rotation, variance overrides.</field>
|
|
</record>
|
|
|
|
<!-- =====================================================================
|
|
Admin auto-membership: anyone with base.group_system (Settings /
|
|
Administration) automatically gets Repairs Manager, which implies
|
|
Dispatcher and User. So admin users see the Fusion Repairs app
|
|
and have full access without needing to be added manually.
|
|
===================================================================== -->
|
|
<record id="base.group_system" model="res.groups">
|
|
<field name="implied_ids" eval="[(4, ref('fusion_repairs.group_fusion_repairs_manager'))]"/>
|
|
</record>
|
|
|
|
<!-- ==================================================================== -->
|
|
<!-- RECORD RULES -->
|
|
<!-- ==================================================================== -->
|
|
|
|
<!-- Multi-company isolation on repair.order -->
|
|
<record id="rule_repair_order_company" model="ir.rule">
|
|
<field name="name">Repair Order: Multi-Company</field>
|
|
<field name="model_id" ref="repair.model_repair_order"/>
|
|
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
|
<field name="global" eval="True"/>
|
|
</record>
|
|
|
|
<!-- Field technicians (from fusion_tasks) see only repairs they're assigned to as technician on a linked task.
|
|
Uses STORED fields (technician_id + additional_technician_ids) - not the computed all_technician_ids. -->
|
|
<record id="rule_repair_order_technician_own" model="ir.rule">
|
|
<field name="name">Repair Order: Technician sees own repairs</field>
|
|
<field name="model_id" ref="repair.model_repair_order"/>
|
|
<field name="domain_force">['|', ('x_fc_technician_task_ids.technician_id', '=', user.id), ('x_fc_technician_task_ids.additional_technician_ids', 'in', [user.id])]</field>
|
|
<field name="groups" eval="[(4, ref('fusion_tasks.group_field_technician'))]"/>
|
|
<field name="perm_read" eval="True"/>
|
|
<field name="perm_write" eval="True"/>
|
|
<field name="perm_create" eval="False"/>
|
|
<field name="perm_unlink" eval="False"/>
|
|
</record>
|
|
|
|
<!-- Intake answer access scoped to repair access -->
|
|
<record id="rule_repair_intake_answer_company" model="ir.rule">
|
|
<field name="name">Repair Intake Answer: Multi-Company</field>
|
|
<field name="model_id" ref="model_fusion_repair_intake_answer"/>
|
|
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
|
<field name="global" eval="True"/>
|
|
</record>
|
|
|
|
<!-- Sales Rep Portal: sees only repair orders they submitted -->
|
|
<record id="rule_repair_order_sales_rep_portal" model="ir.rule">
|
|
<field name="name">Repair Order: Sales Rep Portal - Own Repairs</field>
|
|
<field name="model_id" ref="repair.model_repair_order"/>
|
|
<field name="domain_force">[('x_fc_intake_user_id', '=', user.id)]</field>
|
|
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
|
<field name="perm_read" eval="True"/>
|
|
<field name="perm_write" eval="False"/>
|
|
<field name="perm_create" eval="False"/>
|
|
<field name="perm_unlink" eval="False"/>
|
|
</record>
|
|
|
|
</odoo>
|