This commit is contained in:
gsinghpal
2026-04-13 02:35:35 -04:00
parent 1176ba68ae
commit 0ff8c0b93f
116 changed files with 14227 additions and 2406 deletions

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ===== Dashboard Form ===== -->
<record id="view_fp_sensor_dashboard_form" model="ir.ui.view">
<field name="name">fp.sensor.dashboard.form</field>
<field name="model">fp.sensor.dashboard</field>
<field name="arch" type="xml">
<form string="Sensor Dashboard">
<sheet>
<div class="oe_title">
<h1>
<field name="name" placeholder="e.g. % Nickel Activity"/>
</h1>
</div>
<group>
<group>
<field name="member_count" readonly="1"/>
<field name="alert_count" readonly="1"/>
</group>
<group>
<field name="active" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
</group>
<notebook>
<page string="Sensors" name="sensors">
<field name="sensor_ids" widget="many2many_tags"/>
<field name="sensor_ids" mode="list">
<list>
<field name="name"/>
<field name="unit"/>
<field name="last_value" string="Last Value"/>
<field name="last_measured"/>
<field name="work_center_id" string="Station"/>
</list>
</field>
</page>
<page string="Alert Rules" name="alerts">
<field name="alert_rule_ids">
<list editable="bottom">
<field name="sensor_id"/>
<field name="threshold_low"/>
<field name="threshold_high"/>
<field name="active"/>
</list>
</field>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- ===== Dashboard List ===== -->
<record id="view_fp_sensor_dashboard_list" model="ir.ui.view">
<field name="name">fp.sensor.dashboard.list</field>
<field name="model">fp.sensor.dashboard</field>
<field name="arch" type="xml">
<list string="Sensor Dashboards" default_order="name">
<field name="name"/>
<field name="alert_count" string="Alerts"
decoration-danger="alert_count > 0"/>
<field name="member_count" string="Members"/>
</list>
</field>
</record>
<!-- ===== Window Action ===== -->
<record id="action_fp_sensor_dashboard" model="ir.actions.act_window">
<field name="name">Sensor Dashboards</field>
<field name="res_model">fp.sensor.dashboard</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a sensor dashboard
</p>
<p>Group sensors into dashboards for monitoring and alerting.</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ===== Quick Measure Wizard Form ===== -->
<record id="view_fp_sensor_measure_wizard_form" model="ir.ui.view">
<field name="name">fp.sensor.measure.wizard.form</field>
<field name="model">fp.sensor.measure.wizard</field>
<field name="arch" type="xml">
<form string="Record Measurement">
<group>
<field name="sensor_id"/>
<field name="measurement_type" invisible="1"/>
<field name="value"
invisible="measurement_type != 'number'"/>
<field name="value_text"
invisible="measurement_type != 'text'"/>
<field name="value_bool"
invisible="measurement_type != 'boolean'"/>
<field name="unit" invisible="not unit"/>
<field name="effective_at"/>
<field name="comment" placeholder="Write a comment..."/>
</group>
<footer>
<button name="action_confirm" string="Save" type="object"
class="btn-primary"/>
<button string="Cancel" special="cancel"/>
</footer>
</form>
</field>
</record>
<!-- ===== Wizard Action (called from sensor form) ===== -->
<record id="action_fp_sensor_measure_wizard" model="ir.actions.act_window">
<field name="name">Record Measurement</field>
<field name="res_model">fp.sensor.measure.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</odoo>

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ===== Measurement Form ===== -->
<record id="view_fp_sensor_measurement_form" model="ir.ui.view">
<field name="name">fp.sensor.measurement.form</field>
<field name="model">fp.sensor.measurement</field>
<field name="arch" type="xml">
<form string="Sensor Measurement">
<sheet>
<group>
<group>
<field name="name" readonly="1"/>
<field name="sensor_id"/>
<field name="measurement_type" invisible="1"/>
<field name="value" invisible="measurement_type != 'number'"/>
<field name="value_text" invisible="measurement_type != 'text'"/>
<field name="value_bool" invisible="measurement_type != 'boolean'"/>
<field name="unit"/>
</group>
<group>
<field name="effective_at"/>
<field name="source"/>
<field name="creator_id" widget="many2one_avatar_user"/>
</group>
</group>
<group>
<field name="comment" placeholder="Write a comment..."/>
</group>
</sheet>
</form>
</field>
</record>
<!-- ===== Measurement List ===== -->
<record id="view_fp_sensor_measurement_list" model="ir.ui.view">
<field name="name">fp.sensor.measurement.list</field>
<field name="model">fp.sensor.measurement</field>
<field name="arch" type="xml">
<list string="Sensor Measurements" default_order="effective_at desc"
decoration-muted="source == 'api'">
<field name="value" string="Measurement"/>
<field name="value_text" optional="hide"/>
<field name="comment"/>
<field name="sensor_id"/>
<field name="measurement_type" column_invisible="1"/>
<field name="creator_id" widget="many2one_avatar_user" string="Creator"/>
<field name="effective_at" string="Created At"/>
<field name="source" widget="badge" optional="show"
decoration-info="source == 'manual'"
decoration-success="source == 'api'"
decoration-warning="source == 'iot'"/>
</list>
</field>
</record>
<!-- ===== Measurement Search ===== -->
<record id="view_fp_sensor_measurement_search" model="ir.ui.view">
<field name="name">fp.sensor.measurement.search</field>
<field name="model">fp.sensor.measurement</field>
<field name="arch" type="xml">
<search>
<field name="sensor_id"/>
<field name="creator_id"/>
<separator/>
<filter string="Manual" name="filter_manual"
domain="[('source', '=', 'manual')]"/>
<filter string="API" name="filter_api"
domain="[('source', '=', 'api')]"/>
<filter string="IoT" name="filter_iot"
domain="[('source', '=', 'iot')]"/>
<separator/>
<filter string="Today" name="filter_today"
domain="[('effective_at', '>=', context_today().strftime('%Y-%m-%d'))]"/>
<filter string="This Week" name="filter_week"
domain="[('effective_at', '>=', (context_today() - datetime.timedelta(days=7)).strftime('%Y-%m-%d'))]"/>
<group>
<filter string="Sensor" name="group_sensor"
context="{'group_by': 'sensor_id'}"/>
<filter string="Creator" name="group_creator"
context="{'group_by': 'creator_id'}"/>
<filter string="Source" name="group_source"
context="{'group_by': 'source'}"/>
<filter string="Date" name="group_date"
context="{'group_by': 'effective_at:day'}"/>
</group>
</search>
</field>
</record>
<!-- ===== Window Action ===== -->
<record id="action_fp_sensor_measurement" model="ir.actions.act_window">
<field name="name">Sensor Measurements</field>
<field name="res_model">fp.sensor.measurement</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_sensor_measurement_search"/>
<field name="context">{'search_default_filter_today': 0}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No measurements recorded yet
</p>
<p>Measurements are recorded manually via the sensor form or automatically via the IoT API.</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ===== Sensors parent menu under Operations ===== -->
<menuitem id="menu_fp_sensors"
name="Sensors"
parent="fusion_plating.menu_fp_operations"
sequence="20"/>
<menuitem id="menu_fp_sensor_dashboards"
name="Dashboards"
parent="menu_fp_sensors"
action="action_fp_sensor_dashboard"
sequence="10"/>
<menuitem id="menu_fp_sensors_all"
name="All Sensors"
parent="menu_fp_sensors"
action="action_fp_sensor"
sequence="20"/>
<menuitem id="menu_fp_sensor_measurements"
name="Measurements"
parent="menu_fp_sensors"
action="action_fp_sensor_measurement"
sequence="30"/>
<menuitem id="menu_fp_sensor_types"
name="Sensor Types"
parent="menu_fp_sensors"
action="action_fp_sensor_type"
sequence="40"/>
</odoo>

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ===== Sensor Type Form ===== -->
<record id="view_fp_sensor_type_form" model="ir.ui.view">
<field name="name">fp.sensor.type.form</field>
<field name="model">fp.sensor.type</field>
<field name="arch" type="xml">
<form string="Sensor Type">
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" icon="fa-microchip"
type="object" name="action_view_sensors"
invisible="sensor_count == 0">
<field name="sensor_count" widget="statinfo" string="Sensors"/>
</button>
</div>
<group>
<group>
<field name="name"/>
<field name="measurement_type"/>
</group>
<group>
<field name="active" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<!-- ===== Sensor Type List ===== -->
<record id="view_fp_sensor_type_list" model="ir.ui.view">
<field name="name">fp.sensor.type.list</field>
<field name="model">fp.sensor.type</field>
<field name="arch" type="xml">
<list string="Sensor Types" default_order="name">
<field name="name"/>
<field name="measurement_type"/>
<field name="sensor_count" string="Sensors"/>
</list>
</field>
</record>
<!-- ===== Sensor Type Search ===== -->
<record id="view_fp_sensor_type_search" model="ir.ui.view">
<field name="name">fp.sensor.type.search</field>
<field name="model">fp.sensor.type</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<separator/>
<filter string="Number" name="filter_number" domain="[('measurement_type', '=', 'number')]"/>
<filter string="Text" name="filter_text" domain="[('measurement_type', '=', 'text')]"/>
<filter string="Boolean" name="filter_boolean" domain="[('measurement_type', '=', 'boolean')]"/>
<group>
<filter string="Type" name="group_type" context="{'group_by': 'measurement_type'}"/>
</group>
</search>
</field>
</record>
<!-- ===== Window Action ===== -->
<record id="action_fp_sensor_type" model="ir.actions.act_window">
<field name="name">Sensor Types</field>
<field name="res_model">fp.sensor.type</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_sensor_type_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a sensor type
</p>
<p>Sensor types define what a sensor measures (Number, Text, or Boolean).</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ===== Sensor Form ===== -->
<record id="view_fp_sensor_form" model="ir.ui.view">
<field name="name">fp.sensor.form</field>
<field name="model">fp.sensor</field>
<field name="arch" type="xml">
<form string="Sensor">
<header>
<button name="action_quick_measure"
string="+ Measure"
type="object"
class="btn-primary"
icon="fa-plus"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" icon="fa-bar-chart"
type="object" name="action_view_measurements">
<field name="measurement_count" widget="statinfo"
string="Measurements"/>
</button>
</div>
<div class="oe_title">
<h1>
<field name="name" placeholder="e.g. Waste Water Treatment pH"/>
</h1>
</div>
<group>
<group string="Sensor Configuration">
<field name="sensor_type_id"/>
<field name="measurement_type" invisible="1"/>
<field name="unit" placeholder="e.g. ph, %, g/L, PPM"/>
<field name="uuid" placeholder="Hardware UUID for IoT"/>
<field name="use_location"/>
</group>
<group string="Location">
<field name="work_center_id" string="Station"/>
<field name="tank_id"/>
<field name="facility_id"/>
<field name="location_name"
invisible="not use_location"
placeholder="e.g. WaterTreatmentArea"/>
</group>
</group>
<group string="Last Reading">
<group>
<field name="last_value" readonly="1"
invisible="measurement_type != 'number'"/>
<field name="last_value_text" readonly="1"
invisible="measurement_type != 'text'"/>
</group>
<group>
<field name="last_measured" readonly="1"/>
</group>
</group>
<notebook>
<page string="Recent Measurements" name="measurements">
<field name="measurement_ids" mode="list" limit="5">
<list editable="bottom" default_order="effective_at desc"
decoration-muted="source == 'api'">
<field name="effective_at" string="Date"/>
<field name="value"
invisible="parent.measurement_type != 'number'"/>
<field name="value_text"
invisible="parent.measurement_type != 'text'"/>
<field name="value_bool"
invisible="parent.measurement_type != 'boolean'"/>
<field name="comment"/>
<field name="creator_id" widget="many2one_avatar_user"/>
<field name="source" widget="badge"
decoration-info="source == 'manual'"
decoration-success="source == 'api'"
decoration-warning="source == 'iot'"/>
</list>
</field>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- ===== Sensor List ===== -->
<record id="view_fp_sensor_list" model="ir.ui.view">
<field name="name">fp.sensor.list</field>
<field name="model">fp.sensor</field>
<field name="arch" type="xml">
<list string="Sensors" default_order="name">
<field name="name"/>
<field name="sensor_type_id"/>
<field name="last_value" string="Last Measurement"/>
<field name="unit"/>
<field name="measurement_type" column_invisible="1"/>
<field name="last_measured" string="Last Measured"/>
<field name="work_center_id" string="Station" optional="show"/>
<field name="location_name" string="Location" optional="show"/>
<field name="uuid" optional="hide"/>
</list>
</field>
</record>
<!-- ===== Sensor Search ===== -->
<record id="view_fp_sensor_search" model="ir.ui.view">
<field name="name">fp.sensor.search</field>
<field name="model">fp.sensor</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="uuid"/>
<field name="sensor_type_id"/>
<field name="work_center_id" string="Station"/>
<field name="tank_id"/>
<field name="facility_id"/>
<separator/>
<filter string="Number Sensors" name="filter_number"
domain="[('measurement_type', '=', 'number')]"/>
<filter string="Has UUID" name="filter_has_uuid"
domain="[('uuid', '!=', False)]"/>
<group>
<filter string="Station" name="group_station"
context="{'group_by': 'work_center_id'}"/>
<filter string="Type" name="group_type"
context="{'group_by': 'sensor_type_id'}"/>
<filter string="Facility" name="group_facility"
context="{'group_by': 'facility_id'}"/>
</group>
</search>
</field>
</record>
<!-- ===== Window Action ===== -->
<record id="action_fp_sensor" model="ir.actions.act_window">
<field name="name">Sensors</field>
<field name="res_model">fp.sensor</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_sensor_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create your first sensor
</p>
<p>Sensors track chemistry readings at tanks, work centres, and other locations.</p>
</field>
</record>
</odoo>