Files
Odoo-Modules/fusion_login_audit/views/res_users_views.xml
gsinghpal 72aa28e6c4 feat(fusion_login_audit): smart button + Login Activity tab on res.users
Adds four x_fc_* fields on res.users: login_audit_ids (One2many),
login_audit_count (compute), last_successful_login (compute, stored),
last_login_ip (compute, stored). action_fc_view_login_audit returns
a window action scoped to the current user. View inheritance adds a
smart button to the button box and a "Login Activity" page to the
notebook, both gated by base.group_system on the inner XML nodes
(NOT on the view record — Odoo 19 forbids that; see CLAUDE.md rule #11).

Tests (2 new, 18 total green):
  test_computed_last_successful_login — uses registry cursor to commit
    the audit row so the stored compute picks it up across the
    TransactionCase boundary.
  test_action_view_login_audit_returns_window_action — smart-button
    action shape + domain scoping.

CLAUDE.md rule #11 added: inherited ir.ui.view records cannot have
groups/group_ids on the record; the gate must be on the inner XML nodes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 09:03:58 -04:00

57 lines
2.7 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_users_form_inherit_login_audit" model="ir.ui.view">
<field name="name">res.users.form.inherit.fusion_login_audit</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/>
<!-- Odoo 19: groups MUST be on the inherited XML nodes (button + page
below), NOT on the ir.ui.view record itself. Setting `group_ids`
on the record raises ParseError "Inherited view cannot have
'groups' defined on the record. Use 'groups' attributes inside
the view definition". -->
<field name="arch" type="xml">
<!-- Smart button -->
<xpath expr="//div[@name='button_box']" position="inside">
<button name="action_fc_view_login_audit"
type="object"
class="oe_stat_button"
icon="fa-key"
groups="base.group_system">
<field name="x_fc_login_audit_count" widget="statinfo"
string="Logins"/>
</button>
</xpath>
<!-- Login Activity tab appended at the end of the notebook -->
<xpath expr="//notebook" position="inside">
<page string="Login Activity"
name="fc_login_activity"
groups="base.group_system">
<group>
<field name="x_fc_last_successful_login" readonly="1"/>
<field name="x_fc_last_login_ip" readonly="1"/>
</group>
<field name="x_fc_login_audit_ids" readonly="1"
context="{'create': False, 'edit': False, 'delete': False}">
<list create="false" edit="false" delete="false"
limit="30" default_order="event_time desc">
<field name="event_time"/>
<field name="result" decoration-success="result=='success'"
decoration-danger="result=='failure'"
widget="badge"/>
<field name="failure_reason"/>
<field name="ip_address"/>
<field name="country_code"/>
<field name="city"/>
<field name="browser"/>
<field name="os"/>
</list>
</field>
</page>
</xpath>
</field>
</record>
</odoo>