[IMP] holiday: improve UX holiday timeoff
-Display the state of a time off that you open from the dashboard
-Rename Stress Days into "Mandatory Days"
-My Allocations
Remove "Employee" from the Group By
Replace filter `Current Year` with `Currently Valid`.
-My Time Off
-Remove Employees from list view and kanban view
-Create an allocation / allocation request form
- Create an allocation ux : employee side- compute the name of the allocation.
- Make field `allocation_type` invisible if there is no active accrual plan in the database.
-Accruals
-Add an "archive" in the action menu of the accrual plan.
-Show Employee button in the form view of the Accrual Plan.
-Renamed stress day into the mandatory days.
-Renamed string of the menu Approval into the Management.
-Remove two legends in the time-off Dashboard
- Public Holiday
- Mandatory Day
task-3084232
closes odoo/odoo#116472
Related: odoo/enterprise#40576
Related: odoo/upgrade#4472
Signed-off-by: Sofie Gvaladze (sgv) <sgv@odoo.com>
This commit is contained in:
committed by
Prakash Prajapati
parent
d98c0af075
commit
1b512efdac
@@ -40,7 +40,7 @@ A synchronization with an internal agenda (Meetings of the CRM module) is also p
|
||||
'views/hr_leave_type_views.xml',
|
||||
'views/hr_leave_allocation_views.xml',
|
||||
'views/hr_leave_accrual_views.xml',
|
||||
'views/hr_leave_stress_day_views.xml',
|
||||
'views/hr_leave_mandatory_day_views.xml',
|
||||
'views/mail_activity_views.xml',
|
||||
|
||||
'wizard/hr_holidays_cancel_leave_views.xml',
|
||||
|
||||
@@ -478,8 +478,8 @@
|
||||
<field name="date_to" eval="(datetime.today() + relativedelta(days=+8)).strftime('%Y-%m-%d 17:00:00')"></field>
|
||||
</record>
|
||||
|
||||
<!-- Stress day -->
|
||||
<record id="hr_leave_stress_day_1" model="hr.leave.stress.day">
|
||||
<!-- Mandatory day -->
|
||||
<record id="hr_leave_mandatory_day_1" model="hr.leave.mandatory.day">
|
||||
<field name="name">Company Celebration</field>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="start_date" eval="(datetime.today() + relativedelta(days=+7)).strftime('%Y-%m-%d 07:00:00')"></field>
|
||||
|
||||
@@ -10,7 +10,7 @@ from . import hr_leave_allocation
|
||||
from . import hr_leave_type
|
||||
from . import hr_leave_accrual_plan_level
|
||||
from . import hr_leave_accrual_plan
|
||||
from . import hr_leave_stress_day
|
||||
from . import hr_leave_mandatory_day
|
||||
from . import mail_message_subtype
|
||||
from . import res_partner
|
||||
from . import res_users
|
||||
|
||||
@@ -273,23 +273,23 @@ class HrEmployee(models.Model):
|
||||
def _is_leave_user(self):
|
||||
return self == self.env.user.employee_id and self.user_has_groups('hr_holidays.group_hr_holidays_user')
|
||||
|
||||
def get_stress_days(self, start_date, end_date):
|
||||
def get_mandatory_days(self, start_date, end_date):
|
||||
all_days = {}
|
||||
|
||||
self = self or self.env.user.employee_id
|
||||
|
||||
stress_days = self._get_stress_days(start_date, end_date)
|
||||
for stress_day in stress_days:
|
||||
num_days = (stress_day.end_date - stress_day.start_date).days
|
||||
mandatory_days = self._get_mandatory_days(start_date, end_date)
|
||||
for mandatory_day in mandatory_days:
|
||||
num_days = (mandatory_day.end_date - mandatory_day.start_date).days
|
||||
for d in range(num_days + 1):
|
||||
all_days[str(stress_day.start_date + relativedelta(days=d))] = stress_day.color
|
||||
all_days[str(mandatory_day.start_date + relativedelta(days=d))] = mandatory_day.color
|
||||
|
||||
return all_days
|
||||
|
||||
@api.model
|
||||
def get_special_days_data(self, date_start, date_end):
|
||||
return {
|
||||
'stressDays': self.get_stress_days_data(date_start, date_end),
|
||||
'mandatoryDays': self.get_mandatory_days_data(date_start, date_end),
|
||||
'bankHolidays': self.get_public_holidays_data(date_start, date_end),
|
||||
}
|
||||
|
||||
@@ -328,9 +328,9 @@ class HrEmployee(models.Model):
|
||||
return self.env['resource.calendar.leaves'].search(domain)
|
||||
|
||||
@api.model
|
||||
def get_stress_days_data(self, date_start, date_end):
|
||||
def get_mandatory_days_data(self, date_start, date_end):
|
||||
self = self._get_contextual_employee()
|
||||
stress_days = self._get_stress_days(date_start, date_end).sorted('start_date')
|
||||
mandatory_days = self._get_mandatory_days(date_start, date_end).sorted('start_date')
|
||||
return list(map(lambda sd: {
|
||||
'id': -sd.id,
|
||||
'colorIndex': sd.color,
|
||||
@@ -340,16 +340,16 @@ class HrEmployee(models.Model):
|
||||
'start': datetime.datetime.combine(sd.start_date, datetime.datetime.min.time()).isoformat(),
|
||||
'startType': "datetime",
|
||||
'title': sd.name,
|
||||
}, stress_days))
|
||||
}, mandatory_days))
|
||||
|
||||
def _get_stress_days(self, start_date, end_date):
|
||||
def _get_mandatory_days(self, start_date, end_date):
|
||||
domain = [
|
||||
('start_date', '<=', end_date),
|
||||
('end_date', '>=', start_date),
|
||||
('company_id', 'in', self.env.companies.ids),
|
||||
]
|
||||
|
||||
# a user with hr_holidays permissions will be able to see all stress days from his calendar
|
||||
# a user with hr_holidays permissions will be able to see all mandatory days from his calendar
|
||||
if not self._is_leave_user():
|
||||
domain += [
|
||||
'|',
|
||||
@@ -365,4 +365,4 @@ class HrEmployee(models.Model):
|
||||
else:
|
||||
domain += [('department_ids', '=', False)]
|
||||
|
||||
return self.env['hr.leave.stress.day'].search(domain)
|
||||
return self.env['hr.leave.mandatory.day'].search(domain)
|
||||
|
||||
@@ -300,7 +300,7 @@ class HolidaysRequest(models.Model):
|
||||
# view
|
||||
is_hatched = fields.Boolean('Hatched', compute='_compute_is_hatched')
|
||||
is_striked = fields.Boolean('Striked', compute='_compute_is_hatched')
|
||||
has_stress_day = fields.Boolean(compute='_compute_has_stress_day')
|
||||
has_mandatory_day = fields.Boolean(compute='_compute_has_mandatory_day')
|
||||
|
||||
_sql_constraints = [
|
||||
('type_value',
|
||||
@@ -473,10 +473,10 @@ class HolidaysRequest(models.Model):
|
||||
holiday.department_id = False
|
||||
|
||||
@api.depends('date_from', 'date_to', 'holiday_status_id')
|
||||
def _compute_has_stress_day(self):
|
||||
def _compute_has_mandatory_day(self):
|
||||
date_from, date_to = min(self.mapped('date_from')), max(self.mapped('date_to'))
|
||||
if date_from and date_to:
|
||||
stress_days = self.employee_id._get_stress_days(
|
||||
mandatory_days = self.employee_id._get_mandatory_days(
|
||||
date_from.date(),
|
||||
date_to.date())
|
||||
|
||||
@@ -491,9 +491,9 @@ class HolidaysRequest(models.Model):
|
||||
|
||||
if leave.holiday_status_id.company_id:
|
||||
domain += [('company_id', '=', leave.holiday_status_id.company_id.id)]
|
||||
leave.has_stress_day = leave.date_from and leave.date_to and stress_days.filtered_domain(domain)
|
||||
leave.has_mandatory_day = leave.date_from and leave.date_to and mandatory_days.filtered_domain(domain)
|
||||
else:
|
||||
self.has_stress_day = False
|
||||
self.has_mandatory_day = False
|
||||
|
||||
@api.depends('date_from', 'date_to', 'employee_id')
|
||||
def _compute_number_of_days(self):
|
||||
@@ -862,10 +862,10 @@ class HolidaysRequest(models.Model):
|
||||
self.message_subscribe(partner_ids=employee.user_id.partner_id.ids)
|
||||
|
||||
@api.constrains('date_from', 'date_to')
|
||||
def _check_stress_day(self):
|
||||
def _check_mandatory_day(self):
|
||||
is_leave_user = self.user_has_groups('hr_holidays.group_hr_holidays_user')
|
||||
if not is_leave_user and any(leave.has_stress_day for leave in self):
|
||||
raise ValidationError(_('You are not allowed to request a time off on a Stress Day.'))
|
||||
if not is_leave_user and any(leave.has_mandatory_day for leave in self):
|
||||
raise ValidationError(_('You are not allowed to request a time off on a Mandatory Day.'))
|
||||
|
||||
def _check_double_validation_rules(self, employees, state):
|
||||
if self.user_has_groups('hr_holidays.group_hr_holidays_manager'):
|
||||
|
||||
@@ -8,6 +8,7 @@ class AccrualPlan(models.Model):
|
||||
_name = "hr.leave.accrual.plan"
|
||||
_description = "Accrual Plan"
|
||||
|
||||
active = fields.Boolean(default=True)
|
||||
name = fields.Char('Name', required=True)
|
||||
time_off_type_id = fields.Many2one('hr.leave.type', string="Time Off Type",
|
||||
check_company=True,
|
||||
|
||||
@@ -9,7 +9,7 @@ import logging
|
||||
from datetime import datetime, time
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.addons.resource.models.utils import HOURS_PER_DAY
|
||||
from odoo.addons.hr_holidays.models.hr_leave import get_employee_from_context
|
||||
from odoo.exceptions import AccessError, UserError, ValidationError
|
||||
@@ -136,6 +136,7 @@ class HolidaysAllocation(models.Model):
|
||||
max_leaves = fields.Float(compute='_compute_leaves')
|
||||
leaves_taken = fields.Float(compute='_compute_leaves', string='Time off Taken')
|
||||
taken_leave_ids = fields.One2many('hr.leave', 'holiday_allocation_id', domain="[('state', 'in', ['confirm', 'validate1', 'validate'])]")
|
||||
has_accrual_plan = fields.Boolean(compute='_compute_has_accrual_plan', string='Accrual Plan Available')
|
||||
|
||||
_sql_constraints = [
|
||||
('type_value',
|
||||
@@ -168,7 +169,14 @@ class HolidaysAllocation(models.Model):
|
||||
|
||||
for allocation in self:
|
||||
if is_officer or allocation.employee_id.user_id == self.env.user or allocation.employee_id.leave_manager_id == self.env.user:
|
||||
allocation.name = allocation.sudo().private_name
|
||||
title = allocation.sudo().private_name
|
||||
if allocation.env.context.get('is_employee_allocation'):
|
||||
allocation_duration = allocation.number_of_days_display if allocation.type_request_unit != 'hour' else allocation.number_of_hours_display
|
||||
title = _(" %s Allocation Request ( %s %s)" % (
|
||||
allocation.holiday_status_id.name,
|
||||
allocation_duration,
|
||||
allocation.type_request_unit))
|
||||
allocation.name = title
|
||||
else:
|
||||
allocation.name = '*****'
|
||||
|
||||
@@ -188,6 +196,10 @@ class HolidaysAllocation(models.Model):
|
||||
allocations = self.sudo().search(domain)
|
||||
return [('id', 'in', allocations.ids)]
|
||||
|
||||
@api.depends('accrual_plan_id')
|
||||
def _compute_has_accrual_plan(self):
|
||||
self.has_accrual_plan = bool(self.env['hr.leave.accrual.plan'].sudo().search_count([('active', '=', True)]))
|
||||
|
||||
@api.depends('name', 'date_from', 'date_to')
|
||||
def _compute_description_validity(self):
|
||||
for allocation in self:
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@ from random import randint
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class StressDay(models.Model):
|
||||
_name = 'hr.leave.stress.day'
|
||||
_description = 'Stress Day'
|
||||
class MandatoryDay(models.Model):
|
||||
_name = 'hr.leave.mandatory.day'
|
||||
_description = 'Mandatory Day'
|
||||
_order = 'start_date desc, end_date desc'
|
||||
|
||||
name = fields.Char(required=True)
|
||||
@@ -249,9 +249,9 @@
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_leave_stress_day_rule_multi_company" model="ir.rule">
|
||||
<field name="name">Stress Day: multi company rule</field>
|
||||
<field name="model_id" ref="model_hr_leave_stress_day"/>
|
||||
<record id="hr_leave_mandatory_day_rule_multi_company" model="ir.rule">
|
||||
<field name="name">Mandatory Day: multi company rule</field>
|
||||
<field name="model_id" ref="model_hr_leave_mandatory_day"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -22,5 +22,5 @@ access_hr_leave_accrual_level_user,hr.leave.accrual.level.user,model_hr_leave_ac
|
||||
access_hr_leave_accrual_plan_manager,hr.leave.accrual.plan.manager,model_hr_leave_accrual_plan,hr_holidays.group_hr_holidays_manager,1,1,1,1
|
||||
access_hr_leave_accrual_level_manager,hr.leave.accrual.level.manager,model_hr_leave_accrual_level,hr_holidays.group_hr_holidays_manager,1,1,1,1
|
||||
access_hr_holidays_cancel_leave,access_hr_holidays_cancel_leave,hr_holidays.model_hr_holidays_cancel_leave,base.group_user,1,1,1,1
|
||||
access_hr_leave_stress_day_user,access_hr_holidays_stress_day_user,hr_holidays.model_hr_leave_stress_day,base.group_user,1,0,0,0
|
||||
access_hr_leave_stress_day_manager,access_hr_holidays_stress_day_manager,hr_holidays.model_hr_leave_stress_day,hr_holidays.group_hr_holidays_manager,1,1,1,1
|
||||
access_hr_leave_mandatory_day_user,access_hr_holidays_mandatory_day_user,hr_holidays.model_hr_leave_mandatory_day,base.group_user,1,0,0,0
|
||||
access_hr_leave_mandatory_day_manager,access_hr_holidays_mandatory_day_manager,hr_holidays.model_hr_leave_mandatory_day,hr_holidays.group_hr_holidays_manager,1,1,1,1
|
||||
|
||||
|
@@ -63,7 +63,7 @@
|
||||
<li>Allocated: <span t-esc="props.allocated"/></li>
|
||||
<li>Approved: <span t-esc="props.approved"/></li>
|
||||
<li style="border-bottom: 1px solid gray;">Planned: <span t-esc="props.planned"/></li>
|
||||
<li>Left: <span t-esc="props.left"/></li>
|
||||
<li>Available: <span t-esc="props.left"/></li>
|
||||
</ul>
|
||||
</t>
|
||||
</Popover>
|
||||
|
||||
@@ -62,7 +62,7 @@ registry.category("web_tour.tours").add('hr_holidays_tour', {
|
||||
position: 'bottom',
|
||||
},
|
||||
{
|
||||
trigger: 'button[data-menu-xmlid="hr_holidays.menu_hr_holidays_approvals"]',
|
||||
trigger: 'button[data-menu-xmlid="hr_holidays.menu_hr_holidays_management"]',
|
||||
content: _t("Let's go validate it"),
|
||||
position: 'bottom'
|
||||
},
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
</button>
|
||||
<Dropdown togglerClass="'btn btn-primary'" showCaret="true" class="'btn-group'">
|
||||
<button class="btn btn-link" t-on-click="newAllocationRequest" type="button">
|
||||
New Allocation Request
|
||||
<t t-if="employeeId">Grant Time</t>
|
||||
<t t-else="">New Allocation Request</t>
|
||||
</button>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@ export class TimeOffCalendarModel extends CalendarModel {
|
||||
setup(params, services) {
|
||||
super.setup(params, services);
|
||||
|
||||
this.data.stressDays = {};
|
||||
this.data.mandatoryDays = {};
|
||||
if (this.env.isSmall) {
|
||||
this.meta.scale = 'month';
|
||||
}
|
||||
@@ -46,7 +46,7 @@ export class TimeOffCalendarModel extends CalendarModel {
|
||||
async updateData(data) {
|
||||
await super.updateData(data);
|
||||
|
||||
data.stressDays = await this.fetchStressDays(data);
|
||||
data.mandatoryDays = await this.fetchMandatoryDays(data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,16 +64,16 @@ export class TimeOffCalendarModel extends CalendarModel {
|
||||
});
|
||||
}
|
||||
|
||||
async fetchStressDays(data) {
|
||||
return this.orm.call("hr.employee", "get_stress_days", [
|
||||
async fetchMandatoryDays(data) {
|
||||
return this.orm.call("hr.employee", "get_mandatory_days", [
|
||||
this.employeeId,
|
||||
serializeDate(data.range.start, "datetime"),
|
||||
serializeDate(data.range.end, "datetime"),
|
||||
]);
|
||||
}
|
||||
|
||||
get stressDays() {
|
||||
return this.data.stressDays;
|
||||
get mandatoryDays() {
|
||||
return this.data.mandatoryDays;
|
||||
}
|
||||
|
||||
get employeeId() {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
@for $size from 1 through length($o-colors) {
|
||||
.o_calendar_widget {
|
||||
.hr_stress_day_top_#{$size - 1}:not(.fc-disabled-day) {
|
||||
.hr_mandatory_day_top_#{$size - 1}:not(.fc-disabled-day) {
|
||||
.fc-day-number {
|
||||
color: nth($o-colors, $size) !important;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
|
||||
import { CalendarCommonRenderer } from '@web/views/calendar/calendar_common/calendar_common_renderer';
|
||||
|
||||
import { useStressDays } from '../../hooks';
|
||||
import { useMandatoryDays } from '../../hooks';
|
||||
import { TimeOffCalendarCommonPopover } from './calendar_common_popover';
|
||||
|
||||
|
||||
export class TimeOffCalendarCommonRenderer extends CalendarCommonRenderer {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.stressDays = useStressDays(this.props);
|
||||
this.mandatoryDays = useMandatoryDays(this.props);
|
||||
}
|
||||
|
||||
onDayRender(info) {
|
||||
super.onDayRender(info);
|
||||
this.stressDays(info);
|
||||
this.mandatoryDays(info);
|
||||
}
|
||||
}
|
||||
TimeOffCalendarCommonRenderer.components = {
|
||||
|
||||
@@ -17,7 +17,7 @@ export class TimeOffCalendarFilterPanel extends CalendarFilterPanel {
|
||||
this.getFormattedDateSpan = getFormattedDateSpan;
|
||||
this.leaveState = useState({
|
||||
holidays: [],
|
||||
stressDays: [],
|
||||
mandatoryDays: [],
|
||||
bankHolidays: [],
|
||||
});
|
||||
|
||||
@@ -45,12 +45,12 @@ export class TimeOffCalendarFilterPanel extends CalendarFilterPanel {
|
||||
bankHoliday.start = luxon.DateTime.fromISO(bankHoliday.start)
|
||||
bankHoliday.end = luxon.DateTime.fromISO(bankHoliday.end)
|
||||
});
|
||||
specialDays['stressDays'].forEach(stressDay => {
|
||||
stressDay.start = luxon.DateTime.fromISO(stressDay.start)
|
||||
stressDay.end = luxon.DateTime.fromISO(stressDay.end)
|
||||
specialDays['mandatoryDays'].forEach(mandatoryDay => {
|
||||
mandatoryDay.start = luxon.DateTime.fromISO(mandatoryDay.start)
|
||||
mandatoryDay.end = luxon.DateTime.fromISO(mandatoryDay.end)
|
||||
});
|
||||
this.leaveState.bankHolidays = specialDays['bankHolidays'];
|
||||
this.leaveState.stressDays = specialDays['stressDays'];
|
||||
this.leaveState.mandatoryDays = specialDays['mandatoryDays'];
|
||||
}
|
||||
|
||||
async loadFilterData() {
|
||||
|
||||
+2
-2
@@ -31,13 +31,13 @@
|
||||
background-color: $gray-200;
|
||||
}
|
||||
|
||||
&_stressday {
|
||||
&_mandatoryday {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
@for $size from 1 through length($o-colors) {
|
||||
.hr_stress_day_#{$size - 1}:not(.fc-disabled-day) {
|
||||
.hr_mandatory_day_#{$size - 1}:not(.fc-disabled-day) {
|
||||
color: nth($o-colors, $size) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,18 +10,16 @@
|
||||
<span><img class="o_calendar_filter_plain" src="/hr/static/src/img/icons/plain.svg"/> Validated</span>
|
||||
<span><img class="o_calendar_filter_hatched" src="/hr/static/src/img/icons/hatched.svg"/> To Approve</span>
|
||||
<span><img class="o_calendar_filter_line" src="/hr/static/src/img/icons/line.svg"/> Refused</span>
|
||||
<span><span class="o_timeoff_legend o_timeoff_legend_bankholiday">13</span> Public Holiday</span>
|
||||
<span><span class="o_timeoff_legend o_timeoff_legend_stressday text-odoo">13</span> Stress Day</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column mt-4" t-if="leaveState.stressDays.length">
|
||||
<h5>Stress Days</h5>
|
||||
<div class="d-flex flex-column mt-4" t-if="leaveState.mandatoryDays.length">
|
||||
<h5>Mandatory Days</h5>
|
||||
<ul class="ps-2">
|
||||
<li t-foreach="leaveState.stressDays" t-as="stressDay" t-key="stressDay.id" class="mt-2 list-unstyled">
|
||||
<li t-foreach="leaveState.mandatoryDays" t-as="mandatoryDay" t-key="mandatoryDay.id" class="mt-2 list-unstyled">
|
||||
<strong
|
||||
t-esc="getFormattedDateSpan(stressDay.start, stressDay.end)"
|
||||
t-att-class="'hr_stress_day_'+stressDay.colorIndex"/>
|
||||
: <t t-esc="stressDay.title"/>
|
||||
t-esc="getFormattedDateSpan(mandatoryDay.start, mandatoryDay.end)"
|
||||
t-att-class="'hr_mandatory_day_'+mandatoryDay.colorIndex"/>
|
||||
: <t t-esc="mandatoryDay.title"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -9,5 +9,5 @@ TimeOffCalendarYearPopover.components = { Dialog };
|
||||
TimeOffCalendarYearPopover.template = "web.CalendarYearPopover";
|
||||
TimeOffCalendarYearPopover.subTemplates = {
|
||||
...CalendarYearPopover.subTemplates,
|
||||
body: "hr_holidays.StressDayCalendarYearPopover.body",
|
||||
body: "hr_holidays.MandatoryDayCalendarYearPopover.body",
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="hr_holidays.StressDayCalendarYearPopover.body" owl="1">
|
||||
<t t-name="hr_holidays.MandatoryDayCalendarYearPopover.body" owl="1">
|
||||
<t t-foreach="recordGroups" t-as="recordGroup" t-key="recordGroup.title">
|
||||
<div class="fw-bold mt-2" t-esc="recordGroup.title" />
|
||||
<t t-foreach="recordGroup.records" t-as="record" t-key="record.id">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { CalendarYearRenderer } from '@web/views/calendar/calendar_year/calendar_year_renderer';
|
||||
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { useStressDays } from '../../hooks';
|
||||
import { useMandatoryDays } from '../../hooks';
|
||||
import { useCalendarPopover } from '@web/views/calendar/hooks';
|
||||
import { TimeOffCalendarYearPopover } from './calendar_year_popover';
|
||||
|
||||
@@ -13,9 +13,9 @@ export class TimeOffCalendarYearRenderer extends CalendarYearRenderer {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.orm = useService("orm");
|
||||
this.stressDays = useStressDays(this.props);
|
||||
this.stressDaysList = [];
|
||||
this.stressDayPopover = useCalendarPopover(TimeOffCalendarYearPopover);
|
||||
this.mandatoryDays = useMandatoryDays(this.props);
|
||||
this.mandatoryDaysList = [];
|
||||
this.mandatoryDayPopover = useCalendarPopover(TimeOffCalendarYearPopover);
|
||||
|
||||
useEffect((el) => {
|
||||
for (const week of el) {
|
||||
@@ -41,23 +41,23 @@ export class TimeOffCalendarYearRenderer extends CalendarYearRenderer {
|
||||
|
||||
/** @override **/
|
||||
async onDateClick(info) {
|
||||
const is_stress_day = [...info.dayEl.classList].some(elClass => elClass.startsWith('hr_stress_day_'))
|
||||
this.stressDayPopover.close();
|
||||
if (is_stress_day && !this.env.isSmall) {
|
||||
const is_mandatory_day = [...info.dayEl.classList].some(elClass => elClass.startsWith('hr_mandatory_day_'))
|
||||
this.mandatoryDayPopover.close();
|
||||
if (is_mandatory_day && !this.env.isSmall) {
|
||||
this.popover.close();
|
||||
const date = luxon.DateTime.fromISO(info.dateStr);
|
||||
const target = info.dayEl;
|
||||
const stress_days_data = await this.orm.call("hr.employee", "get_stress_days_data", [date, date]);
|
||||
stress_days_data.forEach(stress_day_data => {
|
||||
stress_day_data['start'] = luxon.DateTime.fromISO(stress_day_data['start'])
|
||||
stress_day_data['end'] = luxon.DateTime.fromISO(stress_day_data['end'])
|
||||
const mandatory_days_data = await this.orm.call("hr.employee", "get_mandatory_days_data", [date, date]);
|
||||
mandatory_days_data.forEach(mandatory_day_data => {
|
||||
mandatory_day_data['start'] = luxon.DateTime.fromISO(mandatory_day_data['start'])
|
||||
mandatory_day_data['end'] = luxon.DateTime.fromISO(mandatory_day_data['end'])
|
||||
});
|
||||
const records = Object.values(this.props.model.records).filter((r) =>
|
||||
luxon.Interval.fromDateTimes(r.start.startOf("day"), r.end.endOf("day")).contains(date)
|
||||
);
|
||||
const props = this.getPopoverProps(date, records)
|
||||
props['records'] = stress_days_data.concat(props['records'])
|
||||
this.stressDayPopover.open(target, props, "o_cw_popover");
|
||||
props['records'] = mandatory_days_data.concat(props['records'])
|
||||
this.mandatoryDayPopover.open(target, props, "o_cw_popover");
|
||||
}
|
||||
else {
|
||||
super.onDateClick(info);
|
||||
@@ -66,6 +66,6 @@ export class TimeOffCalendarYearRenderer extends CalendarYearRenderer {
|
||||
|
||||
onDayRender(info) {
|
||||
super.onDayRender(info);
|
||||
this.stressDaysList = this.stressDays(info);
|
||||
this.mandatoryDaysList = this.mandatoryDays(info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,21 +4,21 @@ import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
const { useEnv } = owl;
|
||||
|
||||
export function useStressDays(props) {
|
||||
export function useMandatoryDays(props) {
|
||||
return (info) => {
|
||||
const date = luxon.DateTime.fromJSDate(info.date).toISODate();
|
||||
const stressDay = props.model.stressDays[date];
|
||||
if (stressDay) {
|
||||
const mandatoryDay = props.model.mandatoryDays[date];
|
||||
if (mandatoryDay) {
|
||||
const dayNumberElTop = info.view.el.querySelector(`.fc-day-top[data-date="${info.el.dataset.date }"]`)
|
||||
const dayNumberEl = info.view.el.querySelector(`.fc-day[data-date="${info.el.dataset.date }"]`)
|
||||
if (dayNumberElTop) {
|
||||
dayNumberElTop.classList.add(`hr_stress_day_top_${stressDay}`);
|
||||
dayNumberElTop.classList.add(`hr_mandatory_day_top_${mandatoryDay}`);
|
||||
}
|
||||
if (dayNumberEl) {
|
||||
dayNumberEl.classList.add(`hr_stress_day_${stressDay}`);
|
||||
dayNumberEl.classList.add(`hr_mandatory_day_${mandatoryDay}`);
|
||||
}
|
||||
}
|
||||
return props.model.stressDays;
|
||||
return props.model.mandatoryDays;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ from . import test_leave_requests
|
||||
from . import test_out_of_office
|
||||
from . import test_company_leave
|
||||
from . import test_res_partner
|
||||
from . import test_stress_days
|
||||
from . import test_mandatory_days
|
||||
from . import test_global_leaves
|
||||
from . import test_uninstall
|
||||
from . import test_holidays_calendar
|
||||
|
||||
@@ -71,8 +71,8 @@ class TestHrHolidaysAccessRightsCommon(TestHrHolidaysCommon):
|
||||
]
|
||||
|
||||
# Here we only test access rights, prevent any conflict with
|
||||
# existing stress days - they are tested someplace else.
|
||||
cls.env['hr.leave.stress.day'].search([]).unlink()
|
||||
# existing mandatory days - they are tested someplace else.
|
||||
cls.env['hr.leave.mandatory.day'].search([]).unlink()
|
||||
|
||||
def request_leave(self, user_id, date_from, number_of_days, values=None):
|
||||
values = dict(values or {}, **{
|
||||
|
||||
+20
-20
@@ -11,7 +11,7 @@ from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
@tests.tagged('access_rights', 'post_install', '-at_install')
|
||||
class TestHrLeaveStressDays(TransactionCase):
|
||||
class TestHrLeaveMandatoryDays(TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
@@ -47,7 +47,7 @@ class TestHrLeaveStressDays(TransactionCase):
|
||||
'company_id': cls.company.id,
|
||||
})
|
||||
|
||||
cls.stress_day = cls.env['hr.leave.stress.day'].create({
|
||||
cls.mandatory_day = cls.env['hr.leave.mandatory.day'].create({
|
||||
'name': 'Super Event',
|
||||
'company_id': cls.company.id,
|
||||
'start_date': datetime(2021, 11, 2),
|
||||
@@ -55,7 +55,7 @@ class TestHrLeaveStressDays(TransactionCase):
|
||||
'color': 1,
|
||||
'resource_calendar_id': cls.default_calendar.id,
|
||||
})
|
||||
cls.stress_week = cls.env['hr.leave.stress.day'].create({
|
||||
cls.mandatory_week = cls.env['hr.leave.mandatory.day'].create({
|
||||
'name': 'Super Event End Of Week',
|
||||
'company_id': cls.company.id,
|
||||
'start_date': datetime(2021, 11, 8),
|
||||
@@ -65,8 +65,8 @@ class TestHrLeaveStressDays(TransactionCase):
|
||||
})
|
||||
|
||||
@freeze_time('2021-10-15')
|
||||
def test_request_stress_days(self):
|
||||
# An employee can request time off outside stress days
|
||||
def test_request_mandatory_days(self):
|
||||
# An employee can request time off outside mandatory days
|
||||
self.env['hr.leave'].with_user(self.employee_user.id).create({
|
||||
'name': 'coucou',
|
||||
'holiday_status_id': self.leave_type.id,
|
||||
@@ -76,7 +76,7 @@ class TestHrLeaveStressDays(TransactionCase):
|
||||
'number_of_days': 1,
|
||||
})
|
||||
|
||||
# Taking a time off during a Stress Day is not allowed for a simple employee...
|
||||
# Taking a time off during a Mandatory Day is not allowed for a simple employee...
|
||||
with self.assertRaises(ValidationError):
|
||||
self.env['hr.leave'].with_user(self.employee_user.id).create({
|
||||
'name': 'coucou',
|
||||
@@ -108,28 +108,28 @@ class TestHrLeaveStressDays(TransactionCase):
|
||||
})
|
||||
|
||||
@freeze_time('2021-10-15')
|
||||
def test_get_stress_days(self):
|
||||
stress_days = self.employee_emp.get_stress_days('2021-11-01', '2021-11-30')
|
||||
def test_get_mandatory_days(self):
|
||||
mandatory_days = self.employee_emp.get_mandatory_days('2021-11-01', '2021-11-30')
|
||||
|
||||
# Stress Days spanning multiple days should be split in single days
|
||||
# Mandatory Days spanning multiple days should be split in single days
|
||||
expected_data = {'2021-11-02': 1, '2021-11-08': 2, '2021-11-09': 2, '2021-11-10': 2, '2021-11-11': 2, '2021-11-12': 2}
|
||||
|
||||
self.assertEqual(len(stress_days), len(expected_data))
|
||||
self.assertEqual(len(mandatory_days), len(expected_data))
|
||||
for day, color in expected_data.items():
|
||||
self.assertTrue(day in stress_days)
|
||||
self.assertEqual(color, stress_days[day])
|
||||
self.assertTrue(day in mandatory_days)
|
||||
self.assertEqual(color, mandatory_days[day])
|
||||
|
||||
with self.assertRaises(ValidationError), Form(self.env['hr.leave'].with_user(self.employee_user.id).with_context(default_employee_id=self.employee_emp.id)) as leave_form:
|
||||
leave_form.holiday_status_id = self.leave_type
|
||||
leave_form.request_date_from = datetime(2021, 11, 1)
|
||||
leave_form.request_date_to = datetime(2021, 11, 1)
|
||||
self.assertFalse(leave_form.has_stress_day)
|
||||
self.assertFalse(leave_form.has_mandatory_day)
|
||||
|
||||
leave_form.request_date_to = datetime(2021, 11, 5)
|
||||
self.assertTrue(leave_form.has_stress_day)
|
||||
self.assertTrue(leave_form.has_mandatory_day)
|
||||
|
||||
@freeze_time('2021-10-15')
|
||||
def test_department_stress_days(self):
|
||||
def test_department_mandatory_days(self):
|
||||
production_department = self.env['hr.department'].create({
|
||||
'name': 'Production Department',
|
||||
'company_id': self.company.id,
|
||||
@@ -149,8 +149,8 @@ class TestHrLeaveStressDays(TransactionCase):
|
||||
'department_id': post_production_department.id
|
||||
})
|
||||
|
||||
# Create one stress day for each department
|
||||
self.env['hr.leave.stress.day'].create({
|
||||
# Create one mandatory day for each department
|
||||
self.env['hr.leave.mandatory.day'].create({
|
||||
'name': 'Last Rush Before Launch (production)',
|
||||
'company_id': self.company.id,
|
||||
'start_date': datetime(2021, 11, 3),
|
||||
@@ -159,7 +159,7 @@ class TestHrLeaveStressDays(TransactionCase):
|
||||
'resource_calendar_id': self.default_calendar.id,
|
||||
'department_ids': [production_department.id],
|
||||
})
|
||||
self.env['hr.leave.stress.day'].create({
|
||||
self.env['hr.leave.mandatory.day'].create({
|
||||
'name': 'Last Rush Before Launch (post-production)',
|
||||
'company_id': self.company.id,
|
||||
'start_date': datetime(2021, 11, 4),
|
||||
@@ -168,7 +168,7 @@ class TestHrLeaveStressDays(TransactionCase):
|
||||
'resource_calendar_id': self.default_calendar.id,
|
||||
'department_ids': [post_production_department.id],
|
||||
})
|
||||
self.env['hr.leave.stress.day'].create({
|
||||
self.env['hr.leave.mandatory.day'].create({
|
||||
'name': 'Last Rush Before Launch (deployment)',
|
||||
'company_id': self.company.id,
|
||||
'start_date': datetime(2021, 11, 5),
|
||||
@@ -178,7 +178,7 @@ class TestHrLeaveStressDays(TransactionCase):
|
||||
'department_ids': [deployment_department.id],
|
||||
})
|
||||
|
||||
# The employee should only be able to create a time off on stress days
|
||||
# The employee should only be able to create a time off on mandatory days
|
||||
# that do not include his department
|
||||
with self.assertRaises(ValidationError):
|
||||
self.env['hr.leave'].with_user(self.employee_user.id).create({
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_my_leaves"
|
||||
name="My Time Off"
|
||||
name="My Time"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="1"/>
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
action="action_hr_holidays_dashboard"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_approvals"
|
||||
name="Approvals"
|
||||
id="menu_hr_holidays_management"
|
||||
name="Management"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="3"
|
||||
groups="hr_holidays.group_hr_holidays_responsible"/>
|
||||
@@ -50,14 +50,14 @@
|
||||
<menuitem
|
||||
id="menu_open_department_leave_approve"
|
||||
name="Time Off"
|
||||
parent="menu_hr_holidays_approvals"
|
||||
parent="menu_hr_holidays_management"
|
||||
action="hr_leave_action_action_approve_department"
|
||||
sequence="1"/>
|
||||
|
||||
<menuitem
|
||||
id="hr_holidays_menu_manager_approve_allocations"
|
||||
name="Allocations"
|
||||
parent="menu_hr_holidays_approvals"
|
||||
parent="menu_hr_holidays_management"
|
||||
action="hr_leave_allocation_action_approve_department"
|
||||
sequence="2"/>
|
||||
|
||||
@@ -114,9 +114,9 @@
|
||||
sequence="3"/>
|
||||
|
||||
<menuitem
|
||||
id="hr_holidays_stress_day_menu_configuration"
|
||||
action="hr_leave_stress_day_action"
|
||||
name="Stress Days"
|
||||
id="hr_holidays_mandatory_day_menu_configuration"
|
||||
action="hr_leave_mandatory_day_action"
|
||||
name="Mandatory Days"
|
||||
parent="menu_hr_holidays_configuration"
|
||||
groups="hr_holidays.group_hr_holidays_manager"
|
||||
sequence="4"/>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</div>
|
||||
<label for="frequency"/>
|
||||
<div class="o_col">
|
||||
<field name="frequency"/>
|
||||
<field name="frequency" class="w-25"/>
|
||||
<div class="o_row" attrs="{'invisible': [('frequency', '!=', 'weekly')]}">
|
||||
<label for="week_day" string="on"/><field name="week_day"/>
|
||||
</div>
|
||||
@@ -51,8 +51,8 @@
|
||||
<field name="added_value_type" nolabel="1" readonly="1" force_save="1"/>
|
||||
</div>
|
||||
</div>
|
||||
<field name="action_with_unused_accruals" style="width: 40%"/>
|
||||
<field name="postpone_max_days" attrs="{'invisible': [('action_with_unused_accruals', '!=', 'postponed')]}"/>
|
||||
<field name="action_with_unused_accruals" class="w-25"/>
|
||||
<field name="postpone_max_days" class="w-25" attrs="{'invisible': [('action_with_unused_accruals', '!=', 'postponed')]}"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
@@ -75,13 +75,15 @@
|
||||
<field name="model">hr.leave.accrual.plan</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Accrual Plan">
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="show_transition_mode" invisible="1" />
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box" attrs="{'invisible': [('id', '=', False)]}">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_open_accrual_plan_employees" type="object" class="oe_stat_button" icon="fa-users">
|
||||
<field name="employees_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
@@ -200,6 +202,7 @@
|
||||
<field name="model">hr.leave.accrual.plan</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Group By">
|
||||
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
|
||||
<filter string="Time Off Type" name='time_off_type_id' context="{'group_by':'time_off_type_id'}"/>
|
||||
<filter string="Company" name='company_id' context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
</search>
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
<filter domain="[('state', '=', 'confirm')]" string="To Approve" name="second_approval"/>
|
||||
<filter string="Approved" domain="[('state', '=', 'validate')]" name="validated"/>
|
||||
<separator/>
|
||||
<filter name="year" string="Current Year"
|
||||
<filter name="year" string="Currently Valid"
|
||||
domain="[
|
||||
('date_from', '>=', context_today().strftime('%Y-1-1')),
|
||||
('date_from', '<=', context_today().strftime('%Y-12-31')),
|
||||
('date_from', '<=', context_today().strftime('%Y-%m-%d')),
|
||||
'|',
|
||||
('date_to', '=', False),
|
||||
('date_to', '>=', context_today().strftime('%Y-%m-%d')),
|
||||
]"
|
||||
help="Active Allocations"/>
|
||||
<separator/>
|
||||
@@ -75,15 +77,16 @@
|
||||
<div class="oe_button_box" name="button_box">
|
||||
</div>
|
||||
<div id="title" class="oe_title">
|
||||
<h2><field name="name" class="w-100" placeholder="e.g. Time Off type (From validity start to validity end / no limit)" attrs="{'invisible': [('state', 'not in', ('draft', 'confirm'))]}" required="1"/>
|
||||
<h2><field name="name" class="w-100" placeholder="e.g. Time Off type (From validity start to validity end / no limit)" attrs="{'invisible': [('state', 'not in', ('draft', 'confirm'))], 'readonly': True}"/>
|
||||
<field name="name_validity" attrs="{'invisible': [('state', 'in', ('draft', 'confirm'))]}"/></h2>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="type_request_unit" invisible="1"/>
|
||||
<field name="has_accrual_plan" invisible="1"/>
|
||||
<field name="holiday_status_id" context="{'employee_id':employee_id, 'default_date_from':current_date, 'request_type':'allocation'}"/>
|
||||
<field name="allocation_type" invisible="1" widget="radio"
|
||||
attrs="{'readonly': ['|', ('is_officer', '=', False), ('state', 'not in', ('draft', 'confirm'))]}"/>
|
||||
attrs="{'readonly': ['|', ('is_officer', '=', False), ('state', 'not in', ('draft', 'confirm'))], 'invisible': [('has_accrual_plan', '=', False)]}"/>
|
||||
<field name="is_officer" invisible="1"/>
|
||||
<field name="accrual_plan_id" attrs="{'invisible': [('allocation_type', '=', 'regular')], 'readonly': ['|', ('is_officer', '=', False), ('state', 'not in', ('draft', 'confirm'))]}"/>
|
||||
<div class="o_td_label" name="validity_label">
|
||||
@@ -100,7 +103,7 @@
|
||||
|
||||
<field name="number_of_days" invisible="1"/>
|
||||
<div class="o_td_label">
|
||||
<label for="number_of_days_display" string="Duration"
|
||||
<label for="number_of_days_display" string="Amount"
|
||||
attrs="{'readonly': [('allocation_type', '=', 'accrual'), ('state', 'not in', ('draft', 'confirm'))]}"/>
|
||||
</div>
|
||||
<div name="duration_display">
|
||||
@@ -247,7 +250,7 @@
|
||||
<field name="department_id" optional="hide"/>
|
||||
<field name="holiday_status_id" class="fw-bold"/>
|
||||
<field name="name"/>
|
||||
<field name="duration_display" string="Duration"/>
|
||||
<field name="duration_display" string="Amount"/>
|
||||
<field name="date_from" string="Validity Start" optional="hide"/>
|
||||
<field name="date_to" string="Validity Stop" optional="hide"/>
|
||||
<field name="allocation_type"/>
|
||||
@@ -309,6 +312,18 @@
|
||||
<xpath expr="//filter[@name='my_leaves']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='active_employee']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='active_types']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='inactive']" position="attributes">
|
||||
<attribute name="string">Archived Time Off Type</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='group_employee']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -416,7 +431,7 @@
|
||||
Employees request allocations to Time Off Officers (e.g. recuperation days).
|
||||
</p>
|
||||
</field>
|
||||
<field name="context">{}</field>
|
||||
<field name="context">{'search_default_year': 1 , 'is_employee_allocation': True}</field>
|
||||
<field name="domain">[('employee_id.user_id', '=', uid)]</field>
|
||||
</record>
|
||||
<record id="hr_leave_allocation_action_my_view_tree" model="ir.actions.act_window.view">
|
||||
|
||||
+17
-14
@@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<odoo>
|
||||
<record id="hr_leave_stress_day_view_form" model="ir.ui.view">
|
||||
<field name="model">hr.leave.stress.day</field>
|
||||
<record id="hr_leave_mandatory_day_view_form" model="ir.ui.view">
|
||||
<field name="model">hr.leave.mandatory.day</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
@@ -21,41 +21,44 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_leave_stress_day_view_list" model="ir.ui.view">
|
||||
<field name="model">hr.leave.stress.day</field>
|
||||
<record id="hr_leave_mandatory_day_view_list" model="ir.ui.view">
|
||||
<field name="model">hr.leave.mandatory.day</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="bottom">
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="company_id" groups="base.group_multi_company" optional="hide"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="department_ids" widget="many2many_tags" optional="hide"/>
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
<field name="color" widget="color_picker"/>
|
||||
<field name="department_ids" widget="many2many_tags"/>
|
||||
<field name="resource_calendar_id" optional="hide"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_leave_stress_day_view_search" model="ir.ui.view">
|
||||
<field name="model">hr.leave.stress.day</field>
|
||||
<record id="hr_leave_mandatory_day_view_search" model="ir.ui.view">
|
||||
<field name="model">hr.leave.mandatory.day</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Stress Days">
|
||||
<search string="Mandatory Day">
|
||||
<field name="name"/>
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<separator />
|
||||
<filter name="filter_date" date="start_date" default_period="this_year" string="Period"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="department" string="Department" context="{'group_by': 'department_ids'}"/>
|
||||
<filter name="company" string="Company" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_leave_stress_day_action" model="ir.actions.act_window">
|
||||
<field name="name">Stress Days</field>
|
||||
<field name="res_model">hr.leave.stress.day</field>
|
||||
<record id="hr_leave_mandatory_day_action" model="ir.actions.act_window">
|
||||
<field name="name">Mandatory Days</field>
|
||||
<field name="res_model">hr.leave.mandatory.day</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="hr_leave_stress_day_view_search"/>
|
||||
<field name="search_view_id" ref="hr_leave_mandatory_day_view_search"/>
|
||||
<field name="context">{'search_default_filter_date': True}</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -213,7 +213,7 @@
|
||||
<field name="can_approve" invisible="1"/>
|
||||
<field name="can_cancel" invisible="1"/>
|
||||
<field name="holiday_allocation_id" invisible="1" force_save="1"/>
|
||||
<field name="has_stress_day" invisible="1"/>
|
||||
<field name="has_mandatory_day" invisible="1"/>
|
||||
<header>
|
||||
<button string="Confirm" name="action_confirm" type="object" class="oe_highlight" attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('active', '=', False)]}"/>
|
||||
<button string="Approve" name="action_approve" type="object" class="oe_highlight" attrs="{'invisible': ['|', '|', ('active', '=', False), ('can_approve', '=', False), ('state', '!=', 'confirm')]}"/>
|
||||
@@ -358,6 +358,10 @@
|
||||
<xpath expr="//div[hasclass('o_hr_leave_column')]" position="attributes">
|
||||
<attribute name="class" remove="col_left col-md-6" separator=" "/>
|
||||
</xpath>
|
||||
<xpath expr="//sheet/widget[@name='web_ribbon']" position="after">
|
||||
<widget name="web_ribbon" title="Refused" bg_color="bg-danger" attrs="{'invisible': ['|', ('state', '!=', 'refuse'), ('id', '=', False)]}"/>
|
||||
<widget name="web_ribbon" title="Approved" bg_color="bg-success" attrs="{'invisible': ['|', ('state', '!=', 'validate'), ('id', '=', False)]}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -524,6 +528,9 @@
|
||||
<field name="mode">primary</field>
|
||||
<field name="priority">32</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='all_employee_ids']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='employee_id']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
@@ -636,6 +643,18 @@
|
||||
<field name="view_id" ref="hr_leave_view_form_dashboard_new_time_off"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_leave_view_kanban_my" model="ir.ui.view">
|
||||
<field name="name">hr.leave.view.kanban.my</field>
|
||||
<field name="inherit_id" ref="hr_leave_view_kanban"/>
|
||||
<field name="mode">primary</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="arch" type="xml">
|
||||
<strong class="o_kanban_record_title" position='attributes'>
|
||||
<attribute name="invisible">1</attribute>
|
||||
</strong>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_leave_action_my" model="ir.actions.act_window">
|
||||
<field name="name">My Time Off</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
@@ -643,7 +662,7 @@
|
||||
<field name="context">{}</field>
|
||||
<field name="search_view_id" ref="hr_leave_view_search_my"/>
|
||||
<field name="view_ids" eval="[(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'kanban', 'view_id': ref('hr_leave_view_kanban')})]"/>
|
||||
(0, 0, {'view_mode': 'kanban', 'view_id': ref('hr_leave_view_kanban_my')})]"/>
|
||||
<field name="domain">[('user_id', '=', uid), ('employee_company_id', 'in', allowed_company_ids)]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Resource" name="resource" domain="[]" context="{'group_by':'resource_id'}"/>
|
||||
<filter string="Company" name="company" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<filter string="Time Off Date" name="leave_month" domain="[]" context="{'group_by':'date_from'}" help="Starting Date of Time Off"/>
|
||||
<filter string="Date" name="leave_month" domain="[]" context="{'group_by':'date_from'}" help="Starting Date of Time Off"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
@@ -63,7 +63,7 @@
|
||||
<tree string="Time Off Detail">
|
||||
<field name="name" string="Reason"/>
|
||||
<field name="resource_id" />
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="company_id" groups="base.group_multi_company" optional="hide"/>
|
||||
<field name="calendar_id"/>
|
||||
<field name="date_from" />
|
||||
<field name="date_to" />
|
||||
|
||||
Reference in New Issue
Block a user