[IMP] hr_holidays: allow quick approval on dashboard
Purpose: HR can view employee leave records from the calendar but can not approve, validate or refuse it from there. In case they want to make action, they have to go through menu < time off < approvals < time off < find the employee < find the requested time off < open it < approve. In this commit the action buttons are added on the dashboard. task - 3175495 closes odoo/odoo#116342 Signed-off-by: Kevin Baptiste <kba@odoo.com>
This commit is contained in:
@@ -1207,10 +1207,12 @@ class HolidaysRequest(models.Model):
|
||||
self.activity_update()
|
||||
return True
|
||||
|
||||
def action_approve(self):
|
||||
def action_approve(self, check_state=True):
|
||||
# if validation_type == 'both': this method is the first approval approval
|
||||
# if validation_type != 'both': this method calls action_validate() below
|
||||
if any(holiday.state != 'confirm' for holiday in self):
|
||||
|
||||
# Do not check the state in case we are redirected from the dashboard
|
||||
if check_state and any(holiday.state != 'confirm' for holiday in self):
|
||||
raise UserError(_('Time off request must be confirmed ("To Approve") in order to approve it.'))
|
||||
|
||||
current_employee = self.env.user.employee_id
|
||||
|
||||
@@ -104,6 +104,7 @@ export class TimeOffCalendarController extends CalendarController {
|
||||
onRecordSaved: onDialogClosed,
|
||||
onRecordDeleted: (record) => this.deleteRecord(record),
|
||||
onLeaveCancelled: onDialogClosed,
|
||||
size: 'md',
|
||||
},
|
||||
{ onClose: () => resolve() }
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { FormViewDialog } from "@web/views/view_dialogs/form_view_dialog";
|
||||
|
||||
import { registry } from '@web/core/registry';
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
import { formView } from '@web/views/form/form_view';
|
||||
import { FormController } from '@web/views/form/form_controller';
|
||||
@@ -13,23 +14,43 @@ export class TimeOffDialogFormController extends FormController {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.leaveCancelWizard = useLeaveCancelWizard();
|
||||
this.orm = useService("orm");
|
||||
}
|
||||
|
||||
get record() {
|
||||
return this.model.root.data;
|
||||
}
|
||||
|
||||
async onClick(action) {
|
||||
const args = (action === 'action_approve') ? [this.record.id, false] : [this.record.id];
|
||||
await this.orm.call("hr.leave", action, args);
|
||||
this.props.onLeaveUpdated();
|
||||
}
|
||||
|
||||
get canApprove() {
|
||||
return !this.model.root.isNew && (this.record.can_approve && ['confirm', 'refuse',].includes(this.record.state));
|
||||
}
|
||||
|
||||
get canValidate() {
|
||||
return !this.model.root.isNew && (this.record.can_approve && this.record.state === 'validate1');
|
||||
}
|
||||
|
||||
get canRefuse() {
|
||||
return !this.model.root.isNew && (this.record.can_approve && this.record.state && ['confirm', 'validate1', 'validate'].includes(this.record.state));
|
||||
}
|
||||
|
||||
deleteRecord() {
|
||||
const record = this.model.root.data
|
||||
|
||||
this.props.onRecordDeleted(record)
|
||||
this.props.onRecordDeleted(this.record)
|
||||
this.props.onCancelLeave();
|
||||
if (record.can_cancel) {
|
||||
this.leaveCancelWizard(record.id, () => {
|
||||
if (this.record.can_cancel) {
|
||||
this.leaveCancelWizard(this.record.id, () => {
|
||||
this.props.onLeaveCancelled();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get canDelete() {
|
||||
const record = this.model.root.data;
|
||||
return !this.model.root.isNew && (record.can_cancel || record.state && !['validate', 'refuse'].includes(record.state));
|
||||
return !this.model.root.isNew && (this.record.can_cancel || this.record.state && !['validate', 'refuse'].includes(this.record.state));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +59,7 @@ TimeOffDialogFormController.props = {
|
||||
onCancelLeave: Function,
|
||||
onRecordDeleted: Function,
|
||||
onLeaveCancelled: Function,
|
||||
onLeaveUpdated: Function,
|
||||
}
|
||||
|
||||
registry.category('views').add('timeoff_dialog_form', {
|
||||
@@ -56,6 +78,10 @@ export class TimeOffFormViewDialog extends FormViewDialog {
|
||||
onCancelLeave: () => {
|
||||
this.props.close();
|
||||
},
|
||||
onLeaveUpdated: () => {
|
||||
this.props.onRecordSaved();
|
||||
this.props.close();
|
||||
},
|
||||
onRecordDeleted: (record) => {
|
||||
this.props.onRecordDeleted(record)
|
||||
},
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
<xpath expr="//button[contains(@class, 'o_form_button_cancel')]" position="after">
|
||||
<button class="btn btn-secondary" t-if="canDelete" t-on-click="deleteRecord" data-hotkey="x">Delete</button>
|
||||
</xpath>
|
||||
<xpath expr="//div[contains(@class, 'o_cp_buttons')]" position="after">
|
||||
<div class="flex-grow-1 d-flex flex-row-reverse">
|
||||
<button class="btn btn-secondary" t-if="canRefuse" t-on-click="() => this.onClick('action_refuse')" data-hotkey="z">Refuse</button>
|
||||
<button class="btn btn-secondary" t-if="canApprove" t-on-click="() => this.onClick('action_approve')" data-hotkey="g">Approve</button>
|
||||
<button class="btn btn-secondary" t-if="canValidate" t-on-click="() => this.onClick('action_validate')" data-hotkey="v">Validate</button>
|
||||
<div/>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -353,6 +353,9 @@
|
||||
<xpath expr="//group[@name='col_left']" position="attributes">
|
||||
<attribute name="colspan">5</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//div[hasclass('o_hr_leave_column')]" position="attributes">
|
||||
<attribute name="class" remove="col_left col-md-6" separator=" "/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user