summaryrefslogtreecommitdiff
path: root/addons/hr_attendance/views
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/hr_attendance/views
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/hr_attendance/views')
-rw-r--r--addons/hr_attendance/views/hr_attendance_view.xml225
-rw-r--r--addons/hr_attendance/views/hr_department_view.xml21
-rw-r--r--addons/hr_attendance/views/hr_employee_view.xml172
-rw-r--r--addons/hr_attendance/views/res_config_settings_views.xml41
-rw-r--r--addons/hr_attendance/views/web_asset_backend_template.xml20
5 files changed, 479 insertions, 0 deletions
diff --git a/addons/hr_attendance/views/hr_attendance_view.xml b/addons/hr_attendance/views/hr_attendance_view.xml
new file mode 100644
index 00000000..c4b27df6
--- /dev/null
+++ b/addons/hr_attendance/views/hr_attendance_view.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+
+ <!-- views -->
+
+ <record id="view_attendance_tree" model="ir.ui.view">
+ <field name="name">hr.attendance.tree</field>
+ <field name="model">hr.attendance</field>
+ <field name="arch" type="xml">
+ <tree string="Employee attendances" edit="0" sample="1">
+ <field name="employee_id"/>
+ <field name="check_in"/>
+ <field name="check_out"/>
+ <field name="worked_hours" string="Work Hours" widget="float_time"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="view_attendance_tree_inherit" model="ir.ui.view">
+ <field name="name">hr.attendance.tree.inherit</field>
+ <field name="model">hr.attendance</field>
+ <field name="inherit_id" ref="hr_attendance.view_attendance_tree"/>
+ <field name="groups_id" eval="[(4, ref('hr_attendance.group_hr_attendance_user'))]"/>
+ <field name="arch" type="xml">
+ <tree position="attributes">
+ <attribute name="edit">1</attribute>
+ <attribute name="editable">bottom</attribute>
+ </tree>
+ </field>
+ </record>
+
+ <record id="view_hr_attendance_kanban" model="ir.ui.view">
+ <field name="name">hr.attendance.kanban</field>
+ <field name="model">hr.attendance</field>
+ <field name="arch" type="xml">
+ <kanban class="o_kanban_mobile" sample="1">
+ <field name="employee_id"/>
+ <field name="check_in"/>
+ <field name="check_out"/>
+ <templates>
+ <t t-name="kanban-box">
+ <div t-attf-class="oe_kanban_global_click">
+ <div>
+ <img t-att-src="kanban_image('hr.employee', 'image_128', record.employee_id.raw_value)" t-att-title="record.employee_id.value" t-att-alt="record.employee_id.value" class="oe_kanban_avatar o_image_24_cover mr4"/>
+ <span class="o_kanban_record_title">
+ <strong><t t-esc="record.employee_id.value"/></strong>
+ </span>
+ </div>
+ <hr class="mt4 mb8"/>
+ <div class="o_kanban_record_subtitle">
+ <i class="fa fa-calendar" aria-label="Period" role="img" title="Period"></i>
+ <t t-esc="record.check_in.value"/>
+ - <t t-esc="record.check_out.value"/>
+ </div>
+ </div>
+ </t>
+ </templates>
+ </kanban>
+ </field>
+ </record>
+
+ <record id="hr_attendance_view_form" model="ir.ui.view">
+ <field name="name">hr.attendance.form</field>
+ <field name="model">hr.attendance</field>
+ <field name="arch" type="xml">
+ <form string="Employee attendances" edit="0">
+ <sheet>
+ <group>
+ <field name="employee_id"/>
+ <field name="check_in"/>
+ <field name="check_out"/>
+ </group>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <record id="hr_attendance_view_form_inherit" model="ir.ui.view">
+ <field name="name">hr.attendance.form.inherit</field>
+ <field name="model">hr.attendance</field>
+ <field name="inherit_id" ref="hr_attendance.hr_attendance_view_form"/>
+ <field name="groups_id" eval="[(4, ref('hr_attendance.group_hr_attendance_user'))]"/>
+ <field name="arch" type="xml">
+ <form position="attributes">
+ <attribute name="edit">1</attribute>
+ </form>
+ </field>
+ </record>
+
+ <record id="hr_attendance_view_filter" model="ir.ui.view">
+ <field name="name">hr_attendance_view_filter</field>
+ <field name="model">hr.attendance</field>
+ <field name="arch" type="xml">
+ <search string="Hr Attendance Search">
+ <field name="employee_id"/>
+ <field name="department_id" operator="child_of"/>
+ <filter string="My Attendances" name="myattendances" domain="[('employee_id.user_id.id', '=', uid)]" />
+ <separator/>
+ <filter string="Check In" name="check_in_filter" date="check_in" default_period="last_month"/>
+ <filter string="No Check Out" name="nocheckout" domain="[('check_out', '=', False)]" />
+ <group expand="0" string="Group By">
+ <filter string="Employee" name="employee" context="{'group_by': 'employee_id'}"/>
+ <filter string="Check In" name="groupby_name" context="{'group_by': 'check_in'}"/>
+ <filter string="Check Out" name="groupby_check_out" context="{'group_by': 'check_out'}"/>
+ </group>
+ </search>
+ </field>
+ </record>
+
+ <record id="hr_attendance_view_pivot" model="ir.ui.view">
+ <field name="name">hr.attendance.pivot</field>
+ <field name="model">hr.attendance</field>
+ <field name="arch" type="xml">
+ <pivot string="Attendance" sample="1">
+ <field name="employee_id" type="row"/>
+ <field name="check_in" type="col"/>
+ <field name="worked_hours" type="measure" widget="float_time"/>
+ </pivot>
+ </field>
+ </record>
+
+ <record id="hr_attendance_view_graph" model="ir.ui.view">
+ <field name="name">hr.attendance.graph</field>
+ <field name="model">hr.attendance</field>
+ <field name="arch" type="xml">
+ <graph string="Attendance" sample="1">
+ <field name="employee_id"/>
+ <field name="check_in"/>
+ <field name="worked_hours" type="measure"/>
+ </graph>
+ </field>
+ </record>
+
+ <!-- actions -->
+
+ <record id="hr_attendance_action" model="ir.actions.act_window">
+ <field name="name">Attendances</field>
+ <field name="res_model">hr.attendance</field>
+ <field name="view_mode">tree,kanban,form</field>
+ <field name="context">{"search_default_today":1}</field>
+ <field name="search_view_id" ref="hr_attendance_view_filter" />
+ <field name="help" type="html">
+ <p class="o_view_nocontent_empty_folder">
+ No attendance records found
+ </p><p>
+ The attendance records of your employees will be displayed here.
+ </p>
+ </field>
+ </record>
+
+ <record id="hr_attendance_action_employee" model="ir.actions.act_window">
+ <field name="name">Attendances</field>
+ <field name="res_model">hr.attendance</field>
+ <field name="view_mode">tree,form</field>
+ <field name="context">{'create': False}</field>
+ <field name="help" type="html">
+ <p class="o_view_nocontent_empty_folder">
+ No attendance records to display
+ </p><p>
+ The attendance records of your employees will be displayed here.
+ </p>
+ </field>
+ </record>
+
+ <record id="hr_attendance_action_graph" model="ir.actions.act_window">
+ <field name="name">Attendance Analysis</field>
+ <field name="res_model">hr.attendance</field>
+ <field name="view_mode">graph,pivot</field>
+ <field name="view_id"></field> <!-- force empty -->
+ <field name="help" type="html">
+ <p class="o_view_nocontent_smiling_face">
+ No data yet!
+ </p>
+ </field>
+ </record>
+
+ <record id="hr_attendance_action_graph_filtered" model="ir.actions.act_window">
+ <field name="name">Attendance Analysis</field>
+ <field name="res_model">hr.attendance</field>
+ <field name="view_mode">graph,pivot</field>
+ <field name="context">{
+ 'search_default_department_id': [active_id],
+ 'default_department_id': active_id}
+ </field>
+ <field name="view_id"></field> <!-- force empty -->
+ <field name="help" type="html">
+ <p class="o_view_nocontent_smiling_face">
+ No data yet!
+ </p>
+ </field>
+ </record>
+
+ <record id="hr_attendance_action_kiosk_mode" model="ir.actions.client">
+ <field name="name">Attendances</field>
+ <field name="tag">hr_attendance_kiosk_mode</field>
+ <field name="target">fullscreen</field>
+ </record>
+
+ <record id="hr_attendance_action_my_attendances" model="ir.actions.client">
+ <field name="name">Attendance</field>
+ <field name="tag">hr_attendance_my_attendances</field>
+ <field name="target">main</field>
+ </record>
+
+ <record id="hr_attendance_action_greeting_message" model="ir.actions.client">
+ <field name="name">Message</field>
+ <field name="tag">hr_attendance_greeting_message</field>
+ </record>
+
+ <!-- Menus -->
+
+ <menuitem id="menu_hr_attendance_root" name="Attendances" sequence="90" groups="hr_attendance.group_hr_attendance,hr_attendance.group_hr_attendance_kiosk" web_icon="hr_attendance,static/description/icon.png"/>
+
+ <menuitem id="menu_hr_attendance_my_attendances" name="Check In / Check Out" parent="menu_hr_attendance_root" sequence="1" groups="hr_attendance.group_hr_attendance" action="hr_attendance_action_my_attendances"/>
+
+ <menuitem id="menu_hr_attendance_kiosk_no_user_mode" name="Kiosk Mode" parent="menu_hr_attendance_root" sequence="10" groups="hr_attendance.group_hr_attendance_kiosk" action="hr_attendance_action_kiosk_mode"/>
+
+ <menuitem id="menu_hr_attendance_manage_attendances" name="Manager" parent="menu_hr_attendance_root" sequence="20" groups="hr_attendance.group_hr_attendance_user"/>
+
+ <menuitem id="menu_hr_attendance_view_attendances" name="Attendances" parent="menu_hr_attendance_manage_attendances" sequence="10" groups="hr_attendance.group_hr_attendance_user" action="hr_attendance_action"/>
+
+ <menuitem id="menu_hr_attendance_view_employees_kanban" name="Employees" parent="menu_hr_attendance_manage_attendances" sequence="15" groups="hr_attendance.group_hr_attendance_user" action="hr.open_view_employee_list_my"/>
+
+ <menuitem id="menu_hr_attendance_report" name="Reporting" parent="menu_hr_attendance_root" sequence="30" groups="hr_attendance.group_hr_attendance_user" action="hr_attendance_action_graph"/>
+</odoo>
diff --git a/addons/hr_attendance/views/hr_department_view.xml b/addons/hr_attendance/views/hr_department_view.xml
new file mode 100644
index 00000000..4b5fc67c
--- /dev/null
+++ b/addons/hr_attendance/views/hr_department_view.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <!--Hr Department Inherit Kanban view-->
+ <record id="hr_department_view_kanban" model="ir.ui.view">
+ <field name="name">hr.department.kanban.inherit</field>
+ <field name="model">hr.department</field>
+ <field name="inherit_id" ref="hr.hr_department_view_kanban"/>
+ <field name="groups_id" eval="[(4,ref('hr_attendance.group_hr_attendance_user'))]"/>
+ <field name="arch" type="xml">
+ <data>
+
+ <xpath expr="//div[hasclass('o_kanban_manage_reports')]" position="inside">
+ <a role="menuitem" class="dropdown-item" name="%(hr_attendance_action_graph_filtered)d" type="action">
+ Attendances
+ </a>
+ </xpath>
+
+ </data>
+ </field>
+ </record>
+</odoo>
diff --git a/addons/hr_attendance/views/hr_employee_view.xml b/addons/hr_attendance/views/hr_employee_view.xml
new file mode 100644
index 00000000..d84007aa
--- /dev/null
+++ b/addons/hr_attendance/views/hr_employee_view.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<odoo>
+ <record id="view_employee_form_inherit_hr_attendance" model="ir.ui.view">
+ <field name="name">hr.employee</field>
+ <field name="model">hr.employee</field>
+ <field name="inherit_id" ref="hr.view_employee_form"/>
+ <field name="priority">20</field>
+ <field name="groups_id" eval="[(4,ref('hr_attendance.group_hr_attendance_user'))]"/>
+ <field name="arch" type="xml">
+ <xpath expr="//button[@id='hr_presence_button']" position="attributes">
+ <attribute name="attrs">
+ {'invisible': ['|', '|', ('user_id', '=', False), ('hr_presence_state', '=', 'absent'), ('attendance_state', '=', 'checked_in')]}
+ </attribute>
+ </xpath>
+ <xpath expr="//div[@name='button_box']" position="inside">
+ <field name="attendance_state" invisible="1"/>
+ <button name="%(hr_attendance_action_employee)d"
+ id="hr_attendance_button"
+ class="oe_stat_button"
+ type="action" attrs="{'invisible': [
+ '|', ('attendance_state', '=', False),
+ '&amp;',
+ ('hr_presence_state', '=', 'present'),
+ ('attendance_state', '=', 'checked_out')]}"
+ context="{'search_default_employee_id': id}">
+ <div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_green" attrs="{'invisible': [('attendance_state', '=', 'checked_out')]}" aria-label="Available" title="Available"/>
+ <div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_red" attrs="{'invisible': [('attendance_state', '=', 'checked_in')]}" aria-label="Not available" title="Not available"/>
+ <div class="o_stat_info" attrs="{'invisible': ['|', ('last_check_in', '=', False), ('last_check_out', '!=', False)]}">
+ <span class="o_stat_text">Attended Since</span>
+ <span class="o_stat_value"><field name="last_check_in" widget="relative_time"/></span>
+ </div>
+ <div class="o_stat_info" attrs="{'invisible': [('last_check_out', '=', False)]}">
+ <span class="o_stat_text">Not Attended Since</span>
+ <span class="o_stat_value"><field name="last_check_out" widget="relative_time"/></span>
+ </div>
+ <div class="o_stat_info" attrs="{'invisible': [('last_check_in', '!=', False)]}">
+ <span class="o_stat_text">Attendance</span>
+ </div>
+ </button>
+ <button name="%(hr_attendance_action)d"
+ class="oe_stat_button"
+ icon="fa-clock-o"
+ type="action"
+ context="{'search_default_employee_id': id, 'search_default_check_in_filter': '1'}"
+ groups="base.group_user"
+ help="Worked hours last month">
+ <div class="o_field_widget o_stat_info">
+ <span class="o_stat_value">
+ <field name="hours_last_month_display"/> Hours
+ </span>
+ <span class="o_stat_text">
+ Last Month
+ </span>
+ </div>
+ </button>
+ </xpath>
+ </field>
+ </record>
+
+ <record id="hr_user_view_form" model="ir.ui.view">
+ <field name="name">hr.user.preferences.view.form.attendance.inherit</field>
+ <field name="model">res.users</field>
+ <field name="inherit_id" ref="hr.res_users_view_form_profile"/>
+ <field name="arch" type="xml">
+ <xpath expr="//button[@id='hr_presence_button']" position="attributes">
+ <attribute name="attrs">
+ {'invisible': ['|', ('hr_presence_state', '=', 'absent'), ('attendance_state', '=', 'checked_in')]}
+ </attribute>
+ </xpath>
+ <xpath expr="//div[@name='button_box']" position="inside">
+ <field name="attendance_state" invisible="1"/>
+ <button name="%(hr_attendance_action_my_attendances)d"
+ id="hr_attendance_button"
+ class="oe_stat_button"
+ invisible="context.get('from_my_profile', False)"
+ type="action" attrs="{'invisible': ['|', ('attendance_state', '=', False), '&amp;', ('hr_presence_state', '=', 'present'), ('attendance_state', '=', 'checked_out')]}">
+ <div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_green" attrs="{'invisible': [('attendance_state', '=', 'checked_out')]}" aria-label="Available" title="Available"/>
+ <div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_red" attrs="{'invisible': [('attendance_state', '=', 'checked_in')]}" aria-label="Not available" title="Not available"/>
+ <div class="o_stat_info" attrs="{'invisible': ['|', ('last_check_in', '=', False), ('last_check_out', '!=', False)]}">
+ <span class="o_stat_text">Attended Since</span>
+ <span class="o_stat_value"><field name="last_check_in" widget="relative_time"/></span>
+ </div>
+ <div class="o_stat_info" attrs="{'invisible': [('last_check_out', '=', False)]}">
+ <span class="o_stat_text">Not Attended Since</span>
+ <span class="o_stat_value"><field name="last_check_out" widget="relative_time"/></span>
+ </div>
+ <div class="o_stat_info" attrs="{'invisible': [('last_check_in', '!=', False)]}">
+ <span class="o_stat_text">Attendance</span>
+ </div>
+ </button>
+ </xpath>
+ <xpath expr="//div[@name='button_box']" position="inside">
+ <field name="employee_ids" invisible="1"/>
+ <button name="%(hr_attendance_action_employee)d"
+ class="oe_stat_button"
+ icon="fa-calendar"
+ type="action"
+ context="{'search_default_employee_id': employee_ids, 'search_default_check_in_filter': '1'}"
+ groups="base.group_user"
+ help="Worked hours last month">
+ <div class="o_field_widget o_stat_info">
+ <span class="o_stat_value">
+ <field name="hours_last_month_display"/> Hours
+ </span>
+ <span class="o_stat_text">
+ Last Month
+ </span>
+ </div>
+ </button>
+ </xpath>
+ </field>
+ </record>
+
+ <!-- employee kanban view specifically for hr_attendance (to check in/out) -->
+ <record id="hr_employees_view_kanban" model="ir.ui.view">
+ <field name="name">hr.employee.kanban</field>
+ <field name="model">hr.employee</field>
+ <field name="priority">99</field>
+ <field name="arch" type="xml">
+ <kanban class="o_hr_employee_attendance_kanban" create="false">
+ <field name="attendance_state"/>
+ <field name="hours_today"/>
+ <field name="id"/>
+ <templates>
+ <t t-name="kanban-box">
+ <div class="oe_kanban_global_click">
+ <div class="o_kanban_image">
+ <img t-att-src="kanban_image('hr.employee', 'image_128', record.id.raw_value)" alt="Employee"/>
+ </div>
+ <div class="oe_kanban_details">
+ <div id="textbox">
+ <div class="float-right" t-if="record.attendance_state.raw_value == 'checked_in'">
+ <span id="oe_hr_attendance_status" class="fa fa-circle oe_hr_attendance_status_green" role="img" aria-label="Available" title="Available"></span>
+ </div>
+ <div class="float-right" t-if="record.attendance_state.raw_value == 'checked_out'">
+ <span id="oe_hr_attendance_status" class="fa fa-circle oe_hr_attendance_status_orange"
+ role="img" aria-label="Not available" title="Not available">
+ </span>
+ </div>
+ <strong>
+ <field name="name"/>
+ </strong>
+ </div>
+ <ul>
+ <li t-if="record.job_id.raw_value"><field name="job_id"/></li>
+ <li t-if="record.work_location.raw_value"><field name="work_location"/></li>
+ </ul>
+ </div>
+ </div>
+ </t>
+ </templates>
+ </kanban>
+ </field>
+ </record>
+
+ <record id="hr_employee_attendance_action_kanban" model="ir.actions.act_window">
+ <field name="name">Employees</field>
+ <field name="res_model">hr.employee.public</field>
+ <field name="view_mode">kanban</field>
+ <field name="view_id" ref="hr_employees_view_kanban"/>
+ <field name="target">fullscreen</field>
+ <field name="help" type="html">
+ <p class="o_view_nocontent_smiling_face">
+ Create a new employee
+ </p><p>
+ Add a few employees to be able to select an employee here and perform his check in / check out.
+ To create employees go to the Employees menu.
+ </p>
+ </field>
+ </record>
+
+</odoo>
diff --git a/addons/hr_attendance/views/res_config_settings_views.xml b/addons/hr_attendance/views/res_config_settings_views.xml
new file mode 100644
index 00000000..3ae3aafe
--- /dev/null
+++ b/addons/hr_attendance/views/res_config_settings_views.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <record id="res_config_settings_view_form" model="ir.ui.view">
+ <field name="name">res.config.settings.view.form.inherit.hr.attendance</field>
+ <field name="model">res.config.settings</field>
+ <field name="priority" eval="80"/>
+ <field name="inherit_id" ref="base.res_config_settings_view_form"/>
+ <field name="arch" type="xml">
+ <xpath expr="//div[hasclass('settings')]" position="inside">
+ <div class="app_settings_block" data-string="Attendances" string="Attendances" data-key="hr_attendance" groups="hr_attendance.group_hr_attendance_manager">
+ <h2>Check-In/Out</h2>
+ <div class="row mt16 o_settings_container" name="pincode_setting_container">
+ <div class="col-12 col-lg-6 o_setting_box" title="Set PIN codes in the employee detail form (in HR Settings tab).">
+ <div class="o_setting_left_pane">
+ <field name="group_attendance_use_pin"/>
+ </div>
+ <div class="o_setting_right_pane">
+ <span class="o_form_label">Employee PIN</span>
+ <div class="text-muted">
+ Use PIN codes to check in in Kiosk Mode
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </xpath>
+ </field>
+ </record>
+
+ <record id="action_hr_attendance_settings" model="ir.actions.act_window">
+ <field name="name">Settings</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">res.config.settings</field>
+ <field name="view_mode">form</field>
+ <field name="target">inline</field>
+ <field name="context">{'module' : 'hr_attendance', 'bin_size': False}</field>
+ </record>
+
+ <menuitem id="hr_attendance.menu_hr_attendance_settings" name="Configuration" parent="menu_hr_attendance_root"
+ sequence="99" action="action_hr_attendance_settings" groups="hr_attendance.group_hr_attendance_manager"/>
+</odoo>
diff --git a/addons/hr_attendance/views/web_asset_backend_template.xml b/addons/hr_attendance/views/web_asset_backend_template.xml
new file mode 100644
index 00000000..3a0fb87f
--- /dev/null
+++ b/addons/hr_attendance/views/web_asset_backend_template.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <template id="assets_backend" name="hr_attendance assets" inherit_id="web.assets_backend">
+ <xpath expr="." position="inside">
+ <script type="text/javascript" src="/hr_attendance/static/src/js/employee_kanban_view_handler.js"></script>
+ <script type="text/javascript" src="/hr_attendance/static/src/js/greeting_message.js"></script>
+ <script type="text/javascript" src="/hr_attendance/static/src/js/kiosk_mode.js"></script>
+ <script type="text/javascript" src="/hr_attendance/static/src/js/kiosk_confirm.js"></script>
+ <script type="text/javascript" src="/hr_attendance/static/src/js/my_attendances.js"></script>
+ <script type="text/javascript" src="/hr_attendance/static/src/js/time_widget.js"></script>
+ <link rel="stylesheet" type="text/scss" href="/hr_attendance/static/src/scss/hr_attendance.scss"/>
+ </xpath>
+ </template>
+
+ <template id="qunit_suite" name="hr attendance tests" inherit_id="web.qunit_suite_tests">
+ <xpath expr="//script[contains(@src, '/web/static/tests/views/kanban_tests.js')]" position="after">
+ <script type="text/javascript" src="/hr_attendance/static/tests/hr_attendance_tests.js"></script>
+ </xpath>
+ </template>
+</odoo>