mirror of
https://github.com/bringout/oca-ocb-hr.git
synced 2026-04-26 11:32:01 +02:00
19.0 vanilla
This commit is contained in:
parent
a1137a1456
commit
e1d89e11e3
2789 changed files with 1093187 additions and 605897 deletions
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="hr_attendance.public_kiosk_mode" name="Attendance Kiosk">
|
||||
<t t-call="web.layout">
|
||||
<t t-set="html_data" t-value="{'lang': kiosk_backend_info['lang']}"/>
|
||||
<t t-set="head">
|
||||
<title>Attendance Kiosk</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta http-equiv="content-type" content="text/html, charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
|
||||
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
|
||||
<t t-call-assets="hr_attendance.assets_public_attendance" t-js="false"/>
|
||||
<t t-call-assets="hr_attendance.assets_public_attendance" t-css="false"/>
|
||||
<t t-call="web.conditional_assets_tests">
|
||||
<t t-set="ignore_missing_deps" t-value="True"/>
|
||||
</t>
|
||||
|
||||
<script type="text/javascript">
|
||||
odoo.define("hr_attendance.public_kiosk_app", ["@hr_attendance/public_kiosk/public_kiosk_app"], function (require) {
|
||||
var { createPublicKioskAttendance } = require("@hr_attendance/public_kiosk/public_kiosk_app");
|
||||
createPublicKioskAttendance(document, <t t-out="json.dumps(kiosk_backend_info)"/>);
|
||||
});
|
||||
</script>
|
||||
</t>
|
||||
<t t-set="body">
|
||||
</t>
|
||||
<body class="o_web_client o_hr_attendance_kiosk_body position-relative">
|
||||
</body>
|
||||
</t>
|
||||
</template>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- views -->
|
||||
<record id="hr_attendance_overtime_rule_view_form" model="ir.ui.view">
|
||||
<field name="name">hr.attendance.overtime.rule.form</field>
|
||||
<field name="model">hr.attendance.overtime.rule</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<label for="name" string="Rule Name"/>
|
||||
<h1><field name="name" placeholder="e.g. Over 8 hours daily"/></h1>
|
||||
<group>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</div>
|
||||
<notebook>
|
||||
<page string="Definition">
|
||||
<group
|
||||
string="Condition"
|
||||
style="grid-template-columns:max-content 1fr"
|
||||
>
|
||||
<field name="base_off" widget="radio" string="The rule is based on"/>
|
||||
<!-- QUANTITY -->
|
||||
<span colspan="2" class="d-flex gap-1" invisible="base_off != 'quantity'">
|
||||
<label for="quantity_period" string="If the worked hours on a"/>
|
||||
<field style="width:10ch" nolabel="1" name="quantity_period"/>
|
||||
<label for="expected_hours_from_contract" string="differs"/>
|
||||
<field class="w-auto" name="expected_hours_from_contract" nolabel="1" widget="boolean_radio" options="{
|
||||
'yes_label_element_id': 'expected_hours_from_contract_yes',
|
||||
'no_label_element_id': 'expected_hours_from_contract_no'
|
||||
}"/>
|
||||
<template id="expected_hours_from_contract_yes">from the amount defined on the contract</template>
|
||||
<template id="expected_hours_from_contract_no">from a specific duration</template>
|
||||
</span>
|
||||
<label for="expected_hours" string="Duration to exceed:" invisible="base_off != 'quantity' or expected_hours_from_contract"/>
|
||||
<span name="expected_hours" class="fw-bold" invisible="base_off != 'quantity' or expected_hours_from_contract">
|
||||
<field name="expected_hours" widget="float_time" style="width:10ch"/>
|
||||
hours
|
||||
</span>
|
||||
<field name="employer_tolerance" widget="float_time" string="With a tolerance in favor of the employer of"/>
|
||||
<field name="employee_tolerance" widget="float_time" string="With a tolerance in favor of the employee of"/>
|
||||
<!-- TIMING -->
|
||||
<field name="timing_type" widget="radio" string="If the employee works" invisible="base_off != 'timing'"/>
|
||||
<span class="fw-bold" invisible="base_off != 'timing' or timing_type not in ['work_days', 'non_work_days']">Between</span>
|
||||
<span class="d-flex gap-1" invisible="base_off != 'timing' or timing_type not in ['work_days', 'non_work_days']">
|
||||
<field nolabel="1" name="timing_start" widget="float_time" style="width:10ch"/>
|
||||
<label for="expected_hours_from_contract" string="and"/>
|
||||
<field nolabel="1" name="timing_stop" widget="float_time" style="width:10ch"/>
|
||||
</span>
|
||||
<field name="resource_calendar_id" string="Schedule" invisible="base_off != 'timing' or timing_type != 'schedule'"/>
|
||||
</group>
|
||||
<group
|
||||
name="action_section"
|
||||
string="Action"
|
||||
style="grid-template-columns:max-content 1fr"
|
||||
>
|
||||
<span colspan="2" class="mb-3 fw-bold">The hours will be considered extra and submitted to approval.</span>
|
||||
<label for="paid" string="Pay extra hours"/>
|
||||
<span class="d-flex gap-1" name="paid">
|
||||
<field class="w-auto" nolabel="1" name="paid"/>
|
||||
<label for="amount_rate" string="with a rate of" invisible="not paid"/>
|
||||
<field name="amount_rate" style="width:10ch" widget="percentage" invisible="not paid"/>
|
||||
</span>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Description">
|
||||
<field name="description" placeholder="Description"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_overtime_rule_view_list" model="ir.ui.view">
|
||||
<field name="name">hr.attendance.overtime.rule.list</field>
|
||||
<field name="model">hr.attendance.overtime.rule</field>
|
||||
<field name="arch" type="xml">
|
||||
<list>
|
||||
<field name="name"/>
|
||||
<field name="base_off"/>
|
||||
<field
|
||||
name="expected_hours_from_contract"
|
||||
string="Get working hours from contract"/>
|
||||
<field name="expected_hours" invisible="expected_hours_from_contract or base_off != 'quantity'"/>
|
||||
<field name="resource_calendar_id" invisible="expected_hours_from_contract or base_off != 'timing'"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_overtime_ruleset_view_form" model="ir.ui.view">
|
||||
<field name="name">hr.attendance.overtime.ruleset.form</field>
|
||||
<field name="model">hr.attendance.overtime.ruleset</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Extra Hours Rules">
|
||||
<field name="active" invisible="1"/>
|
||||
<header>
|
||||
<button name="action_regenerate_overtimes"
|
||||
class="btn"
|
||||
string="Regenerate overtimes"
|
||||
icon="fa-clock-o"
|
||||
type="object"
|
||||
groups="hr_attendance.group_hr_attendance_officer"
|
||||
help="Regenerate overtimes for this ruleset"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<header>
|
||||
<div class="oe_title">
|
||||
<label for="name" string="Ruleset Name"/>
|
||||
<h1><field name="name" placeholder="e.g. Legal Rules"/></h1>
|
||||
</div>
|
||||
</header>
|
||||
<group>
|
||||
<group>
|
||||
<field name="rate_combination_mode"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="country_id" options="{'no_create': True, 'no_open': True}" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
<group colspan="4">
|
||||
<field
|
||||
name="description" colspan="4"
|
||||
placeholder="Provide a description or sources for this ruleset."/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page name="overtime_rules" string="Overtime Rules">
|
||||
<field name="rule_ids" readonly="not id">
|
||||
<list>
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="base_off"/>
|
||||
<field name="information_display"/>
|
||||
<field name="amount_rate" widget="percentage"/>
|
||||
</list>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_overtime_ruleset_view_list" model="ir.ui.view">
|
||||
<field name="name">hr.attendance.overtime.ruleset.list</field>
|
||||
<field name="model">hr.attendance.overtime.ruleset</field>
|
||||
<field name="arch" type="xml">
|
||||
<list>
|
||||
<field name="name"/>
|
||||
<field name="country_id" groups="base.group_multi_company" optional="hide"/>
|
||||
<field name="rate_combination_mode" string="Rate Mode"/>
|
||||
<field name="rules_count"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_overtime_ruleset_view_filter" model="ir.ui.view">
|
||||
<field name="name">hr_attendance_overtime_ruleset_view_filter</field>
|
||||
<field name="model">hr.attendance.overtime.ruleset</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Ruleset Search">
|
||||
<filter string="At least one rule" name="has_rules" domain="[('rule_ids', '!=', False)]"/>
|
||||
<separator invisible="1"/>
|
||||
<filter string="Archived" name="archived_rulesets" domain="[('active', '=', False)]"/>
|
||||
<group>
|
||||
<filter string="Rate Mode" name="rate_mode" context="{'group_by': 'rate_combination_mode'}"/>
|
||||
<filter string="Country" name="country" context="{'group_by': 'country_id'}" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="hr_attendance_overtime_rule_action" model="ir.actions.act_window">
|
||||
<field name="name">Overtime Rules</field>
|
||||
<field name="res_model">hr.attendance.overtime.rule</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_overtime_ruleset_action" model="ir.actions.act_window">
|
||||
<field name="name">Rulesets</field>
|
||||
<field name="res_model">hr.attendance.overtime.ruleset</field>
|
||||
<field name="search_view_id" ref="hr_attendance_overtime_ruleset_view_filter"/>
|
||||
<field name="view_mode">list,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_hr_attendance_overtime_rulesets" name="Overtime Rulesets" parent="hr_attendance.menu_hr_attendance_configuration" sequence="300" action="hr_attendance_overtime_ruleset_action" groups="hr_attendance.group_hr_attendance_manager"/>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="view_attendance_overtime_tree" model="ir.ui.view">
|
||||
<field name="name">hr.attendance.overtime.tree</field>
|
||||
<field name="model">hr.attendance.overtime</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree edit="0" create="0">
|
||||
<field name="date"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="duration" widget="float_time"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_attendance_overtime_search" model="ir.ui.view">
|
||||
<field name="name">hr.attendance.overtime.search</field>
|
||||
<field name="model">hr.attendance.overtime</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<field name="employee_id"/>
|
||||
<field name="duration" filter_domain="[('duration', '>=', self)]"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_overtime_action" model="ir.actions.act_window">
|
||||
<field name="name">Extra Hours</field>
|
||||
<field name="res_model">hr.attendance.overtime</field>
|
||||
<field name="view_mode">tree</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -4,15 +4,39 @@
|
|||
<!-- views -->
|
||||
|
||||
<record id="view_attendance_tree" model="ir.ui.view">
|
||||
<field name="name">hr.attendance.tree</field>
|
||||
<field name="name">hr.attendance.list</field>
|
||||
<field name="model">hr.attendance</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Employee attendances" editable="bottom" sample="1">
|
||||
<field name="employee_id"/>
|
||||
<list
|
||||
js_class="attendance_list_view"
|
||||
string="Employee attendances"
|
||||
decoration-success="color == 10"
|
||||
decoration-danger="color == 1"
|
||||
duplicate="false">
|
||||
<header>
|
||||
<button class="btn-secondary" string="Approve Extra Hours" name="action_approve_overtime" type="object"/>
|
||||
<button class="btn-secondary" string="Refuse Extra Hours" name="action_refuse_overtime" type="object"/>
|
||||
</header>
|
||||
<field name="employee_id" widget="many2one_avatar_employee"/>
|
||||
<field name="check_in"/>
|
||||
<field name="check_out"/>
|
||||
<field name="worked_hours" string="Work Hours" widget="float_time"/>
|
||||
</tree>
|
||||
<field name="check_out" options="{}"/>
|
||||
<field name="worked_hours" string="Worked Hours" widget="float_time"/>
|
||||
<field name="overtime_hours" string="Worked Extra Hours" optional="show" widget="float_time"/>
|
||||
<field name="validated_overtime_hours" string="Extra Hours" optional="show" widget="float_time"/>
|
||||
<field name="overtime_status" optional="hidden" widget="badge" decoration-warning="overtime_status == 'to_approve'" decoration-success="overtime_status == 'approved'" decoration-danger="overtime_status == 'refused'"/>
|
||||
<field name="in_mode" string="Input Mode (In)" optional="hidden"/>
|
||||
<field name="out_mode" string="Input Mode (Out)" optional="hidden"/>
|
||||
<field name="in_latitude" string="Latitude (In)" optional="hidden"/>
|
||||
<field name="in_longitude" string="Longitude (In)" optional="hidden"/>
|
||||
<field name="in_location" string="Location (In)" optional="hidden"/>
|
||||
<field name="out_latitude" string="Latitude (Out)" optional="hidden"/>
|
||||
<field name="out_longitude" string="Longitude (Out)" optional="hidden"/>
|
||||
<field name="out_location" string="Location (Out)" optional="hidden"/>
|
||||
<field name="create_uid" optional="hidden"/>
|
||||
<field name="write_uid" optional="hidden"/>
|
||||
<field name="write_date" optional="hidden"/>
|
||||
<field name="color" column_invisible="1"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
@ -21,24 +45,15 @@
|
|||
<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', 'avatar_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>
|
||||
<t t-name="card">
|
||||
<field name="employee_id" widget="many2one_avatar_employee" options="{'display_avatar_name': True}" class="fs-5 fw-bold mb-2"/>
|
||||
<hr class="mt4 mb8"/>
|
||||
<div>
|
||||
<i class="fa fa-calendar me-1" aria-label="Period" role="img" title="Period"></i>
|
||||
<field name="check_in" /> - <field name="check_out" />
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -50,18 +65,203 @@
|
|||
<field name="name">hr.attendance.form</field>
|
||||
<field name="model">hr.attendance</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Employee attendances">
|
||||
<form string="Employee attendances" duplicate="false">
|
||||
<header>
|
||||
<field
|
||||
name="overtime_status"
|
||||
widget="statusbar"
|
||||
readonly="1"
|
||||
options="{'clickable': '1'}"
|
||||
invisible="not overtime_status"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="employee_id"/>
|
||||
<field name="check_in"/>
|
||||
<field name="check_out"/>
|
||||
<group colspan="2">
|
||||
<group col="1" name="group_employee">
|
||||
<field
|
||||
id="employee_no_officer"
|
||||
name="employee_id"
|
||||
widget="many2one_avatar_employee"
|
||||
readonly="1"
|
||||
groups="!hr_attendance.group_hr_attendance_officer"/>
|
||||
<field
|
||||
id="employee_no_manager"
|
||||
name="employee_id"
|
||||
widget="many2one_avatar_employee"
|
||||
domain="[
|
||||
('attendance_manager_id', '=', uid),
|
||||
('company_id', 'in', allowed_company_ids),
|
||||
]"
|
||||
groups="hr_attendance.group_hr_attendance_officer,!hr_attendance.group_hr_attendance_user"/>
|
||||
<field
|
||||
id="employee_manager"
|
||||
name="employee_id"
|
||||
widget="many2one_avatar_employee"
|
||||
domain="[
|
||||
('company_id', 'in', allowed_company_ids),
|
||||
]"
|
||||
groups="hr_attendance.group_hr_attendance_user"/>
|
||||
<field name="check_in" options="{'rounding': 0}" readonly="not is_manager"/>
|
||||
<field name="check_out" options="{'rounding': 0}" placeholder="Currently Working" readonly="not is_manager"/>
|
||||
</group>
|
||||
<group col="2">
|
||||
<field name="worked_hours" string="Worked Time" widget="float_time"/>
|
||||
<field name="overtime_hours" widget="float_time" string="Worked Extra Hours" invisible="overtime_hours == validated_overtime_hours"/>
|
||||
<label for="validated_overtime_hours"/>
|
||||
<div>
|
||||
<field
|
||||
name="validated_overtime_hours"
|
||||
style="width:5ch"
|
||||
widget="float_time"
|
||||
readonly="1"/>
|
||||
<!-- TODO algin icons baseline with text -->
|
||||
<button
|
||||
class="oe_stat_button flex-shrink-0"
|
||||
string=" "
|
||||
help="Approve all overtimes for the same employee and date"
|
||||
invisible="not is_manager or overtime_status not in ['to_approve', 'refused'] or not overtime_status"
|
||||
name="action_approve_overtime"
|
||||
icon="fa-check"
|
||||
type="object"
|
||||
groups="hr_attendance.group_hr_attendance_officer"/>
|
||||
<button
|
||||
class="oe_stat_button flex-shrink-0"
|
||||
string=" "
|
||||
help="Refuse all overtimes for the same employee and date"
|
||||
invisible="not is_manager or overtime_status not in ['to_approve', 'approved'] or not overtime_status"
|
||||
name="action_refuse_overtime"
|
||||
icon="fa-times"
|
||||
type="object"
|
||||
groups="hr_attendance.group_hr_attendance_officer"/>
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
<separator string="Check In"/>
|
||||
<group name="check_in_group" colspan="2">
|
||||
<group>
|
||||
<group>
|
||||
<field name="in_mode"/>
|
||||
<field name="in_ip_address" invisible="in_mode == 'manual' or not device_tracking_enabled"/>
|
||||
<field name="in_browser" invisible="in_mode == 'manual' or not device_tracking_enabled"/>
|
||||
</group>
|
||||
</group>
|
||||
<group invisible="in_mode == 'manual' or not device_tracking_enabled">
|
||||
<field name="in_location"/>
|
||||
<label for="in_latitude" string="GPS Coordinates"/>
|
||||
<div>
|
||||
<div class="o_row">
|
||||
<span>
|
||||
<field name="in_latitude"/>
|
||||
</span>,
|
||||
<span>
|
||||
<field name="in_longitude" nolabel="1"/>
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
name="action_in_attendance_maps"
|
||||
type="object"
|
||||
class="btn btn-link ps-0 pt-0 pb-2"
|
||||
icon="oi-arrow-right"
|
||||
string="View on Maps"
|
||||
colspan="2"/>
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
<separator string="Check Out" name="check_out_separator" invisible="not check_out"/>
|
||||
<group colspan="2" name="check_out_group" invisible="not check_out">
|
||||
<group>
|
||||
<group>
|
||||
<field name="out_mode" string="Mode"/>
|
||||
<field name="out_ip_address" string="IP Address" invisible="in_mode == 'manual' or not device_tracking_enabled"/>
|
||||
<field name="out_browser" string="Browser" invisible="in_mode == 'manual' or not device_tracking_enabled"/>
|
||||
</group>
|
||||
</group>
|
||||
<group invisible="out_mode == 'manual' or not device_tracking_enabled">
|
||||
<field name="out_location"/>
|
||||
<label for="out_latitude" string="GPS Coordinates"/>
|
||||
<div>
|
||||
<div class="o_row">
|
||||
<span>
|
||||
<field name="out_latitude"/>
|
||||
</span>,
|
||||
<span>
|
||||
<field name="out_longitude" nolabel="1"/>
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
name="action_out_attendance_maps"
|
||||
type="object"
|
||||
class="btn btn-link ps-0 pt-0 pb-2"
|
||||
icon="oi-arrow-right"
|
||||
string="View on Maps"
|
||||
colspan="2"/>
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
<notebook invisible="not overtime_status">
|
||||
<page string="Overtime Details">
|
||||
<field name="linked_overtime_ids">
|
||||
<list editable="bottom">
|
||||
<field name="rule_ids" widget="many2many_tags" readonly="1"/>
|
||||
<field name="duration" widget="float_time" readonly="1"/>
|
||||
<field name="manual_duration" widget="float_time" readonly="0"/>
|
||||
<field name="amount_rate" widget="percentage"/>
|
||||
<field name="status" widget="badge" readonly="1" decoration-warning="status == 'to_approve'" decoration-success="status == 'approved'" decoration-danger="status == 'refused'"/>
|
||||
<button
|
||||
class="oe_stat_button"
|
||||
string="Approve"
|
||||
invisible="not is_manager or status not in ['to_approve', 'refused']"
|
||||
name="action_approve"
|
||||
icon="fa-check"
|
||||
type="object"
|
||||
groups="hr_attendance.group_hr_attendance_officer"/>
|
||||
<button
|
||||
class="oe_stat_button"
|
||||
string="Refuse"
|
||||
invisible="not is_manager or status not in ['to_approve', 'approved']"
|
||||
name="action_refuse"
|
||||
icon="fa-times"
|
||||
type="object"
|
||||
groups="hr_attendance.group_hr_attendance_officer"/>
|
||||
</list>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<chatter/>
|
||||
</form>
|
||||
</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="Worked Hours" type="line" stacked="0" sample="1">
|
||||
<field name="employee_id" type="row"/>
|
||||
<field name="check_in" interval="week" type="col"/>
|
||||
<field name="overtime_hours" widget="float_time"/>
|
||||
<field name="worked_hours" type="measure" widget="float_time"/>
|
||||
</graph>
|
||||
</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="Worked Hours">
|
||||
<field name="employee_id" type="row"/>
|
||||
<field name="check_in" type="col" interval="month"/>
|
||||
<field name="worked_hours" type="measure" widget="float_time"/>
|
||||
<field name="expected_hours" type="measure" widget="float_time"/>
|
||||
<field name="overtime_hours" string="Difference" type="measure" widget="float_time"/>
|
||||
<field name="validated_overtime_hours" string="Balance" type="measure" widget="float_time"/>
|
||||
</pivot>
|
||||
</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>
|
||||
|
|
@ -69,14 +269,34 @@
|
|||
<search string="Hr Attendance Search">
|
||||
<field name="employee_id"/>
|
||||
<field name="department_id" operator="child_of"/>
|
||||
<field name="check_in"/>
|
||||
<filter string="My Attendances" name="myattendances" domain="[('employee_id.user_id', '=', uid)]" />
|
||||
<filter string="My Team" name="myteam" domain="[('employee_id.parent_id.user_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="At Work" name="nocheckout" domain="[('check_out', '=', False)]" />
|
||||
<filter string="Errors" name="errors"
|
||||
domain="['|', ('worked_hours', '>=', 16), '&', ('check_out', '=', False), ('check_in', '<=', '-1d')]"/>
|
||||
<filter string="Automatically Checked-Out" name="auto_check"
|
||||
domain="[('out_mode', '=', 'auto_check_out')]"/>
|
||||
<separator/>
|
||||
<filter string="Date" name="check_in_filter" date="check_in"/>
|
||||
<separator/>
|
||||
<filter
|
||||
string="Active Employees"
|
||||
name="activeemployees"
|
||||
domain="[('employee_id.active', '=', True)]"/>
|
||||
<filter
|
||||
string="Archived Employees"
|
||||
name="archivedemployees"
|
||||
domain="[('employee_id.active', '=', False)]"/>
|
||||
<separator invisible="1"/>
|
||||
<filter string="Last 3 Months" invisible="1" name="last_three_months" domain="[('check_in','>=', '-3m')]"/>
|
||||
<group>
|
||||
<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'}"/>
|
||||
<filter string="Department" name="departement" context="{'group_by': 'department_id'}"/>
|
||||
<filter string="Manager" name="manager" context="{'group_by': 'manager_id'}"/>
|
||||
<filter string="Method" name="groupby_mode_in" context="{'group_by': 'in_mode'}"/>
|
||||
<filter string="Date" name="groupby_name" context="{'group_by': 'check_in:month'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
|
|
@ -84,75 +304,195 @@
|
|||
|
||||
<!-- actions -->
|
||||
|
||||
<record id="action_try_kiosk" model="ir.actions.server">
|
||||
<field name="name">Try kiosk</field>
|
||||
<field name="model_id" ref="hr_attendance.model_hr_attendance"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.action_try_kiosk()</field>
|
||||
</record>
|
||||
|
||||
<record id="action_load_demo_data" model="ir.actions.server">
|
||||
<field name="name">Load demo data</field>
|
||||
<field name="model_id" ref="hr_attendance.model_hr_attendance"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model._load_demo_data()</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_action" model="ir.actions.act_window">
|
||||
<field name="name">Attendances</field>
|
||||
<field name="path">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="group_ids" eval="[(4, ref('hr_attendance.group_hr_attendance_officer'))]"/>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="context">
|
||||
{
|
||||
"search_default_groupby_name": 1,
|
||||
"search_default_employee": 2
|
||||
}
|
||||
</field>
|
||||
<field name="search_view_id" ref="hr_attendance_view_filter"/>
|
||||
<field name="help">
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_reporting" model="ir.actions.act_window">
|
||||
<field name="name">Attendances</field>
|
||||
<field name="res_model">hr.attendance</field>
|
||||
<field name="path">attendance-report</field>
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
<field name="search_view_id" ref="hr_attendance_view_filter"/>
|
||||
<field name="context">
|
||||
{
|
||||
"search_default_employee": 2,
|
||||
"search_default_activeemployees": 1,
|
||||
"search_default_last_three_months": 1
|
||||
}
|
||||
</field>
|
||||
<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.
|
||||
The attendance reporting 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>
|
||||
<record id="hr_attendance_management_view_filter" model="ir.ui.view">
|
||||
<field name="name">hr_attendance_management_view_filter</field>
|
||||
<field name="model">hr.attendance</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<field name="employee_id"/>
|
||||
<field name="department_id" operator="child_of"/>
|
||||
<filter string="My Attendances" name="myattendances" domain="[('employee_id.user_id', '=', uid)]" />
|
||||
<filter string="My Team" name="myteam" domain="[('employee_id.parent_id.user_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<filter string="To Approve" name="to_approve" domain="[('overtime_status','=', 'to_approve')]"/>
|
||||
<filter string="Approved" name="approved" domain="[('overtime_status','=', 'approved')]"/>
|
||||
<filter string="Refused" name="refused" domain="[('overtime_status','=', 'refused')]"/>
|
||||
<separator/>
|
||||
<filter string="Date" name="check_in_filter" date="check_in"/>
|
||||
<separator/>
|
||||
<filter
|
||||
string="Active Employees"
|
||||
name="activeemployees"
|
||||
domain="[('employee_id.active', '=', True)]"/>
|
||||
<filter
|
||||
string="Archived Employees"
|
||||
name="archivedemployees"
|
||||
domain="[('employee_id.active', '=', False)]"/>
|
||||
<group>
|
||||
<filter string="Employee" name="employee" context="{'group_by': 'employee_id'}"/>
|
||||
<filter string="Date" name="groupby_date" context="{'group_by': 'check_in'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_attendance_tree_management" model="ir.ui.view">
|
||||
<field name="name">hr.attendance.list</field>
|
||||
<field name="model">hr.attendance</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Employee attendances" create="0">
|
||||
<header>
|
||||
<button class="btn-secondary" string="Approve" name="action_approve_overtime" type="object"/>
|
||||
<button class="btn-secondary" string="Refuse" name="action_refuse_overtime" type="object"/>
|
||||
</header>
|
||||
<field name="employee_id" widget="many2one_avatar_employee" readonly="1"/>
|
||||
<field name="check_in" readonly="1"/>
|
||||
<field name="check_out" readonly="1"/>
|
||||
<field name="worked_hours" readonly="1" string="Worked Time" widget="float_time"/>
|
||||
<field name="overtime_hours" string="Worked Extra Hours" widget="float_time"/>
|
||||
<field name="validated_overtime_hours" readonly="overtime_status == 'refused'" string="Extra Hours" widget="float_time"/>
|
||||
<button
|
||||
class="oe_stat_button"
|
||||
string="Approve"
|
||||
invisible="not is_manager or overtime_status not in ['to_approve', 'refused']"
|
||||
groups="hr_attendance.group_hr_attendance_officer"
|
||||
name="action_approve_overtime"
|
||||
icon="fa-check"
|
||||
type="object"/>
|
||||
<button
|
||||
class="oe_stat_button"
|
||||
string="Refuse"
|
||||
invisible="not is_manager or overtime_status not in ['to_approve', 'approved']"
|
||||
groups="hr_attendance.group_hr_attendance_officer"
|
||||
name="action_refuse_overtime"
|
||||
icon="fa-times"
|
||||
type="object"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_management_action" model="ir.actions.act_window">
|
||||
<field name="name">Management</field>
|
||||
<field name="res_model">hr.attendance</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'create': False}</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="hr_attendance_management_view_filter"/>
|
||||
<field name="view_id" ref="view_attendance_tree_management"/>
|
||||
<field name="context">
|
||||
{
|
||||
"search_default_to_approve" : 1,
|
||||
"search_default_activeemployees": 1,
|
||||
}
|
||||
</field>
|
||||
<field name="domain">[('check_out', '!=', False)]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_empty_folder">
|
||||
No attendance records to display
|
||||
No attendance records found
|
||||
</p><p>
|
||||
The attendance records of your employees will be displayed here.
|
||||
The attendance reporting of your employees will be displayed here.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_action_overview" model="ir.actions.act_window">
|
||||
<field name="name">Attendances</field>
|
||||
<field name="res_model">hr.attendance</field>
|
||||
<field name="view_mode">tree</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>
|
||||
Your attendance records will be displayed here.
|
||||
</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>
|
||||
|
||||
<record model="ir.actions.server" id="open_kiosk_url">
|
||||
<field name="name">Open Kiosk Url</field>
|
||||
<field name="model_id" ref="hr_attendance.model_res_company"/>
|
||||
<field name="path">attendance-kiosk</field>
|
||||
<field name="binding_model_id" ref="hr_attendance.model_res_company"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">
|
||||
action = model._action_open_kiosk_mode()
|
||||
</field>
|
||||
<field name="group_ids" eval="[(4, ref('hr_attendance.group_hr_attendance_user'))]"/>
|
||||
</record>
|
||||
|
||||
<!-- Menus -->
|
||||
|
||||
<menuitem id="menu_hr_attendance_root" name="Attendances" sequence="205" groups="hr_attendance.group_hr_attendance,hr_attendance.group_hr_attendance_kiosk" web_icon="hr_attendance,static/description/icon.svg"/>
|
||||
<menuitem id="menu_hr_attendance_root" name="Attendances" sequence="205" groups="hr_attendance.group_hr_attendance_officer" 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_action_open_form" name="Kiosk Mode" action="open_kiosk_url" parent="menu_hr_attendance_root" sequence="10" groups="hr_attendance.group_hr_attendance_user"/>
|
||||
|
||||
<menuitem id="menu_hr_attendance_attendances_overview" name="Attendances" parent="menu_hr_attendance_root" sequence="1" groups="hr_attendance.group_hr_attendance" action="hr_attendance_action_overview"/>
|
||||
<menuitem
|
||||
id="menu_hr_attendance_reporting"
|
||||
name="Reporting"
|
||||
parent="menu_hr_attendance_root"
|
||||
sequence="15"
|
||||
groups="hr_attendance.group_hr_attendance_officer"/>
|
||||
|
||||
<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_attendance_reporting"
|
||||
name="Attendances"
|
||||
action="hr_attendance_reporting"
|
||||
parent="menu_hr_attendance_reporting"
|
||||
sequence="10"/>
|
||||
|
||||
<menuitem id="menu_hr_attendance_overview" name="Overview" parent="menu_hr_attendance_root" sequence="5" groups="hr_attendance.group_hr_attendance_officer"/>
|
||||
|
||||
<menuitem id="menu_hr_attendance_view_dashboard" name="Dashboard" action="hr_attendance_action" parent="menu_hr_attendance_overview" sequence="1"/>
|
||||
|
||||
<menuitem id="menu_hr_attendance_employee" name="Employees" parent="menu_hr_attendance_overview" action="hr.open_view_employee_list_my" groups="hr_attendance.group_hr_attendance_officer" sequence="2"/>
|
||||
|
||||
<menuitem id="menu_hr_attendance_view_attendances_management" name="Management" parent="menu_hr_attendance_root" sequence="6" groups="hr_attendance.group_hr_attendance_officer" action="hr_attendance_management_action"/>
|
||||
|
||||
<menuitem id="menu_hr_attendance_configuration" name="Configuration" parent="menu_hr_attendance_root" sequence="99" groups="hr_attendance.group_hr_attendance_manager"/>
|
||||
|
||||
<menuitem id="menu_hr_attendance_onboarding" name="Onboarding" action="action_try_kiosk" parent="menu_hr_attendance_configuration" sequence="100" groups="hr.group_hr_user"/>
|
||||
|
||||
<menuitem id="menu_hr_attendance_view_attendances" name="Attendances" parent="menu_hr_attendance_root" sequence="10" groups="hr_attendance.group_hr_attendance_user" action="hr_attendance_action"/>
|
||||
</odoo>
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@
|
|||
<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_report_action_filtered)d" type="action" groups="hr_attendance.group_hr_attendance_user">
|
||||
Attendances
|
||||
</a>
|
||||
<div role="menuitem">
|
||||
<a class="dropdown-item" name="%(hr_attendance_reporting)d" type="action" groups="hr_attendance.group_hr_attendance_officer">
|
||||
Attendances
|
||||
</a>
|
||||
</div>
|
||||
</xpath>
|
||||
</data>
|
||||
</field>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="hr_employee_public_view_form" model="ir.ui.view">
|
||||
<field name="name">hr.employee.public.form.inherit.attendance</field>
|
||||
<field name="model">hr.employee.public</field>
|
||||
<field name="inherit_id" ref="hr.hr_employee_public_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<button name="action_open_last_month_attendances"
|
||||
class="oe_stat_button"
|
||||
icon="fa-clock-o"
|
||||
type="object"
|
||||
groups="base.group_user"
|
||||
help="Worked hours this month"
|
||||
invisible="not is_user">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value">
|
||||
<field name="hours_last_month" widget="float_time"/>
|
||||
<span class="o_stat_value text-success" invisible="hours_last_month_overtime <= 0 or not display_extra_hours">
|
||||
(+<field name="hours_last_month_overtime" widget="float_time"/>)
|
||||
</span>
|
||||
<span class="o_stat_value text-danger" invisible="hours_last_month_overtime >= 0 or not display_extra_hours">
|
||||
(<field name="hours_last_month_overtime" widget="float_time"/>)
|
||||
</span>
|
||||
</span>
|
||||
<span class="o_stat_text">
|
||||
Monthly Hours
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -1,94 +1,64 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="hr_employee_search_view" model="ir.ui.view">
|
||||
<field name="name">hr.employee.search.view</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="inherit_id" ref="hr.view_employee_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//separator[@name='managers_groupby_separator']" position="before">
|
||||
<filter name="group_attendance_manager" string="Attendance Approver" context="{'group_by': 'attendance_manager_id'}" groups="hr_attendance.group_hr_attendance_user"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<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">110</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<button name="action_open_versions" position="before">
|
||||
<field name="attendance_state" invisible="1"/>
|
||||
<button name="%(hr_attendance_action)d"
|
||||
<field name="hours_last_month" groups="hr_attendance.group_hr_attendance_officer" invisible="1"/>
|
||||
<button name="action_open_last_month_attendances"
|
||||
class="oe_stat_button"
|
||||
icon="fa-clock-o"
|
||||
type="action"
|
||||
context="{'search_default_employee_id': id, 'search_default_check_in_filter': '1'}"
|
||||
groups="hr_attendance.group_hr_attendance_user"
|
||||
help="Worked hours last month">
|
||||
type="object"
|
||||
groups="hr_attendance.group_hr_attendance_officer"
|
||||
help="Worked hours this month">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value">
|
||||
<field name="hours_last_month_display" widget="float_time"/> Hours
|
||||
<field name="hours_last_month" widget="float_time"/>
|
||||
<span class="o_stat_value text-success" invisible="hours_last_month_overtime <= 0 or not display_extra_hours">
|
||||
(+<field name="hours_last_month_overtime" widget="float_time"/>)
|
||||
</span>
|
||||
<span class="o_stat_value text-danger" invisible="hours_last_month_overtime >= 0 or not display_extra_hours">
|
||||
(<field name="hours_last_month_overtime" widget="float_time"/>)
|
||||
</span>
|
||||
</span>
|
||||
<span class="o_stat_text">
|
||||
Last Month
|
||||
Monthly Hours
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button name="%(hr_attendance_overtime_action)d"
|
||||
class="oe_stat_button"
|
||||
icon="fa-history"
|
||||
type="action"
|
||||
attrs="{'invisible': [('total_overtime', '=', 0.0)]}"
|
||||
context="{'search_default_employee_id': active_id}"
|
||||
groups="hr_attendance.group_hr_attendance_user">
|
||||
<div class="o_stat_info">
|
||||
<span class="o_stat_value text-success" attrs="{'invisible': [('total_overtime', '<', 0)]}">
|
||||
<field name="total_overtime" widget="float_time"/>
|
||||
</span>
|
||||
<span class="o_stat_value text-danger" attrs="{'invisible': [('total_overtime', '>=', 0)]}">
|
||||
<field name="total_overtime" widget="float_time"/>
|
||||
</span>
|
||||
<span class="o_stat_text">Extra Hours</span>
|
||||
</div>
|
||||
</button>
|
||||
</button>
|
||||
<xpath expr="//group[@name='managers']" position="inside">
|
||||
<field name="attendance_manager_id" string="Attendance" widget="many2one_avatar_user" groups="hr_attendance.group_hr_attendance_user"/>
|
||||
</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="//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" widget="float_time"/> Hours
|
||||
</span>
|
||||
<span class="o_stat_text">
|
||||
Last Month
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<xpath expr="//field[@name='barcode']" position="attributes">
|
||||
<attribute name="string">RFID/Badge Number</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<button name="%(hr_attendance_overtime_action)d"
|
||||
class="oe_stat_button"
|
||||
icon="fa-history"
|
||||
type="action"
|
||||
attrs="{'invisible': [('total_overtime', '=', 0.0)]}"
|
||||
context="{'search_default_employee_id': employee_ids}"
|
||||
groups="base.group_user"
|
||||
help="Amount of extra hours">
|
||||
<div class="o_stat_info">
|
||||
<span class="o_stat_value text-success" attrs="{'invisible': [('total_overtime', '<', 0)]}">
|
||||
<field name="total_overtime" widget="float_time"/>
|
||||
</span>
|
||||
<span class="o_stat_value text-danger" attrs="{'invisible': [('total_overtime', '>=', 0)]}">
|
||||
<field name="total_overtime" widget="float_time"/>
|
||||
</span>
|
||||
<span class="o_stat_text">Extra Hours</span>
|
||||
</div>
|
||||
</button>
|
||||
<xpath expr="//button[@name='generate_random_barcode']" position="after">
|
||||
<button name="open_barcode_scanner" string="Read a badge" type="object" class="btn btn-link" invisible="barcode"/>
|
||||
</xpath>
|
||||
<!-- identification_group -->
|
||||
<group name="identification_group" position="inside">
|
||||
<field
|
||||
name="ruleset_id" string="Overtime Ruleset"
|
||||
placeholder="Select a ruleset to manage overtime."
|
||||
/>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
@ -98,37 +68,28 @@
|
|||
<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" action="action_employee_kiosk_confirm" type="object">
|
||||
<kanban create="false">
|
||||
<field name="attendance_state"/>
|
||||
<field name="hours_today"/>
|
||||
<field name="total_overtime"/>
|
||||
<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.public', 'avatar_128', record.id.raw_value)" alt="Employee"/>
|
||||
</div>
|
||||
<div class="oe_kanban_details">
|
||||
<div id="textbox">
|
||||
<t t-name="card" class="flex-row">
|
||||
<aside>
|
||||
<field name="avatar_128" widget="image" alt="Employee" class="mb-0"/>
|
||||
</aside>
|
||||
<main class="w-100 ms-2">
|
||||
<div>
|
||||
<div class="float-end" t-if="record.attendance_state.raw_value == 'checked_in'">
|
||||
<span id="oe_hr_attendance_status" class="fa fa-circle text-success me-1" role="img" aria-label="Available" title="Available"></span>
|
||||
<span class="fa fa-circle text-success me-1" role="img" aria-label="Available" title="Available"></span>
|
||||
</div>
|
||||
<div class="float-end" t-if="record.attendance_state.raw_value == 'checked_out'">
|
||||
<span id="oe_hr_attendance_status" class="fa fa-circle text-warning me-1"
|
||||
<span class="fa fa-circle text-warning me-1"
|
||||
role="img" aria-label="Not available" title="Not available">
|
||||
</span>
|
||||
</div>
|
||||
<strong>
|
||||
<field name="name"/>
|
||||
</strong>
|
||||
<field class="fw-bolder" name="name"/>
|
||||
</div>
|
||||
<ul>
|
||||
<li t-if="record.job_id.raw_value"><field name="job_id"/></li>
|
||||
<li t-if="record.work_location_id.raw_value"><field name="work_location_id"/></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<field t-if="record.job_id.raw_value" name="job_id"/>
|
||||
<field t-if="record.work_location_id.raw_value" name="work_location_id"/>
|
||||
</main>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
|
|
@ -151,4 +112,67 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_employee_tree_inherit_leave" model="ir.ui.view">
|
||||
<field name="name">hr.employee.list.leave</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="inherit_id" ref="hr.view_employee_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='work_location_id']" position="after">
|
||||
<field name="attendance_manager_id" optional="hide" widget="many2one_avatar_user" groups="hr_attendance.group_hr_attendance_user"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_employee_simple_tree_view" model="ir.ui.view">
|
||||
<field name="name">hr.attendance.list</field>
|
||||
<field name="model">hr.attendance</field>
|
||||
<field name="arch" type="xml">
|
||||
<list sample="1">
|
||||
<field name="check_in"/>
|
||||
<field name="check_out"/>
|
||||
<field name="worked_hours" string="Work Hours" widget="float_time"/>
|
||||
<field name="validated_overtime_hours" string="Extra Hours" widget="float_time" column_invisible="not context.get('display_extra_hours')"/>
|
||||
<field name="overtime_status" string="Status" widget="badge"
|
||||
decoration-warning="overtime_status == 'to_approve'"
|
||||
decoration-success="overtime_status == 'approved'"
|
||||
decoration-danger="overtime_status == 'refused'"
|
||||
column_invisible="not context.get('display_extra_hours')"
|
||||
optional="hide"
|
||||
/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_attendance_employee_simple_form_view" model="ir.ui.view">
|
||||
<field name="name">hr.attendance.form</field>
|
||||
<field name="model">hr.attendance</field>
|
||||
<field name="mode">primary</field>
|
||||
<field name="inherit_id" ref="hr_attendance.hr_attendance_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="overtime_status" position="attributes">
|
||||
<attribute name="readonly">1</attribute>
|
||||
</field>
|
||||
<xpath expr="//field[@id='employee_no_manager']" position="replace"/>
|
||||
<xpath expr="//field[@id='employee_manager']" position="replace"/>
|
||||
<xpath expr="//field[@id='employee_no_officer']" position="attributes">
|
||||
<attribute name="groups"/>
|
||||
</xpath>
|
||||
<field name="check_in" position="attributes">
|
||||
<attribute name="readonly">1</attribute>
|
||||
</field>
|
||||
<field name="check_out" position="attributes">
|
||||
<attribute name="readonly">1</attribute>
|
||||
</field>
|
||||
<field name="validated_overtime_hours" position="attributes">
|
||||
<attribute name="readonly">1</attribute>
|
||||
</field>
|
||||
<button name="action_approve_overtime" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</button>
|
||||
<button name="action_refuse_overtime" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
|
|||
|
|
@ -6,127 +6,87 @@
|
|||
<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 in Kiosk Mode</h2>
|
||||
<div class="row mt16 o_settings_container" name="kiosk_mode_setting_container">
|
||||
<div class="col-12 col-lg-6 o_setting_box">
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="attendance_kiosk_mode"/>
|
||||
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." role="img" aria-label="Values set here are company-specific." groups="base.group_multi_company"/>
|
||||
<div class="row">
|
||||
<div class="text-muted col-lg-10">
|
||||
Define the way the user will be identified by the application.
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-group">
|
||||
<div class="mt16">
|
||||
<field name="attendance_kiosk_mode" required="1" class="w-75"/>
|
||||
</div>
|
||||
</div>
|
||||
<xpath expr="//form" position="inside">
|
||||
<app data-string="Attendances" string="Attendances" name="hr_attendance" groups="hr_attendance.group_hr_attendance_manager">
|
||||
<block title="Modes" name="kiosk_mode_setting_container">
|
||||
<setting string="Kiosk Mode" company_dependent="1" help="Define the way the user will be identified by the application.">
|
||||
<field name="attendance_kiosk_mode" required="1" class="w-75"/>
|
||||
<div>
|
||||
<a href="https://www.odoo.com/documentation/latest/applications/hr/attendances/hardware.html"
|
||||
target="_blank"><i class="fa fa-fw fa-arrow-right"/>Installation Manual</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 o_setting_box">
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="attendance_kiosk_delay" string="Display Time"/>
|
||||
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." role="img" aria-label="Values set here are company-specific." groups="base.group_multi_company"/>
|
||||
<div class="row">
|
||||
<div class="text-muted col-lg-10">
|
||||
Choose how long the greeting message will be displayed.
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-group">
|
||||
<div class="mt16">
|
||||
<field name="attendance_kiosk_delay" required="1" class="text-center" style="width: 10%; min-width: 4rem;"/> seconds
|
||||
</div>
|
||||
</div>
|
||||
</setting>
|
||||
<setting string="Attendances from Backend" company_dependent="1" help="Allow Users to Check in/out from Odoo.">
|
||||
<field name="attendance_from_systray" required="1"/>
|
||||
</setting>
|
||||
<setting string="Automatic Check-Out" company_dependent="1" help="Automatically Check-Out Employees based on their working schedule with an additional tolerance. Does not apply to employees with a flexible working schedule.">
|
||||
<field name="auto_check_out"/>
|
||||
<div invisible="not auto_check_out">
|
||||
<span class="me-2">Tolerance</span><field name="auto_check_out_tolerance" class="text-center" style="width: 5ch;"/><span class="ms-2">Hours</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt16 o_settings_container" name="pincode_setting_container">
|
||||
<div class="col-12 col-lg-6 o_setting_box" attrs="{'invisible': [('attendance_kiosk_mode', '=', 'manual')]}">
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="attendance_barcode_source"/>
|
||||
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." role="img" aria-label="Values set here are company-specific." groups="base.group_multi_company"/>
|
||||
<div class="row">
|
||||
<div class="text-muted col-lg-10">
|
||||
Define the camera used for the barcode scan.
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-group">
|
||||
<div class="mt16">
|
||||
<field name="attendance_barcode_source" required="1"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 o_setting_box" title="Set PIN codes in the employee detail form (in HR Settings tab)." attrs="{'invisible': [('attendance_kiosk_mode', '=', 'barcode')]}">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="group_attendance_use_pin"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="group_attendance_use_pin"/>
|
||||
<div class="text-muted col-lg-10">
|
||||
Use PIN codes (defined on the Employee's profile) to check-in.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Extra Hours</h2>
|
||||
<div class="row mt16 o_settings_container" name="overtime_settings">
|
||||
<div class="col-12 col-lg-6 o_setting_box">
|
||||
<div class="o_setting_left_pane" title="Activate the count of employees' extra hours.">
|
||||
<field name="hr_attendance_overtime"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="hr_attendance_overtime" class="o_form_label">Count of Extra Hours</label>
|
||||
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." role="img" aria-label="Values set here are company-specific." groups="base.group_multi_company"/>
|
||||
</setting>
|
||||
<setting string="Absence Management" company_dependent="1" help="If checked, days not covered by an attendance will be visible in the Report. Does not apply to employees with a flexible working schedule.">
|
||||
<field name="absence_management"/>
|
||||
</setting>
|
||||
<setting string="Device & Location Tracking" company_dependent="1" help="Allow the collection of GPS location, IP address, and browser/device details used to track employee access and attendance">
|
||||
<field name="attendance_device_tracking"/>
|
||||
</setting>
|
||||
</block>
|
||||
<block title="Kiosk Settings">
|
||||
<setting invisible="attendance_kiosk_mode == 'manual'" company_dependent="1" help="Define the camera used for the barcode scan.">
|
||||
<field name="attendance_barcode_source" required="1"/>
|
||||
</setting>
|
||||
<setting string="Display Time" company_dependent="1" help="Choose how long the greeting message will be displayed.">
|
||||
<field name="attendance_kiosk_delay" required="1" class="text-center" style="width: 10%; min-width: 4rem;"/><span> seconds</span>
|
||||
</setting>
|
||||
<setting title="Set PIN codes in the employee detail form (in HR Settings tab)." invisible="attendance_kiosk_mode == 'barcode'" help="Use PIN codes (defined on the Employee's profile) to check-in.">
|
||||
<field name="attendance_kiosk_use_pin"/>
|
||||
</setting>
|
||||
<setting title="Kiosk Mode Adress" help="Use this url to access your kiosk mode from any device.">
|
||||
<field name="attendance_kiosk_url" class="o_hr_kiosk_url_media w-100" style="width:100% !important;" widget="CopyClipboardURL"/>
|
||||
<button name="regenerate_kiosk_key" type="object" string="Generate new URL" class="btn-link" icon="fa-refresh"/>
|
||||
</setting>
|
||||
</block>
|
||||
<block title="Extra Hours" name="overtime_settings">
|
||||
<!-- TODO: Remove the tolerance settings in master -->
|
||||
<setting company_dependent="1" invisible="1">
|
||||
<div class="mt16">
|
||||
<label for="overtime_company_threshold" class="o_form_label">
|
||||
Tolerance Time In Favor Of Company
|
||||
</label>
|
||||
<div class="text-muted">
|
||||
Compare attendance with working hours set on employee.
|
||||
Allow a period of time (around working hours) where extra time will not be counted, in benefit of the company
|
||||
</div>
|
||||
<div class="mt16" attrs="{'invisible': [('hr_attendance_overtime', '=', False)],
|
||||
'required': [('hr_attendance_overtime', '=', True)]}">
|
||||
<div class="mt16 row" title="Count of extra hours is considered from this date. Potential extra hours prior to this date are not considered.">
|
||||
<label for="overtime_start_date" string="Start from" class="col-3 col-lg-3 o_light_label"/>
|
||||
<field name="overtime_start_date" class="col-lg-3 p-0" attrs="{'required': [('hr_attendance_overtime', '=', True)]}" />
|
||||
</div>
|
||||
<br/>
|
||||
<label for="overtime_company_threshold" class="o_form_label">
|
||||
Tolerance Time In Favor Of Company
|
||||
</label>
|
||||
<div class="text-muted">
|
||||
Allow a period of time (around working hours) where extra time will not be counted, in benefit of the company
|
||||
</div>
|
||||
<span>Time Period </span><field name="overtime_company_threshold" class="text-center"
|
||||
attrs="{'required': [('hr_attendance_overtime', '=', True)]}" style="width: 10%; min-width: 4rem;"/><span> Minutes</span>
|
||||
<br/>
|
||||
<br/>
|
||||
<label for="overtime_employee_threshold" class="o_form_label">
|
||||
Tolerance Time In Favor Of Employee
|
||||
</label>
|
||||
<div class="text-muted">
|
||||
Allow a period of time (around working hours) where extra time will not be deducted, in benefit of the employee
|
||||
</div>
|
||||
<span>Time Period </span><field name="overtime_employee_threshold" class="text-center"
|
||||
attrs="{'required': [('hr_attendance_overtime', '=', True)]}" style="width: 10%; min-width: 4rem;"/><span> Minutes</span>
|
||||
<span class="me-2">Time Period</span><field name="overtime_company_threshold" class="text-center" style="width: 5ch;"/><span class="ms-2">Minutes</span>
|
||||
<br/>
|
||||
<br/>
|
||||
<label for="overtime_employee_threshold" class="o_form_label">
|
||||
Tolerance Time In Favor Of Employee
|
||||
</label>
|
||||
<div class="text-muted">
|
||||
Allow a period of time (around working hours) where extra time will not be deducted, in benefit of the employee
|
||||
</div>
|
||||
<span class="me-2">Time Period </span><field name="overtime_employee_threshold" class="text-center" style="width: 5ch;"/><span> Minutes</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</setting>
|
||||
<setting title="Display Extra Hours." string="Display Extra Hours" company_dependent="1" help="Display Extra Hours in Kiosk mode and on User profile.">
|
||||
<field name="hr_attendance_display_overtime"/>
|
||||
</setting>
|
||||
<setting title="Extra Hours Validation" string="Extra Hours Validation" company_dependent="1" help="Can be converted as Time Off (cfr Time Off configuration).">
|
||||
<field name="attendance_overtime_validation" widget="radio"/>
|
||||
</setting>
|
||||
</block>
|
||||
</app>
|
||||
</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"/>
|
||||
<menuitem id="menu_hr_attendance_settings" name="Settings" parent="menu_hr_attendance_configuration" sequence="10" action="action_hr_attendance_settings" groups="hr_attendance.group_hr_attendance_manager"/>
|
||||
</odoo>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue