This commit is contained in:
gsinghpal
2026-04-02 23:40:34 -04:00
parent 1c560c6df2
commit 4cd7357aa0
73 changed files with 7076 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form_fusion_accounting" model="ir.ui.view">
<field name="name">res.config.settings.view.form.fusion.accounting</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="account.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//app[@name='account']" position="inside">
<block title="Fusion AI" name="fusion_ai_settings">
<setting string="AI Provider" help="Select the AI provider for Fusion Accounting.">
<field name="fusion_ai_provider" widget="radio"/>
</setting>
<setting string="Anthropic API Key" help="API key for Anthropic Claude. Leave blank if using Fusion API module.">
<field name="fusion_anthropic_api_key" password="True"/>
</setting>
<setting string="OpenAI API Key" help="API key for OpenAI GPT. Leave blank if using Fusion API module.">
<field name="fusion_openai_api_key" password="True"/>
</setting>
<setting string="Claude Model" help="The Anthropic Claude model to use for conversations.">
<field name="fusion_claude_model"/>
</setting>
<setting string="OpenAI Model" help="The OpenAI model to use for conversations.">
<field name="fusion_openai_model"/>
</setting>
</block>
<block title="Fusion AI Behaviour" name="fusion_ai_behaviour">
<setting string="Tier 3 Promotion Threshold" help="Accuracy threshold (0.0 - 1.0) for promoting Tier 3 tools to auto-approved.">
<field name="fusion_tier3_threshold"/>
</setting>
<setting string="Tier 3 Minimum Sample Size" help="Minimum decisions before promotion is considered.">
<field name="fusion_tier3_min_sample"/>
</setting>
<setting string="Audit Scan Frequency" help="How often the automated audit scan runs.">
<field name="fusion_audit_cron_frequency"/>
</setting>
<setting string="Match History in Prompt" help="Number of recent match history records to include in AI prompt context.">
<field name="fusion_history_in_prompt"/>
</setting>
<setting string="Max Tool Calls Per Turn" help="Maximum number of tool calls the AI can make in a single conversation turn.">
<field name="fusion_max_tool_calls"/>
</setting>
<setting string="Post-Action Audit Hook" help="Run audit checks automatically after journal entries are posted.">
<field name="fusion_enable_post_audit"/>
</setting>
</block>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Client Action for OWL Dashboard -->
<record id="action_fusion_dashboard" model="ir.actions.client">
<field name="name">Fusion AI Dashboard</field>
<field name="tag">fusion_accounting.dashboard</field>
</record>
</odoo>

View File

@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_fusion_history_list" model="ir.ui.view">
<field name="name">fusion.accounting.match.history.list</field>
<field name="model">fusion.accounting.match.history</field>
<field name="arch" type="xml">
<list string="Match History">
<field name="proposed_at"/>
<field name="tool_name"/>
<field name="decision" widget="badge"
decoration-success="decision == 'approved'"
decoration-danger="decision == 'rejected'"
decoration-warning="decision == 'pending'"
decoration-info="decision == 'auto'"/>
<field name="ai_confidence" widget="progressbar"/>
<field name="amount"/>
<field name="partner_id"/>
<field name="decided_by"/>
<field name="decided_at"/>
</list>
</field>
</record>
<record id="view_fusion_history_form" model="ir.ui.view">
<field name="name">fusion.accounting.match.history.form</field>
<field name="model">fusion.accounting.match.history</field>
<field name="arch" type="xml">
<form string="Match History">
<header>
<button name="action_approve" string="Approve" type="object"
class="btn-primary" invisible="decision != 'pending'"
groups="fusion_accounting.group_fusion_accounting_manager"/>
<button name="action_reject" string="Reject" type="object"
class="btn-danger" invisible="decision != 'pending'"
groups="fusion_accounting.group_fusion_accounting_manager"/>
</header>
<sheet>
<group>
<group>
<field name="tool_name"/>
<field name="decision"/>
<field name="ai_confidence"/>
<field name="amount"/>
<field name="partner_id"/>
</group>
<group>
<field name="session_id"/>
<field name="rule_id"/>
<field name="proposed_at"/>
<field name="decided_at"/>
<field name="decided_by"/>
</group>
</group>
<group string="AI Details">
<field name="ai_reasoning"/>
<field name="tool_params"/>
<field name="tool_result"/>
</group>
<group string="Correction" invisible="decision != 'rejected'">
<field name="rejection_reason"/>
<field name="correct_action"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_fusion_history_search" model="ir.ui.view">
<field name="name">fusion.accounting.match.history.search</field>
<field name="model">fusion.accounting.match.history</field>
<field name="arch" type="xml">
<search>
<field name="tool_name"/>
<field name="partner_id"/>
<filter name="pending" string="Pending" domain="[('decision', '=', 'pending')]"/>
<filter name="approved" string="Approved" domain="[('decision', '=', 'approved')]"/>
<filter name="rejected" string="Rejected" domain="[('decision', '=', 'rejected')]"/>
<separator/>
<group>
<filter name="group_tool" string="Tool" domain="[]" context="{'group_by': 'tool_name'}"/>
<filter name="group_decision" string="Decision" domain="[]" context="{'group_by': 'decision'}"/>
</group>
</search>
</field>
</record>
<record id="action_fusion_history" model="ir.actions.act_window">
<field name="name">Match History</field>
<field name="res_model">fusion.accounting.match.history</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fusion_history_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">No match history yet</p>
<p>AI tool calls and their outcomes will appear here.</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Root menu under Accounting (account_accountant uses accountant.menu_accounting) -->
<menuitem id="menu_fusion_accounting_root"
name="Fusion AI"
parent="accountant.menu_accounting"
sequence="8"
groups="group_fusion_accounting_user"/>
<!-- Dashboard -->
<menuitem id="menu_fusion_dashboard"
name="Dashboard"
parent="menu_fusion_accounting_root"
action="action_fusion_dashboard"
sequence="10"/>
<!-- Sessions -->
<menuitem id="menu_fusion_sessions"
name="AI Sessions"
parent="menu_fusion_accounting_root"
action="action_fusion_session"
sequence="20"/>
<!-- Match History -->
<menuitem id="menu_fusion_history"
name="Match History"
parent="menu_fusion_accounting_root"
action="action_fusion_history"
sequence="30"/>
<!-- Rules -->
<menuitem id="menu_fusion_rules"
name="Fusion Rules"
parent="menu_fusion_accounting_root"
action="action_fusion_rule"
sequence="40"
groups="group_fusion_accounting_manager"/>
<!-- Configuration (link to settings) -->
<menuitem id="menu_fusion_config"
name="Configuration"
parent="menu_fusion_accounting_root"
action="account.action_account_config"
sequence="90"
groups="group_fusion_accounting_admin"/>
</odoo>

View File

@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_fusion_rule_list" model="ir.ui.view">
<field name="name">fusion.accounting.rule.list</field>
<field name="model">fusion.accounting.rule</field>
<field name="arch" type="xml">
<list string="Fusion Rules">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="rule_type" widget="badge"/>
<field name="approval_tier" widget="badge"
decoration-success="approval_tier == 'auto'"
decoration-warning="approval_tier == 'needs_approval'"/>
<field name="created_by"/>
<field name="confidence_score" widget="progressbar"/>
<field name="total_uses"/>
<field name="active"/>
</list>
</field>
</record>
<record id="view_fusion_rule_form" model="ir.ui.view">
<field name="name">fusion.accounting.rule.form</field>
<field name="model">fusion.accounting.rule</field>
<field name="arch" type="xml">
<form string="Fusion Rule">
<header>
<button name="action_demote" string="Demote to Needs Approval" type="object"
class="btn-warning" invisible="approval_tier != 'auto'"
groups="fusion_accounting.group_fusion_accounting_admin"/>
<button name="action_rollback" string="Rollback to Previous Version" type="object"
class="btn-secondary" invisible="not parent_rule_id"
groups="fusion_accounting.group_fusion_accounting_admin"/>
</header>
<sheet>
<div class="oe_title">
<h1><field name="name" placeholder="Rule Name"/></h1>
</div>
<group>
<group>
<field name="rule_type"/>
<field name="approval_tier"/>
<field name="created_by"/>
<field name="version"/>
<field name="parent_rule_id"/>
</group>
<group>
<field name="confidence_score" widget="progressbar"/>
<field name="total_uses"/>
<field name="total_approved"/>
<field name="total_rejected"/>
<field name="promotion_threshold"/>
<field name="min_sample_size"/>
</group>
</group>
<notebook>
<page string="Logic" name="logic">
<group>
<field name="description"/>
<field name="match_logic"/>
<field name="trigger_domain"/>
<field name="match_code"/>
</group>
</page>
<page string="Accounts" name="accounts">
<group>
<field name="fee_account_id"/>
<field name="write_off_account_id"/>
<field name="journal_ids" widget="many2many_tags"/>
</group>
</page>
<page string="Notes" name="notes">
<field name="notes"/>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<record id="view_fusion_rule_search" model="ir.ui.view">
<field name="name">fusion.accounting.rule.search</field>
<field name="model">fusion.accounting.rule</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="rule_type"/>
<filter name="active" string="Active" domain="[('active', '=', True)]"/>
<filter name="auto" string="Auto-Approved" domain="[('approval_tier', '=', 'auto')]"/>
<filter name="admin_created" string="Admin Created" domain="[('created_by', '=', 'admin')]"/>
<filter name="ai_created" string="AI Created" domain="[('created_by', '=', 'ai')]"/>
<separator/>
<group>
<filter name="group_type" string="Type" domain="[]" context="{'group_by': 'rule_type'}"/>
<filter name="group_tier" string="Approval Tier" domain="[]" context="{'group_by': 'approval_tier'}"/>
</group>
</search>
</field>
</record>
<record id="action_fusion_rule" model="ir.actions.act_window">
<field name="name">Fusion Rules</field>
<field name="res_model">fusion.accounting.rule</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fusion_rule_search"/>
<field name="context">{'search_default_active': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">No rules defined yet</p>
<p>Create rules to teach the AI your accounting patterns.</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Session List View -->
<record id="view_fusion_session_list" model="ir.ui.view">
<field name="name">fusion.accounting.session.list</field>
<field name="model">fusion.accounting.session</field>
<field name="arch" type="xml">
<list string="AI Sessions">
<field name="name"/>
<field name="user_id"/>
<field name="state" widget="badge" decoration-success="state == 'active'" decoration-muted="state == 'closed'"/>
<field name="ai_provider"/>
<field name="ai_model"/>
<field name="tool_call_count"/>
<field name="create_date"/>
</list>
</field>
</record>
<!-- Session Form View (with basic chat) -->
<record id="view_fusion_session_form" model="ir.ui.view">
<field name="name">fusion.accounting.session.form</field>
<field name="model">fusion.accounting.session</field>
<field name="arch" type="xml">
<form string="AI Session">
<header>
<button name="action_close_session" string="Close Session" type="object"
class="btn-secondary" invisible="state == 'closed'"/>
<field name="state" widget="statusbar" statusbar_visible="active,closed"/>
</header>
<sheet>
<group>
<group>
<field name="name"/>
<field name="user_id"/>
<field name="context_domain"/>
</group>
<group>
<field name="ai_provider"/>
<field name="ai_model"/>
<field name="tool_call_count"/>
<field name="token_count_in"/>
<field name="token_count_out"/>
</group>
</group>
<notebook>
<page string="Conversation" name="conversation">
<field name="message_ids_json" widget="text" readonly="1"/>
</page>
<page string="Match History" name="history">
<field name="match_history_ids">
<list>
<field name="tool_name"/>
<field name="decision" widget="badge"
decoration-success="decision == 'approved'"
decoration-danger="decision == 'rejected'"
decoration-warning="decision == 'pending'"
decoration-info="decision == 'auto'"/>
<field name="ai_confidence" widget="progressbar"/>
<field name="amount"/>
<field name="proposed_at"/>
</list>
</field>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- Session Search View -->
<record id="view_fusion_session_search" model="ir.ui.view">
<field name="name">fusion.accounting.session.search</field>
<field name="model">fusion.accounting.session</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="user_id"/>
<filter name="active" string="Active" domain="[('state', '=', 'active')]"/>
<filter name="closed" string="Closed" domain="[('state', '=', 'closed')]"/>
<separator/>
<group>
<filter name="group_user" string="User" domain="[]" context="{'group_by': 'user_id'}"/>
<filter name="group_state" string="Status" domain="[]" context="{'group_by': 'state'}"/>
</group>
</search>
</field>
</record>
<!-- Session Action -->
<record id="action_fusion_session" model="ir.actions.act_window">
<field name="name">AI Sessions</field>
<field name="res_model">fusion.accounting.session</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fusion_session_search"/>
<field name="context">{'search_default_active': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No AI sessions yet
</p>
<p>Start a conversation with Fusion AI from the dashboard.</p>
</field>
</record>
</odoo>