Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions spp_change_request_v2/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
"assets": {
"web.assets_backend": [
"spp_change_request_v2/static/src/components/**/*",
"spp_change_request_v2/static/src/js/create_change_request.js",
"spp_change_request_v2/static/src/xml/create_change_request_template.xml",
],
},
"installable": True,
Expand Down
35 changes: 35 additions & 0 deletions spp_change_request_v2/static/src/js/create_change_request.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/** @odoo-module **/

import {ListController} from "@web/views/list/list_controller";
import {onWillStart} from "@odoo/owl";
import {patch} from "@web/core/utils/patch";
import {user} from "@web/core/user";
import {useService} from "@web/core/utils/hooks";

patch(ListController.prototype, {
setup() {
super.setup();
this.actionService = useService("action");
onWillStart(async () => {
const is_admin = await user.hasGroup("spp_security.group_spp_admin");
const is_cr_user = await user.hasGroup(
"spp_change_request_v2.group_cr_user"
);
this.canCreateChangeRequest = is_admin || is_cr_user;
});
},

async loadChangeRequestWizard() {
if (this.model.root.resModel !== "spp.change.request") {
return;
}
await this.actionService.doAction(
"spp_change_request_v2.action_cr_create_wizard",
{
onClose: async () => {
await this.model.root.load();
},
}
);
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">

<t t-inherit="web.ListView" t-inherit-mode="extension">
<xpath expr="//Layout/t[@t-set-slot='control-panel-create-button']" position="replace">
<t t-set-slot="control-panel-create-button">
<t t-if="model.root.resModel == 'spp.change.request'">
<button
t-if="!editedRecord and activeActions.create and props.showButtons and canCreateChangeRequest"
type="button"
class="btn btn-primary o_list_button_add_cr"
accesskey="c"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent keyboard shortcut attribute usage

Low Severity

The "New Request" button uses accesskey="c" while the fallback "New" button on line 22 and all other buttons in the codebase use data-hotkey="c". The accesskey attribute is a native HTML attribute with browser-specific behavior, whereas data-hotkey is Odoo's unified hotkey system that integrates with the framework's keyboard shortcuts dialog and provides consistent cross-platform behavior. This inconsistency means the shortcut will behave differently and won't appear in Odoo's keyboard shortcuts helper.

Fix in Cursor Fix in Web

title="Create a New Change Request"
t-on-click="loadChangeRequestWizard"
>New Request</button>
</t>
<t t-else="">
<button
t-if="!editedRecord and activeActions.create and props.showButtons"
type="button"
class="btn btn-primary o_list_button_add"
data-hotkey="c"
t-on-click="onClickCreate"
data-bounce-button=""
>New</button>
<t t-if="props.showButtons and !env.inDialog" t-call="web.ListView.EditableButtons" />
</t>
</t>
</xpath>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Template extensions overwrite existing program create button

High Severity

The new create_change_request_template.xml extends web.ListView using position="replace" on the same xpath (//Layout/t[@t-set-slot='control-panel-create-button']) that spp_programs/static/src/xml/create_program_template.xml already targets. When both modules are installed, the second extension applied completely overwrites the first — causing one module's custom create button (either "Create Program" or "New Request") to silently fall through to the default "New" button. The same conflict occurs for the web.FormView extension, where both set t-if on the same o_form_button_create button, so only one model's create button gets properly hidden.

Additional Locations (1)

Fix in Cursor Fix in Web

</t>

<t t-inherit="web.FormView" t-inherit-mode="extension">
<xpath expr="//button[hasclass('o_form_button_create')]" position="attributes">
<attribute name="t-if">model.root.resModel != 'spp.change.request'</attribute>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FormView create button loses permission check on t-if override

Medium Severity

The FormView modification uses position="attributes" to set a new t-if condition on the create button, which completely replaces any existing t-if condition. The standard Odoo FormView create button has conditions like activeActions.create to check permissions. The new condition model.root.resModel != 'spp.change.request' only checks the model type, losing the permission checks. This causes the create button to appear in forms even when the user lacks create permission. The ListView modification correctly preserves activeActions.create (line 19), but the FormView modification does not.

Fix in Cursor Fix in Web

</xpath>
</t>

</templates>
2 changes: 1 addition & 1 deletion spp_change_request_v2/strategies/add_member.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def apply(self, change_request):
membership_vals = {
"group": group.id,
"individual": individual.id,
"start_date": fields.Date.today(),
"start_date": fields.Datetime.now(),
}

# Handle relationship/membership type
Expand Down
46 changes: 33 additions & 13 deletions spp_change_request_v2/views/detail_add_member_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,66 @@
<field name="model">spp.cr.detail.add_member</field>
<field name="arch" type="xml">
<form>
<header>
<button
name="action_submit_for_approval"
string="Submit for Approval"
type="object"
class="btn-primary"
invisible="approval_state != 'draft'"
/>
<button
name="action_submit_for_approval"
string="Resubmit for Review"
type="object"
class="btn-primary"
invisible="approval_state != 'revision'"
/>
<field
name="approval_state"
widget="statusbar"
statusbar_visible="draft,pending,approved,applied"
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Statusbar references non-existent "applied" state in approval_state

Low Severity

The statusbar uses approval_state field with statusbar_visible="draft,pending,approved,applied", but approval_state (from spp.approval.mixin) only has values: draft, pending, revision, approved, rejected. The value applied doesn't exist in this field. The main change request view correctly uses display_state which includes applied. This inconsistency means detail forms will never display the "Completed" status in their statusbar, even when the change request has been applied.

Additional Locations (2)

Fix in Cursor Fix in Web

</header>
Comment on lines +9 to +29

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve maintainability and reduce code duplication, consider extracting this common header into a reusable QWeb template. This same header is added to 11 different form views in this PR. By using a template, any future changes to the submission buttons or status bar will only need to be made in one place.

You could define the template in a new or existing XML file (e.g., inside a <templates> tag):

<templates>
    <t t-name="spp_change_request_v2.cr_detail_form_header">
        <header>
            <button
                name="action_submit_for_approval"
                string="Submit for Approval"
                type="object"
                class="btn-primary"
                invisible="approval_state != 'draft'"
            />
            <button
                name="action_submit_for_approval"
                string="Resubmit for Review"
                type="object"
                class="btn-primary"
                invisible="approval_state != 'revision'"
            />
            <field
                name="approval_state"
                widget="statusbar"
                statusbar_visible="draft,pending,approved,applied"
            />
        </header>
    </t>
</templates>

Then, you can replace the <header> block in this file and all other similar detail forms with a single line, as suggested below.

                <t t-call="spp_change_request_v2.cr_detail_form_header"/>

<sheet>
<div class="oe_title">
<h1>Add Member to Group</h1>
</div>

<!-- Target Group -->
<group string="Target Group">
<field name="registrant_id" readonly="1"/>
<field name="change_request_id" invisible="1"/>
<field name="registrant_id" readonly="1" />
<field name="change_request_id" invisible="1" />
</group>

<!-- Member Details -->
<group string="New Member Information">
<group>
<field name="given_name" required="1"/>
<field name="family_name" required="1"/>
<field name="member_name" readonly="1" force_save="1"/>
<field name="given_name" required="1" />
<field name="family_name" required="1" />
<field name="member_name" readonly="1" force_save="1" />
</group>
<group>
<field name="birthdate"/>
<field name="gender_id"/>
<field name="relationship_id"/>
<field name="birthdate" />
<field name="gender_id" />
<field name="relationship_id" />
</group>
</group>

<group string="Contact Information">
<group>
<field name="phone"/>
<field name="id_number"/>
<field name="phone" />
<field name="id_number" />
</group>
</group>

<!-- Result (after apply) -->
<group string="Result" invisible="not created_individual_id">
<field name="created_individual_id"/>
<field name="created_individual_id" />
</group>
</sheet>
<chatter/>
<chatter />
</form>
</field>
</record>

</odoo>
37 changes: 34 additions & 3 deletions spp_change_request_v2/views/detail_change_hoh_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,27 @@
<field name="model">spp.cr.detail.change_hoh</field>
<field name="arch" type="xml">
<form string="Change Head of Household Details">
<header>
<button
name="action_submit_for_approval"
string="Submit for Approval"
type="object"
class="btn-primary"
invisible="approval_state != 'draft'"
/>
<button
name="action_submit_for_approval"
string="Resubmit for Review"
type="object"
class="btn-primary"
invisible="approval_state != 'revision'"
/>
<field
name="approval_state"
widget="statusbar"
statusbar_visible="draft,pending,approved,applied"
/>
</header>
<sheet>
<group>
<group string="Current Head">
Expand All @@ -19,7 +40,11 @@
domain="[('id', 'in', available_individual_ids)]"
required="1"
/>
<field name="new_head_membership_id" invisible="1" force_save="1"/>
<field
name="new_head_membership_id"
invisible="1"
force_save="1"
/>
</group>
</group>
<group>
Expand All @@ -28,11 +53,17 @@
<field name="effective_date" />
</group>
<group string="Previous Head Reassignment">
<field name="previous_head_new_role_id" options="{'no_create': True}" />
<field
name="previous_head_new_role_id"
options="{'no_create': True}"
/>
</group>
</group>
<group string="Additional Information">
<field name="remarks" placeholder="Enter any additional notes..." />
<field
name="remarks"
placeholder="Enter any additional notes..."
/>
</group>
</sheet>
</form>
Expand Down
39 changes: 33 additions & 6 deletions spp_change_request_v2/views/detail_create_group_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,31 @@
<field name="model">spp.cr.detail.create_group</field>
<field name="arch" type="xml">
<form string="Create New Group Details">
<header>
<button
name="action_submit_for_approval"
string="Submit for Approval"
type="object"
class="btn-primary"
invisible="approval_state != 'draft'"
/>
<button
name="action_submit_for_approval"
string="Resubmit for Review"
type="object"
class="btn-primary"
invisible="approval_state != 'revision'"
/>
<field
name="approval_state"
widget="statusbar"
statusbar_visible="draft,pending,approved,applied"
/>
</header>
<sheet>
<group>
<group string="Group Information">
<field name="group_name" required="1"/>
<field name="group_name" required="1" />
<field name="group_type_id" options="{'no_create': True}" />
</group>
<group string="Contact">
Expand All @@ -26,16 +47,22 @@
</group>
<group invisible="create_new_head">
<group string="Select Existing Individual">
<field name="head_individual_id" options="{'no_create': True}" />
<field
name="head_individual_id"
options="{'no_create': True}"
/>
</group>
</group>
<group invisible="not create_new_head">
<group string="New Head Information">
<field name="head_given_name" required="create_new_head"/>
<field name="head_family_name" required="create_new_head"/>
<field name="head_name" readonly="1" force_save="1"/>
<field name="head_given_name" required="create_new_head" />
<field name="head_family_name" required="create_new_head" />
<field name="head_name" readonly="1" force_save="1" />
<field name="head_birthdate" />
<field name="head_gender_id" options="{'no_create': True}" />
<field
name="head_gender_id"
options="{'no_create': True}"
/>
<field name="head_phone" />
</group>
</group>
Expand Down
42 changes: 31 additions & 11 deletions spp_change_request_v2/views/detail_edit_group_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,65 @@
<field name="model">spp.cr.detail.edit_group</field>
<field name="arch" type="xml">
<form>
<header>
<button
name="action_submit_for_approval"
string="Submit for Approval"
type="object"
class="btn-primary"
invisible="approval_state != 'draft'"
/>
<button
name="action_submit_for_approval"
string="Resubmit for Review"
type="object"
class="btn-primary"
invisible="approval_state != 'revision'"
/>
<field
name="approval_state"
widget="statusbar"
statusbar_visible="draft,pending,approved,applied"
/>
</header>
<sheet>
<div class="oe_title">
<h1>Edit Group Information</h1>
</div>

<group string="Group">
<field name="registrant_id" readonly="1"/>
<field name="change_request_id" invisible="1"/>
<field name="registrant_id" readonly="1" />
<field name="change_request_id" invisible="1" />
</group>

<notebook>
<page string="Group Information">
<group>
<group>
<field name="group_name" required="1"/>
<field name="group_name" required="1" />
</group>
<group>
<field name="phone"/>
<field name="email"/>
<field name="phone" />
<field name="email" />
</group>
</group>
</page>
<page string="Address">
<group>
<group>
<field name="address_line1"/>
<field name="address_line2"/>
<field name="address_line1" />
<field name="address_line2" />
</group>
<group>
<field name="city"/>
<field name="postal_code"/>
<field name="city" />
<field name="postal_code" />
</group>
</group>
</page>
</notebook>
</sheet>
<chatter/>
<chatter />
</form>
</field>
</record>

</odoo>
Loading
Loading