Initial commit: Hr packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:50 +02:00
commit 62531cd146
2820 changed files with 1432848 additions and 0 deletions

View file

@ -0,0 +1,30 @@
/** @odoo-module */
import { CharField } from "@web/views/fields/char/char_field";
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
export class ApplicantCharField extends CharField {
setup() {
super.setup();
this.action = useService("action");
}
onClick() {
const record = this.props.record.data;
if (record.res_id !== undefined && record.res_model == 'hr.applicant') {
this.action.doAction({
type: 'ir.actions.act_window',
res_model: 'hr.applicant',
res_id: record.res_id,
views: [[false, "form"]],
view_mode: "form",
target: "current",
});
}
}
}
ApplicantCharField.template = "hr_recruitment.ApplicantCharField";
registry.category("fields").add("applicant_char", ApplicantCharField);

View file

@ -0,0 +1,7 @@
.o_field_applicant_char {
color: $link-color;
&:hover {
color: $link-hover-color;
}
}

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="hr_recruitment.ApplicantCharField" t-inherit="web.CharField" t-inherit-mode="primary" owl="1">
<xpath expr="//span[@t-esc='formattedValue']" position="attributes">
<attribute name="t-on-click.prevent.stop">onClick</attribute>
</xpath>
</t>
</templates>

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View file

@ -0,0 +1,109 @@
odoo.define('hr_recruitment.tour', function(require) {
"use strict";
const {_t} = require('web.core');
const {Markup} = require('web.utils');
var tour = require('web_tour.tour');
const { markup } = owl;
tour.register('hr_recruitment_tour',{
url: "/web",
rainbowManMessage: markup(_t("<div>Great job! You hired a new colleague!</div><div>Try the Website app to publish job offers online.</div>")),
fadeout: 'very_slow',
sequence: 230,
}, [tour.stepUtils.showAppsMenuItem(), {
trigger: '.o_app[data-menu-xmlid="hr_recruitment.menu_hr_recruitment_root"]',
content: Markup(_t("Let's have a look at how to <b>improve</b> your <b>hiring process</b>.")),
position: 'right',
edition: 'community'
}, {
trigger: '.o_app[data-menu-xmlid="hr_recruitment.menu_hr_recruitment_root"]',
content: Markup(_t("Let's have a look at how to <b>improve</b> your <b>hiring process</b>.")),
position: 'bottom',
edition: 'enterprise'
}, {
trigger: ".o-kanban-button-new",
content: _t("Create your first Job Position."),
position: "bottom",
width: 195
}, {
trigger: ".o_job_name",
extra_trigger: '.o_hr_job_simple_form',
content: _t("What do you want to recruit today? Choose a job title..."),
position: "right"
}, {
trigger: ".o_job_alias",
extra_trigger: '.o_hr_job_simple_form',
content: _t("Choose an application email."),
position: "right",
width: 195
}, {
trigger: '.o_create_job',
content: _t('Let\'s create the position. An email will be setup for applications, and a public job description, if you use the Website app.'),
position: 'bottom',
run: function (actions) {
actions.auto('.modal:visible .btn.btn-primary');
},
}, {
trigger: ".oe_kanban_action_button",
extra_trigger: '.o_hr_recruitment_kanban',
content: _t("Let\'s have a look at the applications pipeline."),
position: "bottom"
}, {
trigger: ".o_copy_paste_email",
content: _t("Copy this email address, to paste it in your email composer, to apply."),
position: "bottom"
}, {
trigger: ".breadcrumb-item:not(.active):last",
extra_trigger: '.o_kanban_applicant',
content: _t("Lets go back to the dashboard."),
position: "bottom",
width: 195
}, {
trigger: ".oe_kanban_action_button",
extra_trigger: '.o_hr_recruitment_kanban',
content: Markup(_t("<b>Did you apply by sending an email?</b> Check incoming applications.")),
position: "bottom"
}, {
trigger: ".oe_kanban_card",
extra_trigger: '.o_kanban_applicant',
content: Markup(_t("<b>Drag this card</b>, to qualify him for a first interview.")),
position: "bottom",
run: "drag_and_drop .o_kanban_group:eq(1) ",
}, {
trigger: ".oe_kanban_card",
extra_trigger: '.o_kanban_applicant',
content: Markup(_t("<b>Click to view</b> the application.")),
position: "bottom",
width: 195
}, {
trigger: ".o_Chatter .o_ChatterTopbar_buttonSendMessage",
extra_trigger: '.o_applicant_form',
content: Markup(_t("<div><b>Try to send an email</b> to the applicant.</div><div><i>Tips: All emails sent or received are saved in the history here</i>")),
position: "bottom"
}, {
trigger: ".o_Chatter .o_Composer_buttonSend",
extra_trigger: '.o_applicant_form',
content: _t("Send your email. Followers will get a copy of the communication."),
position: "bottom"
}, {
trigger: ".o_Chatter .o_ChatterTopbar_buttonLogNote",
extra_trigger: '.o_applicant_form',
content: _t("Or talk about this applicant privately with your colleagues."),
position: "bottom"
}, {
trigger: ".o_create_employee",
extra_trigger: '.o_applicant_form',
content: _t("Lets create this new employee now."),
position: "bottom",
width: 225
}, {
trigger: ".o_form_button_save",
extra_trigger: ".o_employee_form",
content: _t("Save it !"),
position: "bottom",
width: 80
}]);
});

View file

@ -0,0 +1,22 @@
.o_applicant_interviewer_form {
.o_ChatterTopbar_buttonSendMessage,
.o_ChatterTopbar_buttonLogNote,
.o_MessageList_empty {
display: none;
}
}
.o_applicant_form {
&.o_form_readonly {
.o_field_empty:empty {
min-height: unset;
}
}
&.o_form_editable {
.oe_title {
max-width: unset;
}
}
}

View file

@ -0,0 +1,108 @@
.o_kanban_renderer.o_kanban_dashboard {
&.o_hr_recruitment_kanban {
&.o_kanban_ungrouped .o_kanban_record {
width: 450px;
&:not(.o_kanban_ghost) {
min-height: 220px;
}
}
.ribbon {
&::before, &::after {
display: none;
}
span {
padding: 5px;
font-size: small;
z-index: unset;
height: auto;
}
}
.ribbon-top-right {
margin-top: -$o-kanban-dashboard-vpadding;
span {
left: 0px;
right: 30px;
}
}
.text_top_padding{
padding-top: 0.375rem;
}
.o_primary {
display: flex !important;
align-items: center;
justify-content: space-between;
padding-right: 24px !important;
.fa {
margin-left: 0;
}
}
.o_job_activities {
list-style-type: none;
.to-recruit {
color: $o-enterprise-color;
font-weight: bold;
}
}
.o_kanban_card_header_title {
min-height: 3rem;
.o_field_boolean_favorite {
display: inline;
}
}
}
}
.o_kanban_renderer {
&.o_kanban_applicant {
.ribbon {
&::before, &::after {
display: none;
}
span {
padding: 5px;
font-size: x-small;
z-index: unset;
height: auto;
}
}
.ribbon-top-right {
margin-top: -$o-kanban-dashboard-vpadding;
span {
top: 10px;
left: 20px;
}
}
}
}
.o_kanban_view {
.oe_kanban_card {
.o_kanban_state_with_padding {
padding-left:7%;
padding-bottom:5%;
width: 12px;
}
}
.o_view_sample_data .ribbon {
display: none;
}
}
.o_recruitment_list {
.o_list_button {
text-align: right;
}
}

View file

@ -0,0 +1,29 @@
/** @odoo-module */
import { registry } from '@web/core/registry';
import { formView } from '@web/views/form/form_view';
import { FormController } from '@web/views/form/form_controller';
import { session } from '@web/session';
export class InterviewerFormController extends FormController {
/**
* Add `o_applicant_interviewer_form` class if necessary
*/
get className() {
const result = super.className;
const root = this.model.root;
if (!root.data.interviewer_ids || !root.data.user_id) {
return result;
}
result["o_applicant_interviewer_form"] = root.data.interviewer_ids.records.findIndex(
interviewer => interviewer.data.id === session.uid) > -1;
return result;
}
}
registry.category('views').add('hr_recruitment_interviewer', {
...formView,
Controller: InterviewerFormController,
});